# 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