Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/pre-commit-hooks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Optional: Pre-commit hooks workflow
# This provides guidance for setting up local pre-commit hooks

name: Pre-commit Validation

on:
pull_request:
paths:
- ".pre-commit-config.yaml"
- ".github/workflows/pre-commit-hooks.yml"

jobs:
validate-pre-commit:
name: Validate Pre-commit Configuration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install pre-commit
run: |
pip install pre-commit
pre-commit --version

- name: Run pre-commit on all files
run: pre-commit run --all-files
continue-on-error: true

- name: Show pre-commit setup instructions
if: always()
run: |
echo "## 📋 Setting up Pre-commit Hooks Locally"
echo ""
echo "Pre-commit hooks help catch secrets BEFORE they reach GitHub."
echo ""
echo "### Installation:"
echo "\`\`\`bash"
echo "# Install pre-commit"
echo "pip install pre-commit"
echo ""
echo "# Install the git hooks"
echo "pre-commit install"
echo ""
echo "# (Optional) Run against all files"
echo "pre-commit run --all-files"
echo "\`\`\`"
echo ""
echo "### What it does:"
echo "- Scans for secrets before each commit"
echo "- Validates Terraform formatting"
echo "- Checks for merge conflicts"
echo "- Prevents large files from being committed"
282 changes: 282 additions & 0 deletions .github/workflows/secret-scanning.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
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."
Loading
Loading