From a7b8ecd341df30f66e184f7330720134cea840ce Mon Sep 17 00:00:00 2001 From: Brijesh Kumar Patel Date: Mon, 19 Jan 2026 17:34:02 +0530 Subject: [PATCH] PDP-684 : Reverting my changes for trufflehog --- .github/workflows/trufflehog-scan.yml | 90 ++++++++++++++++++--------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/.github/workflows/trufflehog-scan.yml b/.github/workflows/trufflehog-scan.yml index 316d837..3250a2b 100644 --- a/.github/workflows/trufflehog-scan.yml +++ b/.github/workflows/trufflehog-scan.yml @@ -9,6 +9,15 @@ permissions: contents: read pull-requests: 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/ @@ -30,19 +39,28 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 2 + 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 echo "Adding default exclusions" cat << 'EOF' > .trufflehog-ignore ${{ env.DEFAULT_EXCLUDES }} EOF + # Append repo/org-level custom exclusions if defined if [ -n "${{ vars.TRUFFLEHOG_EXCLUDES }}" ]; then echo "Adding repo/org-level TRUFFLEHOG_EXCLUDES patterns" + # Support both comma-separated and newline-separated patterns echo "${{ vars.TRUFFLEHOG_EXCLUDES }}" | tr ',' '\n' | sed '/^$/d' >> .trufflehog-ignore fi @@ -55,7 +73,7 @@ jobs: uses: trufflesecurity/trufflehog@main continue-on-error: true with: - base: ${{ github.event.pull_request.head.sha }}~1 + base: ${{ github.event.pull_request.base.sha }} head: ${{ github.event.pull_request.head.sha }} extra_args: --json ${{ steps.config.outputs.exclude_args }} @@ -63,54 +81,41 @@ jobs: id: parse if: github.event_name != 'workflow_dispatch' run: | + # Capture TruffleHog JSON output by re-running with same args echo "Parsing TruffleHog results..." VERIFIED_COUNT=0 UNVERIFIED_COUNT=0 - # Get changed files list - CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}) - echo "Changed files:" - echo "$CHANGED_FILES" - - # Scan only HEAD commit (current state), not history SCAN_OUTPUT=$(docker run --rm -v "$(pwd)":/tmp -w /tmp \ - -e GIT_CONFIG_COUNT=2 \ - -e GIT_CONFIG_KEY_0=diff.renames \ - -e GIT_CONFIG_VALUE_0=false \ - -e GIT_CONFIG_KEY_1=diff.renameLimit \ - -e GIT_CONFIG_VALUE_1=0 \ ghcr.io/trufflesecurity/trufflehog:latest \ git file:///tmp/ \ - --since-commit ${{ github.event.pull_request.head.sha }}~1 \ + --since-commit ${{ github.event.pull_request.base.sha }} \ --branch ${{ github.event.pull_request.head.sha }} \ - --max-depth=1 \ --json \ ${{ steps.config.outputs.exclude_args }} \ --no-update 2>/dev/null || true) + # Parse JSON lines and create GitHub annotations if [ -n "$SCAN_OUTPUT" ]; then while IFS= read -r line; do + # Skip non-JSON lines (info logs) if ! echo "$line" | jq -e '.DetectorName' > /dev/null 2>&1; then continue fi FILE=$(echo "$line" | jq -r '.SourceMetadata.Data.Git.file // "unknown"') - - # Only report if file is in the changed files list - if ! echo "$CHANGED_FILES" | grep -qxF "$FILE"; then - continue - fi - LINE_NUM=$(echo "$line" | jq -r '.SourceMetadata.Data.Git.line // 1') DETECTOR=$(echo "$line" | jq -r '.DetectorName // "Secret"') VERIFIED=$(echo "$line" | jq -r '.Verified // false') if [ "$VERIFIED" == "true" ]; then VERIFIED_COUNT=$((VERIFIED_COUNT + 1)) - echo "::error file=${FILE},line=${LINE_NUM},title=${DETECTOR} [VERIFIED]::VERIFIED ACTIVE CREDENTIAL: ${DETECTOR} found in ${FILE} at line ${LINE_NUM}. Remove and rotate immediately!" + # Error annotation for verified secrets + echo "::error file=${FILE},line=${LINE_NUM},title=${DETECTOR} [VERIFIED]::VERIFIED ACTIVE CREDENTIAL: ${DETECTOR} found in ${FILE} at line ${LINE_NUM}. This secret is confirmed active. Remove and rotate immediately!" else UNVERIFIED_COUNT=$((UNVERIFIED_COUNT + 1)) + # Warning annotation for unverified secrets echo "::warning file=${FILE},line=${LINE_NUM},title=${DETECTOR} [Unverified]::Potential secret: ${DETECTOR} found in ${FILE} at line ${LINE_NUM}. Review and remove if this is a real credential." fi done <<< "$SCAN_OUTPUT" @@ -128,14 +133,17 @@ jobs: UNVERIFIED=${{ steps.parse.outputs.unverified_count || 0 }} if [ "$VERIFIED" -gt 0 ]; then + # Verified secrets found - must fail echo "has_verified=true" >> $GITHUB_OUTPUT echo "has_secrets=true" >> $GITHUB_OUTPUT echo "description=Found ${VERIFIED} verified (active) secrets - action required" >> $GITHUB_OUTPUT elif [ "$UNVERIFIED" -gt 0 ]; then + # Only unverified secrets - warn but pass echo "has_verified=false" >> $GITHUB_OUTPUT echo "has_secrets=true" >> $GITHUB_OUTPUT echo "description=Found ${UNVERIFIED} unverified potential secrets - review recommended" >> $GITHUB_OUTPUT else + # No secrets echo "has_verified=false" >> $GITHUB_OUTPUT echo "has_secrets=false" >> $GITHUB_OUTPUT echo "description=No secrets detected in PR changes" >> $GITHUB_OUTPUT @@ -154,6 +162,7 @@ jobs: const verifiedCount = '${{ steps.parse.outputs.verified_count }}' || '0'; const unverifiedCount = '${{ steps.parse.outputs.unverified_count }}' || '0'; + // Find existing comment const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, @@ -165,26 +174,38 @@ jobs: let body; if (!hasSecrets) { + // No secrets found if (existing) { - // Update to show secrets are now resolved (whether verified or unverified) - body = `${commentMarker} + // Check if existing comment was a critical/blocking one (had verified secrets) + const wasBlocking = existing.body.includes('CRITICAL') || existing.body.includes(':rotating_light:'); + if (wasBlocking) { + // Update to show verified secrets are now resolved + body = `${commentMarker} ## :white_check_mark: Secret Scanning Passed + **No secrets detected in this pull request.** + **Scanned commit:** \`${shortSha}\` ([${commitSha}](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha})) + Previous issues have been resolved. Thank you for addressing the security concerns! + --- *This comment will be updated if new secrets are detected in future commits.* `; - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existing.id, - body: body - }); + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body: body + }); + } + // If it was just a warning (unverified only), leave it as-is } + // If no existing comment and no secrets, don't post anything return; } + // Secrets found - create or update warning comment let severity, icon, action; if (hasVerified) { severity = 'CRITICAL'; @@ -198,22 +219,29 @@ jobs: body = `${commentMarker} ## ${icon} Secret Scanning ${severity} + **TruffleHog scan results:** - **Verified (active) secrets:** ${verifiedCount} ${verifiedCount > 0 ? ':x:' : ':white_check_mark:'} - **Unverified (potential) secrets:** ${unverifiedCount} ${unverifiedCount > 0 ? ':warning:' : ':white_check_mark:'} + **Scanned commit:** \`${shortSha}\` ([${commitSha}](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha})) + ${action} + ### What to do: 1. **Review the workflow annotations** - they point to exact file and line locations 2. **Remove any exposed secrets** from your code 3. **Rotate compromised credentials** - especially verified ones 4. **Push the fix** to this branch + ### Understanding Results | Type | Meaning | Action Required | |------|---------|-----------------| | **Verified** | Confirmed active credential | **Must remove & rotate** - PR blocked | | **Unverified** | Potential secret pattern | Review recommended - PR can proceed | + Check the [workflow run logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. + --- *Verified secrets are confirmed active by TruffleHog. Unverified secrets match known patterns but couldn't be validated.* `;