#!/bin/bash # Copper Tone Technologies - Comprehensive Security & Code Audit Script # Run this script from the project root directory set -e AUDIT_DIR="docs/audits/$(date +%Y%m%d-%H%M%S)" mkdir -p "$AUDIT_DIR" echo "===========================================" echo "COPPER TONE TECHNOLOGIES - SECURITY AUDIT" echo "===========================================" echo "Date: $(date)" echo "Output directory: $AUDIT_DIR" echo "" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_fail() { echo -e "${RED}[FAIL]${NC} $1"; } log_info() { echo -e "[INFO] $1"; } # ==== SECTION 1: DEPENDENCY AUDIT ==== echo "" echo "============================================" echo "SECTION 1: DEPENDENCY VULNERABILITIES" echo "============================================" # 1.1 Frontend pnpm audit echo "" echo "1.1 Frontend PNPM Audit..." podman run --rm -v "$(pwd)/frontend:/app:Z" -w /app node:lts sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm audit --json" > "$AUDIT_DIR/pnpm-audit.json" 2>/dev/null || true podman run --rm -v "$(pwd)/frontend:/app:Z" -w /app node:lts sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm audit" 2>&1 | tee "$AUDIT_DIR/pnpm-audit.txt" || true if grep -q '"vulnerabilities": {}' "$AUDIT_DIR/pnpm-audit.json" 2>/dev/null; then log_pass "No pnpm vulnerabilities found" else log_warn "PNPM vulnerabilities detected - see $AUDIT_DIR/pnpm-audit.txt" fi # 1.2 Go module verification echo "" echo "1.2 Go Module Verification..." for service in auth-service work-management-service payment-service blog-service; do if [ -d "backend/functions/$service" ]; then echo " Checking $service..." podman run --rm -v "$(pwd)/backend/functions/$service:/app:Z" -w /app golang:1.25-alpine go mod verify 2>&1 | tee -a "$AUDIT_DIR/go-verify.txt" fi done log_pass "Go modules verified" # ==== SECTION 2: SECRET SCANNING ==== echo "" echo "============================================" echo "SECTION 2: SECRET SCANNING" echo "============================================" echo "2.1 Scanning for hardcoded secrets..." { echo "=== Potential Secrets Found ===" grep -rn --include="*.ts" --include="*.js" --include="*.go" --include="*.vue" \ -E "(password|secret|api_key|apikey|token|credential).*=.*['\"][^'\"]{8,}['\"]" \ --exclude-dir=node_modules --exclude-dir=.git . 2>/dev/null || echo "No obvious hardcoded secrets found" echo "" echo "=== .env files found ===" find . -name "*.env" -o -name ".env*" 2>/dev/null | grep -v node_modules || echo "No .env files found" echo "" echo "=== Private keys or certificates ===" find . -name "*.pem" -o -name "*.key" -o -name "*.p12" 2>/dev/null | grep -v node_modules || echo "No private key files found" } | tee "$AUDIT_DIR/secrets-scan.txt" # Check for secrets in git history echo "" echo "2.2 Checking for secrets in recent git commits..." git log --oneline -20 --diff-filter=A -- "*.env" "*.pem" "*.key" "*secret*" 2>/dev/null | tee "$AUDIT_DIR/git-secrets-check.txt" || true # ==== SECTION 3: CONTAINER SECURITY ==== echo "" echo "============================================" echo "SECTION 3: CONTAINER SECURITY" echo "============================================" echo "3.1 Running containers..." podman ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" | tee "$AUDIT_DIR/running-containers.txt" echo "" echo "3.2 Container image scan (using Trivy if available)..." if command -v trivy &> /dev/null; then for image in $(podman images --format "{{.Repository}}:{{.Tag}}" | grep coppertone); do echo "Scanning $image..." trivy image "$image" --severity HIGH,CRITICAL 2>&1 | tee -a "$AUDIT_DIR/trivy-scan.txt" done else log_warn "Trivy not installed - skipping container vulnerability scan" echo "Install with: podman run --rm aquasec/trivy image " fi echo "" echo "3.3 Checking container user privileges..." { echo "=== Container Users ===" for container in $(podman ps --format "{{.Names}}"); do user=$(podman exec "$container" whoami 2>/dev/null || echo "unknown") echo "$container: running as $user" if [ "$user" = "root" ]; then log_warn "$container runs as root" fi done } | tee "$AUDIT_DIR/container-users.txt" # ==== SECTION 4: CODE QUALITY ==== echo "" echo "============================================" echo "SECTION 4: CODE QUALITY" echo "============================================" echo "4.1 TypeScript type checking..." podman run --rm -v "$(pwd)/frontend:/app:Z" -w /app node:lts sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install --frozen-lockfile && pnpm run type-check" 2>&1 | tee "$AUDIT_DIR/typescript-check.txt" || log_warn "TypeScript errors found" echo "" echo "4.2 ESLint check..." podman run --rm -v "$(pwd)/frontend:/app:Z" -w /app node:lts sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install --frozen-lockfile && pnpm exec eslint src/ --max-warnings 0" 2>&1 | tee "$AUDIT_DIR/eslint-check.txt" || log_warn "ESLint warnings/errors found" echo "" echo "4.3 Go vet check..." for service in auth-service work-management-service payment-service; do if [ -d "backend/functions/$service" ]; then echo " Checking $service..." podman run --rm -v "$(pwd)/backend/functions/$service:/app:Z" -w /app golang:1.25-alpine go vet ./... 2>&1 | tee -a "$AUDIT_DIR/go-vet.txt" || true fi done # ==== SECTION 5: AUTHENTICATION & AUTHORIZATION ==== echo "" echo "============================================" echo "SECTION 5: AUTHENTICATION AUDIT" echo "============================================" echo "5.1 JWT Configuration..." { echo "=== JWT Security Check ===" if grep -q "JWT_SECRET.*32" backend/functions/auth-service/main.go; then log_pass "JWT secret minimum length enforced (32 chars)" fi if grep -q "jwt.SigningMethodHS256" backend/functions/auth-service/main.go; then log_info "Using HS256 signing (symmetric - ensure secret is strong)" fi echo "" echo "=== Token Expiration ===" grep -n "exp.*time.Now" backend/functions/auth-service/main.go || echo "Check token expiration manually" } | tee "$AUDIT_DIR/jwt-audit.txt" echo "" echo "5.2 Password Security..." { echo "=== Password Hashing ===" if grep -q "bcrypt.GenerateFromPassword" backend/functions/auth-service/main.go; then log_pass "Using bcrypt for password hashing" fi if grep -q "bcrypt.DefaultCost" backend/functions/auth-service/main.go; then log_info "Using bcrypt default cost (10)" fi } | tee "$AUDIT_DIR/password-audit.txt" echo "" echo "5.3 Role-Based Access Control..." { echo "=== RBAC Implementation ===" grep -n "requireRole" backend/functions/auth-service/main.go | head -20 echo "" echo "=== Protected Routes ===" grep -n "authenticate(" backend/functions/auth-service/main.go } | tee "$AUDIT_DIR/rbac-audit.txt" # ==== SECTION 6: API SECURITY ==== echo "" echo "============================================" echo "SECTION 6: API SECURITY" echo "============================================" echo "6.1 CORS Configuration..." { echo "=== CORS Settings ===" grep -n "Access-Control" backend/functions/auth-service/main.go grep -n "CORS" podman-compose.yml echo "" if grep -q 'CORS_ALLOW_ORIGIN.*\*' podman-compose.yml; then log_warn "CORS allows all origins (*) - restrict in production" fi } | tee "$AUDIT_DIR/cors-audit.txt" echo "" echo "6.2 HTTP Security Headers..." { echo "=== Checking security headers ===" curl -sI http://localhost:8090/ | grep -iE "(strict-transport|content-security|x-frame|x-content-type|x-xss)" || log_warn "Missing security headers" } | tee "$AUDIT_DIR/headers-audit.txt" echo "" echo "6.3 Rate Limiting..." { if grep -rq "rate" backend/functions/auth-service/main.go; then log_pass "Rate limiting implemented" else log_warn "No rate limiting found - consider adding for auth endpoints" fi } | tee "$AUDIT_DIR/ratelimit-audit.txt" # ==== SECTION 7: DATABASE SECURITY ==== echo "" echo "============================================" echo "SECTION 7: DATABASE SECURITY" echo "============================================" echo "7.1 SQL Injection Prevention..." { echo "=== Parameterized Queries Check ===" # Check for string concatenation in SQL if grep -rn "fmt.Sprintf.*SELECT\|fmt.Sprintf.*INSERT\|fmt.Sprintf.*UPDATE\|fmt.Sprintf.*DELETE" backend/functions/; then log_fail "Potential SQL injection - using fmt.Sprintf with SQL" else log_pass "No obvious SQL injection vulnerabilities (using parameterized queries)" fi echo "" echo "=== Query Examples ===" grep -n "db.Query\|db.QueryRow\|db.Exec" backend/functions/auth-service/main.go | head -10 } | tee "$AUDIT_DIR/sql-audit.txt" echo "" echo "7.2 Database SSL Mode..." { echo "=== SSL Configuration ===" grep -n "sslmode\|DB_SSL_MODE" backend/functions/auth-service/main.go podman-compose.yml if grep -q 'DB_SSL_MODE.*disable' podman-compose.yml; then log_warn "Database SSL is disabled - enable for production" fi } | tee "$AUDIT_DIR/db-ssl-audit.txt" # ==== SECTION 8: INPUT VALIDATION ==== echo "" echo "============================================" echo "SECTION 8: INPUT VALIDATION" echo "============================================" echo "8.1 Frontend XSS Prevention..." { echo "=== DOMPurify Usage ===" grep -rn "DOMPurify\|v-html" frontend/src/ || echo "Check v-html usage for XSS" echo "" echo "=== v-html occurrences ===" grep -rn "v-html" frontend/src/views/ frontend/src/components/ 2>/dev/null || echo "No v-html found" } | tee "$AUDIT_DIR/xss-audit.txt" echo "" echo "8.2 Backend Input Validation..." { echo "=== Email Validation ===" grep -n "email.*==" backend/functions/auth-service/main.go | head -5 echo "" echo "=== Password Requirements ===" grep -n "Password\|password" backend/functions/auth-service/main.go | grep -v "PasswordHash\|passwordHash" | head -10 } | tee "$AUDIT_DIR/validation-audit.txt" # ==== SECTION 9: INFRASTRUCTURE ==== echo "" echo "============================================" echo "SECTION 9: INFRASTRUCTURE AUDIT" echo "============================================" echo "9.1 Exposed Ports..." { echo "=== Port Mappings ===" grep -n "ports:" -A2 podman-compose.yml echo "" echo "=== Database Port ===" if grep -q "5432:5432" podman-compose.yml; then log_warn "Database port exposed externally" else log_pass "Database port not exposed externally" fi } | tee "$AUDIT_DIR/ports-audit.txt" echo "" echo "9.2 Volume Mounts..." { echo "=== Persistent Volumes ===" grep -n "volumes:" -A5 podman-compose.yml } | tee "$AUDIT_DIR/volumes-audit.txt" # ==== SECTION 10: SUMMARY ==== echo "" echo "============================================" echo "AUDIT SUMMARY" echo "============================================" { echo "Audit completed: $(date)" echo "Output directory: $AUDIT_DIR" echo "" echo "=== Files Generated ===" ls -la "$AUDIT_DIR" echo "" echo "=== Critical Findings ===" echo "1. Review pnpm-audit.txt for dependency vulnerabilities" echo "2. Review secrets-scan.txt for exposed credentials" echo "3. Review cors-audit.txt for CORS configuration" echo "4. Review sql-audit.txt for injection vulnerabilities" echo "5. Review headers-audit.txt for missing security headers" } | tee "$AUDIT_DIR/SUMMARY.txt" echo "" echo "===========================================" echo "AUDIT COMPLETE - Results in: $AUDIT_DIR" echo "==========================================="