320 lines
12 KiB
Bash
Executable File
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 "==========================================="
|