name: Security Check # ======================================== # Automated Security Scanning # ======================================== # This workflow runs on every PR and push to main # to detect potential security issues on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] # Allow manual trigger workflow_dispatch: jobs: # ======================================== # SECRET SCANNING # ======================================== secret-scan: name: Scan for Secrets runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 # Full history for better scanning - name: TruffleHog Secret Scan uses: trufflesecurity/trufflehog@main with: path: ./ base: ${{ github.event.repository.default_branch }} head: HEAD extra_args: --debug --only-verified - name: Gitleaks Secret Scan uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # ======================================== # FILE VALIDATION # ======================================== file-validation: name: Validate Files runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Check for .env files run: | echo "Checking for .env files..." if git ls-files | grep -E "^\.env$"; then echo "L ERROR: .env file found in repository!" exit 1 fi echo " No .env files found" - name: Check for sensitive files run: | echo "Checking for sensitive files..." sensitive_patterns=( "*.key" "*.pem" "*.cert" "*.p12" "*.pfx" "*secret*" "*credential*" ) found_sensitive=false for pattern in "${sensitive_patterns[@]}"; do if git ls-files | grep -i "$pattern"; then echo "  WARNING: Potential sensitive file found: $pattern" found_sensitive=true fi done if [ "$found_sensitive" = true ]; then echo "Please review files above and ensure they're not sensitive" exit 1 fi echo " No sensitive files found" - name: Verify .gitignore run: | echo "Verifying .gitignore contains .env..." if ! grep -q "^\.env$" .gitignore; then echo "L ERROR: .env not found in .gitignore!" exit 1 fi echo " .gitignore is properly configured" # ======================================== # CODE QUALITY & SECURITY # ======================================== code-security: name: Code Security Analysis runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Run ESLint Security Plugin run: | npm install --save-dev eslint-plugin-security # Run eslint with security rules (if configured) # npm run lint:security || true continue-on-error: true - name: Check for hardcoded secrets in code run: | echo "Scanning TypeScript files for potential secrets..." # Check for potential hardcoded passwords if grep -r -i "password.*=.*['\"][^'\"]\{8,\}['\"]" src/ --include="*.ts" --include="*.tsx"; then echo "  WARNING: Potential hardcoded password found" echo "Please use environment variables instead" fi # Check for API keys if grep -r -E "api[_-]?key.*=.*['\"][^'\"]{20,}['\"]" src/ --include="*.ts" --include="*.tsx"; then echo "  WARNING: Potential hardcoded API key found" echo "Please use environment variables instead" fi echo " Code scan completed" # ======================================== # DEPENDENCY SECURITY # ======================================== dependency-security: name: Dependency Security Audit runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Run npm audit run: | npm audit --audit-level=moderate continue-on-error: true - name: Check for known vulnerabilities uses: snyk/actions/node@master continue-on-error: true env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high # ======================================== # ENVIRONMENT VALIDATION # ======================================== env-validation: name: Environment Configuration Check runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Verify .env.example exists run: | if [ ! -f .env.example ]; then echo "L ERROR: .env.example not found!" echo "Please create .env.example with safe default values" exit 1 fi echo " .env.example exists" - name: Check .env.example for secrets run: | echo "Checking .env.example for actual secrets..." # .env.example should NOT contain real secrets if grep -E "(password|key|secret|token)=.{20,}" .env.example; then echo "  WARNING: .env.example may contain real credentials!" echo "Example files should only have placeholder values" exit 1 fi echo " .env.example contains no real secrets" - name: Validate environment variable usage run: | echo "Checking that environment variables are used correctly..." # Check AuthContext for proper env var usage if [ -f "src/contexts/AuthContext.tsx" ]; then if grep -q "import.meta.env" src/contexts/AuthContext.tsx; then echo " AuthContext uses environment variables" else echo "  WARNING: AuthContext may not be using environment variables" fi fi # ======================================== # SUMMARY # ======================================== security-summary: name: Security Check Summary needs: [secret-scan, file-validation, code-security, dependency-security, env-validation] runs-on: ubuntu-latest if: always() steps: - name: Security Summary run: | echo "======================================" echo "Security Check Summary" echo "======================================" echo "" echo "Secret Scan: ${{ needs.secret-scan.result }}" echo "File Validation: ${{ needs.file-validation.result }}" echo "Code Security: ${{ needs.code-security.result }}" echo "Dependency Security: ${{ needs.dependency-security.result }}" echo "Environment Validation: ${{ needs.env-validation.result }}" echo "" if [ "${{ needs.secret-scan.result }}" == "failure" ] || \ [ "${{ needs.file-validation.result }}" == "failure" ]; then echo "L CRITICAL: Security issues detected!" exit 1 fi echo " All critical security checks passed"