clean up #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Secret Scanning | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| - "feature/**" | |
| - "fix/**" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| gitleaks: | |
| name: Gitleaks Secret Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Fetch all history for accurate scanning | |
| - name: Run Gitleaks | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_ENABLE_COMMENTS: true | |
| - name: Upload Gitleaks Report | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: gitleaks-report | |
| path: results.sarif | |
| retention-days: 7 | |
| trufflehog: | |
| name: TruffleHog Secret Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: TruffleHog OSS | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| base: ${{ github.event.repository.default_branch }} | |
| head: HEAD | |
| extra_args: --debug --only-verified | |
| custom-pattern-check: | |
| name: Custom Pattern Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for common secret patterns | |
| id: secret_check | |
| run: | | |
| echo "Scanning for common secret patterns..." | |
| # Define patterns to search for | |
| PATTERNS=( | |
| "aws_access_key_id" | |
| "aws_secret_access_key" | |
| "AKIA[0-9A-Z]{16}" # AWS Access Key | |
| "(?i)api[_-]?key.*['\"][0-9a-zA-Z]{32,}['\"]" # Generic API keys | |
| "(?i)password.*['\"][^'\"]{8,}['\"]" # Passwords in quotes | |
| "(?i)secret.*['\"][0-9a-zA-Z]{32,}['\"]" # Generic secrets | |
| "(?i)token.*['\"][0-9a-zA-Z]{32,}['\"]" # Tokens | |
| "private[_-]?key" | |
| "-----BEGIN (RSA|OPENSSH|DSA|EC) PRIVATE KEY-----" # Private keys | |
| "ghp_[0-9a-zA-Z]{36}" # GitHub Personal Access Token | |
| "ghs_[0-9a-zA-Z]{36}" # GitHub OAuth Secret | |
| "sk_live_[0-9a-zA-Z]{24,}" # Stripe Live Secret Key | |
| "pk_live_[0-9a-zA-Z]{24,}" # Stripe Live Public Key | |
| ) | |
| FOUND_SECRETS=0 | |
| REPORT_FILE="secret_scan_report.txt" | |
| echo "=== Secret Scanning Report ===" > $REPORT_FILE | |
| echo "Timestamp: $(date)" >> $REPORT_FILE | |
| echo "" >> $REPORT_FILE | |
| # Get list of changed files | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) | |
| else | |
| FILES=$(git diff --name-only HEAD~1 HEAD) | |
| fi | |
| # Skip certain file types and directories | |
| FILES=$(echo "$FILES" | grep -v ".terraform/" | grep -v ".git/" | grep -v "node_modules/" || true) | |
| for FILE in $FILES; do | |
| if [ -f "$FILE" ]; then | |
| echo "Scanning: $FILE" >> $REPORT_FILE | |
| for PATTERN in "${PATTERNS[@]}"; do | |
| MATCHES=$(grep -niE "$PATTERN" "$FILE" 2>/dev/null || true) | |
| if [ ! -z "$MATCHES" ]; then | |
| FOUND_SECRETS=1 | |
| echo " ❌ FOUND POTENTIAL SECRET:" >> $REPORT_FILE | |
| echo " Pattern: $PATTERN" >> $REPORT_FILE | |
| echo "$MATCHES" | while IFS= read -r line; do | |
| # Redact the actual secret value | |
| REDACTED=$(echo "$line" | sed -E 's/['\''"][0-9a-zA-Z]{8,}['\''"]/***REDACTED***/g') | |
| echo " $REDACTED" >> $REPORT_FILE | |
| done | |
| echo "" >> $REPORT_FILE | |
| fi | |
| done | |
| fi | |
| done | |
| if [ $FOUND_SECRETS -eq 1 ]; then | |
| echo "status=failed" >> $GITHUB_OUTPUT | |
| cat $REPORT_FILE | |
| echo "" | |
| echo "❌ SECRETS DETECTED! Please remove sensitive data before committing." | |
| exit 1 | |
| else | |
| echo "status=passed" >> $GITHUB_OUTPUT | |
| echo "✅ No secrets detected" | |
| fi | |
| - name: Comment on PR with findings | |
| if: failure() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const fs = require('fs'); | |
| let report = '⚠️ **Secret Scanning Failed**\n\n'; | |
| report += '**Potential secrets or API keys were detected in your changes.**\n\n'; | |
| report += 'Please review and remove any sensitive data before merging.\n\n'; | |
| report += '### What to do:\n'; | |
| report += '1. Remove the secret from your code\n'; | |
| report += '2. Use environment variables or GitHub Secrets instead\n'; | |
| report += '3. If the secret was already committed, you must:\n'; | |
| report += ' - Rotate/invalidate the exposed secret\n'; | |
| report += ' - Remove it from git history using `git filter-branch` or BFG Repo-Cleaner\n\n'; | |
| report += '### Common secret patterns detected:\n'; | |
| report += '- AWS Access Keys (AKIA...)\n'; | |
| report += '- API Keys\n'; | |
| report += '- Private Keys\n'; | |
| report += '- Passwords or tokens in code\n\n'; | |
| report += '**This PR cannot be merged until all secrets are removed.**'; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: report | |
| }); | |
| block-merge: | |
| name: Block Merge if Secrets Found | |
| runs-on: ubuntu-latest | |
| needs: [gitleaks, trufflehog, custom-pattern-check] | |
| if: always() | |
| steps: | |
| - name: Check scan results | |
| run: | | |
| if [ "${{ needs.gitleaks.result }}" = "failure" ] || \ | |
| [ "${{ needs.trufflehog.result }}" = "failure" ] || \ | |
| [ "${{ needs.custom-pattern-check.result }}" = "failure" ]; then | |
| echo "❌ Secret scanning failed. Blocking merge." | |
| exit 1 | |
| else | |
| echo "✅ All secret scans passed. Safe to merge." | |
| fi | |
| # Optional: Auto-revert commits with secrets on main branch | |
| auto-revert: | |
| name: Auto-revert Commits with Secrets | |
| runs-on: ubuntu-latest | |
| needs: [gitleaks, trufflehog, custom-pattern-check] | |
| if: | | |
| failure() && | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Revert last commit | |
| run: | | |
| COMMIT_SHA="${{ github.sha }}" | |
| COMMIT_MSG=$(git log -1 --pretty=%B $COMMIT_SHA) | |
| echo "⚠️ Reverting commit: $COMMIT_SHA" | |
| echo "Commit message: $COMMIT_MSG" | |
| git revert --no-edit $COMMIT_SHA | |
| git push origin main | |
| - name: Create issue for manual review | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const issue = await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: '🚨 Secrets Detected - Commit Automatically Reverted', | |
| body: `## Security Alert: Secrets Detected | |
| **Commit**: \`${{ github.sha }}\` | |
| **Author**: @${{ github.actor }} | |
| **Branch**: main | |
| ### What happened? | |
| Secret scanning detected potential secrets or API keys in a commit to the main branch. | |
| The commit has been automatically reverted to prevent exposure. | |
| ### Required Actions: | |
| 1. **⚠️ ROTATE ALL EXPOSED SECRETS IMMEDIATELY** | |
| - If the secret was an API key, revoke it | |
| - If it was an AWS key, disable it in IAM | |
| - Generate new credentials | |
| 2. **Clean up your local branch**: | |
| \`\`\`bash | |
| git fetch origin | |
| git reset --hard origin/main | |
| \`\`\` | |
| 3. **Remove the secret properly**: | |
| - Use environment variables | |
| - Use GitHub Secrets | |
| - Use AWS Secrets Manager / Parameter Store | |
| - Add pattern to .gitignore | |
| 4. **Re-commit without secrets**: | |
| - Make your changes again | |
| - Ensure no secrets are in the code | |
| - Submit a new PR | |
| ### Preventing Future Incidents: | |
| - Always use \`.tfvars\` files for sensitive values (they're gitignored) | |
| - Use \`backend.tf\` for backend config (also gitignored) | |
| - Store secrets in GitHub Secrets or AWS Secrets Manager | |
| - Run \`git diff\` before committing to review changes | |
| - Enable pre-commit hooks for local secret scanning | |
| **This issue will remain open until confirmed that exposed secrets have been rotated.**`, | |
| labels: ['security', 'urgent', 'secrets-detected'] | |
| }); | |
| console.log('Created issue:', issue.data.number); | |
| - name: Send alert notification | |
| if: always() | |
| run: | | |
| echo "🚨 SECURITY ALERT: Secrets detected in commit ${{ github.sha }}" | |
| echo "Commit has been reverted and an issue has been created." | |
| echo "Please rotate any exposed credentials immediately." |