182 lines
5.8 KiB
YAML
182 lines
5.8 KiB
YAML
# GitHub Actions Workflow for Gitleaks Secret Scanning
|
|
# Save as: .github/workflows/gitleaks.yml
|
|
|
|
name: Secret Scanning with Gitleaks
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- develop
|
|
- 'release/**'
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- develop
|
|
schedule:
|
|
# Run daily at 2 AM UTC
|
|
- cron: '0 2 * * *'
|
|
workflow_dispatch: # Allow manual triggers
|
|
|
|
# Cancel in-progress runs when new commit pushed
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
gitleaks-scan:
|
|
name: Scan for Secrets
|
|
runs-on: ubuntu-latest
|
|
|
|
permissions:
|
|
# Required for uploading SARIF results to GitHub Security tab
|
|
security-events: write
|
|
# Required for checking out private repos
|
|
contents: read
|
|
|
|
steps:
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
# Fetch full history for comprehensive scanning
|
|
fetch-depth: 0
|
|
|
|
- name: Run Gitleaks Scan
|
|
id: gitleaks
|
|
uses: gitleaks/gitleaks-action@v2
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
# Optional: Use custom configuration
|
|
# GITLEAKS_CONFIG: .gitleaks.toml
|
|
|
|
# Optional: Generate JSON report for further processing
|
|
- name: Generate JSON Report
|
|
if: always() # Run even if secrets found
|
|
run: |
|
|
docker run --rm -v ${{ github.workspace }}:/repo \
|
|
zricethezav/gitleaks:latest \
|
|
detect --source /repo \
|
|
--report-path /repo/gitleaks-report.json \
|
|
--report-format json \
|
|
--exit-code 0 || true
|
|
|
|
# Optional: Upload JSON report as artifact
|
|
- name: Upload Scan Report
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gitleaks-report
|
|
path: gitleaks-report.json
|
|
retention-days: 30
|
|
|
|
# Optional: Generate SARIF report for GitHub Security tab
|
|
- name: Generate SARIF Report
|
|
if: always()
|
|
run: |
|
|
docker run --rm -v ${{ github.workspace }}:/repo \
|
|
zricethezav/gitleaks:latest \
|
|
detect --source /repo \
|
|
--report-path /repo/gitleaks.sarif \
|
|
--report-format sarif \
|
|
--exit-code 0 || true
|
|
|
|
# Optional: Upload SARIF report to GitHub Security
|
|
- name: Upload SARIF to GitHub Security
|
|
if: always()
|
|
uses: github/codeql-action/upload-sarif@v3
|
|
with:
|
|
sarif_file: gitleaks.sarif
|
|
category: gitleaks
|
|
|
|
# Optional: Comment on PR with findings
|
|
- name: Comment PR with Findings
|
|
if: failure() && github.event_name == 'pull_request'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const fs = require('fs');
|
|
try {
|
|
const report = JSON.parse(fs.readFileSync('gitleaks-report.json', 'utf8'));
|
|
const findings = report.length;
|
|
|
|
const comment = `## 🔒 Secret Scanning Results
|
|
|
|
⚠️ **${findings} potential secret(s) detected!**
|
|
|
|
Please review the findings and take immediate action:
|
|
1. **Do not merge** this PR until secrets are removed
|
|
2. Rotate any exposed credentials immediately
|
|
3. Remove secrets from code and use environment variables
|
|
4. Review the security tab for detailed findings
|
|
|
|
See [Secret Scanning Guide](https://github.com/${{ github.repository }}/blob/main/docs/secret-scanning.md) for remediation steps.`;
|
|
|
|
github.rest.issues.createComment({
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
body: comment
|
|
});
|
|
} catch (error) {
|
|
console.log('No report file or error reading it:', error.message);
|
|
}
|
|
|
|
# Optional: Post to Slack on failure
|
|
- name: Notify Slack on Failure
|
|
if: failure()
|
|
uses: slackapi/slack-github-action@v1
|
|
with:
|
|
payload: |
|
|
{
|
|
"text": "🚨 Secrets detected in ${{ github.repository }}",
|
|
"blocks": [
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "*Secret Scanning Alert*\n\nSecrets detected in repository: `${{ github.repository }}`\nBranch: `${{ github.ref_name }}`\nCommit: `${{ github.sha }}`\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
env:
|
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
|
|
|
# Optional: Baseline scanning for incremental detection
|
|
baseline-scan:
|
|
name: Incremental Scan Against Baseline
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'push'
|
|
|
|
steps:
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Download Existing Baseline
|
|
continue-on-error: true
|
|
run: |
|
|
# Download baseline from artifact storage or S3
|
|
# Example: aws s3 cp s3://bucket/.gitleaks-baseline.json .
|
|
echo "Baseline download would go here"
|
|
|
|
- name: Run Incremental Scan
|
|
run: |
|
|
docker run --rm -v ${{ github.workspace }}:/repo \
|
|
zricethezav/gitleaks:latest \
|
|
detect --source /repo \
|
|
--baseline-path /repo/.gitleaks-baseline.json \
|
|
--report-path /repo/new-findings.json \
|
|
--report-format json \
|
|
--exit-code 1 || true
|
|
|
|
- name: Upload New Findings
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: new-findings
|
|
path: new-findings.json
|
|
retention-days: 90
|