Skip to content

Update trufflehog-scan.yml #11

Update trufflehog-scan.yml

Update trufflehog-scan.yml #11

Workflow file for this run

name: TruffleHog Secret Scan
on:
pull_request:
types: [opened, synchronize, reopened]
pull_request_target:
types: [opened, synchronize, reopened]
workflow_dispatch:
permissions:
contents: read
pull-requests: write
statuses: write
# Default exclusion patterns (regex format)
# Supports: exact filenames, wildcards, regex patterns
# Examples:
# Exact file: ^config/settings\.json$
# Directory: ^node_modules/
# Extension: \.lock$
# Wildcard: .*\.min\.js$
# Regex: ^src/test/.*_test\.py$
env:
DEFAULT_EXCLUDES: |
^node_modules/
^vendor/
^\.git/
\.lock$
^package-lock\.json$
^yarn\.lock$
^pnpm-lock\.yaml$
\.min\.js$
\.min\.css$
^\.github/workflows/
jobs:
trufflehog-scan:
name: Scan PR for Secrets
runs-on: ubuntu-latest
# Run pull_request_target only for fork PRs, pull_request only for same-repo PRs
# This prevents duplicate runs
if: |
(github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository) ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
github.event_name == 'workflow_dispatch'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch PR head commits
if: github.event_name != 'workflow_dispatch'
run: |
# Fetch PR commits using GitHub's merge ref (works for all PRs including forks)
git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/pr-head
echo "Fetched PR #${{ github.event.pull_request.number }} head commit: ${{ github.event.pull_request.head.sha }}"
- name: Setup exclude config
id: config
run: |
# Always include default exclusions first
echo "Adding default exclusions..."
cat << 'EOF' > .trufflehog-ignore
${{ env.DEFAULT_EXCLUDES }}
EOF
# Append user-defined exclusions if set (additive, not replacement)
if [ -n "${{ vars.TRUFFLEHOG_EXCLUDES }}" ]; then
echo "Adding repo/org-level TRUFFLEHOG_EXCLUDES patterns..."
echo "${{ vars.TRUFFLEHOG_EXCLUDES }}" | tr ',' '\n' | sed '/^$/d' >> .trufflehog-ignore
fi
echo "Exclusion patterns:"
cat .trufflehog-ignore
echo "exclude_args=--exclude-paths=.trufflehog-ignore" >> $GITHUB_OUTPUT
- name: TruffleHog Scan
id: trufflehog
uses: trufflesecurity/trufflehog@main
continue-on-error: true
with:
base: ${{ github.event.pull_request.base.sha }}
head: ${{ github.event.pull_request.head.sha }}
extra_args: --json ${{ steps.config.outputs.exclude_args }}
- name: Process scan results
id: process
if: github.event_name != 'workflow_dispatch'
run: |
# Check if TruffleHog found any secrets
if [ "${{ steps.trufflehog.outcome }}" == "failure" ]; then
echo "has_secrets=true" >> $GITHUB_OUTPUT
echo "status=failure" >> $GITHUB_OUTPUT
echo "description=Secret scanning found exposed credentials" >> $GITHUB_OUTPUT
else
echo "has_secrets=false" >> $GITHUB_OUTPUT
echo "status=success" >> $GITHUB_OUTPUT
echo "description=No secrets detected in PR changes" >> $GITHUB_OUTPUT
fi
- name: Post PR comment on findings
if: steps.process.outputs.has_secrets == 'true' && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v7
with:
script: |
const commentMarker = '<!-- TRUFFLEHOG-SCAN-COMMENT -->';
const commitSha = '${{ github.event.pull_request.head.sha }}';
const shortSha = commitSha.substring(0, 7);
const scanTime = new Date().toISOString().replace('T', ' ').substring(0, 19) + ' UTC';
const body = `${commentMarker}
## :rotating_light: Secret Scanning Alert
**TruffleHog detected potential secrets in this pull request.**

Check failure on line 117 in .github/workflows/trufflehog-scan.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/trufflehog-scan.yml

Invalid workflow file

You have an error in your yaml syntax on line 117
| Scan Details | |
|--------------|---|
| **Commit** | [\`${shortSha}\`](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha}) |
| **Scanned At** | ${scanTime} |
| **Workflow Run** | [View Logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) |
### What to do:
1. **Remove the exposed secret** from your code
2. **Rotate the credential immediately** - assume it's compromised
3. **Push the fix** to this branch
4. The scan will re-run automatically
### Finding Details
Check the [workflow run logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for:
- File paths containing secrets
- Line numbers
- Secret types (API key, password, token, etc.)
- Verification status (verified = confirmed active)
---
*Only files modified in this PR were scanned. Secrets are classified as **verified** (confirmed active) or **unverified** (potential match).*
`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
per_page: 100
});
const existing = comments.find(c => c.body && c.body.includes(commentMarker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: body
});
}
- name: Update PR comment when secrets resolved
if: steps.process.outputs.has_secrets == 'false' && github.event_name != 'workflow_dispatch'
uses: actions/github-script@v7
with:
script: |
const commentMarker = '<!-- TRUFFLEHOG-SCAN-COMMENT -->';
const commitSha = '${{ github.event.pull_request.head.sha }}';
const shortSha = commitSha.substring(0, 7);
const scanTime = new Date().toISOString().replace('T', ' ').substring(0, 19) + ' UTC';
// Check if there's an existing alert comment from a previous failed scan
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
per_page: 100
});
const existing = comments.find(c => c.body && c.body.includes(commentMarker));
// Only update if there was a previous alert - don't create new comments for clean scans
if (existing) {
const resolvedBody = `${commentMarker}
## :white_check_mark: Secret Scanning Passed
**Previously detected secrets have been resolved.**
| Scan Details | |
|--------------|---|
| **Commit** | [\`${shortSha}\`](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha}) |
| **Scanned At** | ${scanTime} |
| **Workflow Run** | [View Logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) |
The secrets flagged in previous scans are no longer detected in the modified files.
---
*This PR is now clear of detected secrets. Remember to rotate any credentials that were previously exposed.*
`;
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: resolvedBody
});
console.log('Updated existing alert comment to show resolved status');
} else {
console.log('No previous alert comment found - scan passed cleanly');
}
- name: Set commit status
if: github.event_name != 'workflow_dispatch'
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: '${{ github.event.pull_request.head.sha }}',
state: '${{ steps.process.outputs.status }}',
target_url: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}',
description: '${{ steps.process.outputs.description }}',
context: 'TruffleHog Secret Scan'
});
- name: Fail workflow if secrets found
if: steps.process.outputs.has_secrets == 'true'
run: |
echo "::error::Secrets detected in PR. Review the logs and PR comment for details."
exit 1