Files
web-hosts/domains/coppertone.tech/scripts/audit.sh
2025-12-26 13:38:04 +01:00

320 lines
12 KiB
Bash
Executable File

#!/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 <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 "==========================================="