Secrets Detection Scan #334
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
| # Secrets Detection with TruffleHog | |
| # Scans for accidentally committed secrets and credentials | |
| name: Secrets Detection Scan | |
| on: | |
| push: | |
| branches: [ main, dev, 'kcs/*' ] | |
| pull_request: | |
| branches: [ main, dev ] | |
| schedule: | |
| # Run daily at 1 AM UTC | |
| - cron: '0 1 * * *' | |
| jobs: | |
| trufflehog: | |
| name: TruffleHog Secrets Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| # Fetch full git history for comprehensive scanning | |
| fetch-depth: 0 | |
| - name: Run TruffleHog secrets scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| # Scan the entire repository including git history | |
| path: ./ | |
| base: ${{ github.event.repository.default_branch }} | |
| head: HEAD | |
| extra_args: --debug --only-verified --json | |
| - name: Run TruffleHog filesystem scan | |
| id: trufflehog-fs | |
| continue-on-error: true | |
| run: | | |
| # Install TruffleHog if not available | |
| if ! command -v trufflehog &> /dev/null; then | |
| curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin | |
| fi | |
| # Scan filesystem for secrets | |
| trufflehog filesystem . \ | |
| --json \ | |
| --only-verified \ | |
| --exclude-paths=.trufflehogignore \ | |
| > trufflehog-results.json 2>&1 || true | |
| - name: Parse and comment on secrets found | |
| if: always() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| // Check if results file exists | |
| if (fs.existsSync('trufflehog-results.json')) { | |
| const results = fs.readFileSync('trufflehog-results.json', 'utf8'); | |
| const lines = results.trim().split('\n').filter(line => line.trim()); | |
| let secrets = []; | |
| for (const line of lines) { | |
| try { | |
| const finding = JSON.parse(line); | |
| if (finding.Verified || finding.verified) { | |
| secrets.push(finding); | |
| } | |
| } catch (e) { | |
| // Skip invalid JSON lines | |
| } | |
| } | |
| if (secrets.length > 0) { | |
| let comment = '## π Secrets Detection Results\n\n'; | |
| comment += `β οΈ **CRITICAL**: Found ${secrets.length} verified secret(s) in the repository!\n\n`; | |
| for (const secret of secrets.slice(0, 5)) { // Show max 5 secrets | |
| const detector = secret.DetectorName || secret.detector_name || 'Unknown'; | |
| const file = secret.SourceMetadata?.Data?.Filesystem?.file || 'Unknown file'; | |
| comment += `- π¨ **${detector}** detected in \`${file}\`\n`; | |
| } | |
| if (secrets.length > 5) { | |
| comment += `\n... and ${secrets.length - 5} more secret(s).\n`; | |
| } | |
| comment += '\n**IMMEDIATE ACTION REQUIRED:**\n'; | |
| comment += '1. π Rotate all exposed credentials immediately\n'; | |
| comment += '2. ποΈ Remove secrets from git history using BFG Repo-Cleaner\n'; | |
| comment += '3. π Use environment variables or secret management systems\n'; | |
| comment += '4. π Add sensitive patterns to `.trufflehogignore`\n'; | |
| // Post comment on PR or create issue | |
| if (context.eventName === 'pull_request') { | |
| await github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: comment | |
| }); | |
| // Also add labels | |
| await github.rest.issues.addLabels({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| labels: ['security', 'critical', 'secrets-detected'] | |
| }); | |
| } else { | |
| // Create an issue for secrets found in push events | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: 'π¨ CRITICAL: Secrets detected in repository', | |
| body: comment, | |
| labels: ['security', 'critical', 'secrets-detected'] | |
| }); | |
| } | |
| // Exit with error to fail the workflow | |
| core.setFailed(`Found ${secrets.length} verified secret(s) in the repository`); | |
| } else { | |
| console.log('β No verified secrets found'); | |
| } | |
| } else { | |
| console.log('βΉοΈ No TruffleHog results file found'); | |
| } | |
| - name: Upload secrets scan results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: secrets-scan-results-${{ github.sha }} | |
| path: | | |
| trufflehog-results.json | |
| retention-days: 30 | |
| gitguardian: | |
| name: GitGuardian Secrets Scan (Disabled - API Key Issue) | |
| runs-on: ubuntu-latest | |
| if: false # Disabled due to GitGuardian API key configuration issue | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: GitGuardian scan | |
| uses: GitGuardian/ggshield/actions/secret@main | |
| env: | |
| GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} | |
| GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} | |
| GITHUB_PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | |
| GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} | |
| with: | |
| args: --exit-zero |