From ac52fde3fad16b42c5666d0665d33905a50dc3c3 Mon Sep 17 00:00:00 2001 From: jeffreyhung <17494876+Jeffreyhung@users.noreply.github.com> Date: Fri, 11 Sep 2026 09:24:52 -0700 Subject: [PATCH 1/5] skip the scan if setup steps failed, failed quietly --- .github/workflows/secret-scan.yml | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index 1300e88..b01cd0c 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -13,10 +13,14 @@ jobs: - name: Checkout Code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Cosign + id: cosign + continue-on-error: true # v4 of the action install v3 of the CLI. v4 of the CLI will deprecate some features so be aware. uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Pin Trufflehog to a known good release id: trufflehog_release + if: ${{ steps.cosign.outcome == 'success' }} + continue-on-error: true shell: bash env: GH_TOKEN: ${{ github.token }} @@ -35,7 +39,7 @@ jobs: done if [[ -z "$LATEST_TAG_NAME" ]]; then - echo "::error::No usable TruffleHog release found" + echo "::warning::No usable TruffleHog release found" exit 1 fi @@ -43,11 +47,14 @@ jobs: echo "latest_tag_name=$LATEST_TAG_NAME" >> "$GITHUB_OUTPUT" echo "latest_release=${LATEST_TAG_NAME#v}" >> "$GITHUB_OUTPUT" - name: Download and verify TruffleHog release + id: download + if: ${{ steps.trufflehog_release.outcome == 'success' }} + continue-on-error: true run: | - curl -fsSL --retry 8 --retry-max-time 120 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt - curl -fsSL --retry 8 --retry-max-time 120 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.pem - curl -fsSL --retry 8 --retry-max-time 120 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.sig - curl -fsSL --retry 8 --retry-max-time 120 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_linux_amd64.tar.gz + curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt + curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.pem + curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.sig + curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_linux_amd64.tar.gz cosign verify-blob trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt \ --certificate trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.pem \ @@ -57,10 +64,13 @@ jobs: sha256sum --ignore-missing -c trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt - name: Extract TruffleHog + id: extract + if: ${{ steps.download.outcome == 'success' }} run: | tar xzf trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_linux_amd64.tar.gz -C /usr/local/bin chmod +x /usr/local/bin/trufflehog - name: Run TruffleHog scan + if: ${{ steps.extract.outcome == 'success' }} continue-on-error: true id: scan run: | @@ -70,6 +80,7 @@ jobs: trufflehog git file://. --only-verified --github-actions --fail --exclude-detectors="datadogtoken,lob" fi - name: Send Alert to SIEM + if: ${{ always() && !cancelled() }} id: alert env: SIEM_WEBHOOK_URL: ${{ vars.SECRET_SCAN_SIEM_WEBHOOK_URL }} @@ -94,9 +105,15 @@ jobs: pull_request="" fi + if [[ "$SCAN_OUTCOME" == "skipped" ]]; then + status="setup_failed" + else + status="$SCAN_OUTCOME" + fi + jq -n \ --arg event "github_secret_scanning" \ - --arg status "$SCAN_OUTCOME" \ + --arg status "$status" \ --arg createdAt "$created_at" \ --arg repo "$REPO" \ --arg pull_request "$pull_request" \ From 3928ad966dbf17e361e4bd5a5aa06d241f18fde1 Mon Sep 17 00:00:00 2001 From: jeffreyhung <17494876+Jeffreyhung@users.noreply.github.com> Date: Fri, 11 Sep 2026 09:45:46 -0700 Subject: [PATCH 2/5] clean up and improvement on readability --- .github/workflows/secret-scan.yml | 40 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index b01cd0c..bee9611 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -6,9 +6,6 @@ jobs: runs-on: ubuntu-latest permissions: contents: "read" - outputs: - latest_release: ${{ steps.trufflehog_release.outputs.latest_release }} - latest_tag_name: ${{ steps.trufflehog_release.outputs.latest_tag_name }} steps: - name: Checkout Code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -21,7 +18,6 @@ jobs: id: trufflehog_release if: ${{ steps.cosign.outcome == 'success' }} continue-on-error: true - shell: bash env: GH_TOKEN: ${{ github.token }} run: | @@ -50,38 +46,48 @@ jobs: id: download if: ${{ steps.trufflehog_release.outcome == 'success' }} continue-on-error: true + env: + TRUFFLEHOG_TAG: ${{ steps.trufflehog_release.outputs.latest_tag_name }} + TRUFFLEHOG_VERSION: ${{ steps.trufflehog_release.outputs.latest_release }} run: | - curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt - curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.pem - curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.sig - curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors -w '%{url_effective} %{http_code}\n' -O https://github.com/trufflesecurity/trufflehog/releases/download/${{ steps.trufflehog_release.outputs.latest_tag_name }}/trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_linux_amd64.tar.gz + base="https://github.com/trufflesecurity/trufflehog/releases/download/${TRUFFLEHOG_TAG}" + for file in \ + "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" \ + "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt.pem" \ + "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt.sig" \ + "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" + do + curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \ + -w '%{url_effective} %{http_code}\n' -O "${base}/${file}" + done - cosign verify-blob trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt \ - --certificate trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.pem \ - --signature trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt.sig \ + cosign verify-blob "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" \ + --certificate "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt.pem" \ + --signature "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt.sig" \ --certificate-identity-regexp 'https://github\.com/trufflesecurity/trufflehog/\.github/workflows/.+' \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" - sha256sum --ignore-missing -c trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_checksums.txt + sha256sum --ignore-missing -c "trufflehog_${TRUFFLEHOG_VERSION}_checksums.txt" - name: Extract TruffleHog id: extract if: ${{ steps.download.outcome == 'success' }} + env: + TRUFFLEHOG_VERSION: ${{ steps.trufflehog_release.outputs.latest_release }} run: | - tar xzf trufflehog_${{ steps.trufflehog_release.outputs.latest_release }}_linux_amd64.tar.gz -C /usr/local/bin + tar xzf "trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" -C /usr/local/bin chmod +x /usr/local/bin/trufflehog - name: Run TruffleHog scan if: ${{ steps.extract.outcome == 'success' }} continue-on-error: true id: scan run: | + args=(git file://. --only-verified --github-actions --fail --exclude-detectors="datadogtoken,lob") if [ -e .secret_scan_ignore ]; then - trufflehog git file://. --only-verified --github-actions --fail --exclude-paths=.secret_scan_ignore --exclude-detectors="datadogtoken,lob" - else - trufflehog git file://. --only-verified --github-actions --fail --exclude-detectors="datadogtoken,lob" + args+=(--exclude-paths=.secret_scan_ignore) fi + trufflehog "${args[@]}" - name: Send Alert to SIEM if: ${{ always() && !cancelled() }} - id: alert env: SIEM_WEBHOOK_URL: ${{ vars.SECRET_SCAN_SIEM_WEBHOOK_URL }} SCAN_OUTCOME: ${{ steps.scan.outcome }} From c12f59c32908dad2027a391d58d6919c9bd48c6d Mon Sep 17 00:00:00 2001 From: jeffreyhung <17494876+Jeffreyhung@users.noreply.github.com> Date: Fri, 11 Sep 2026 09:58:46 -0700 Subject: [PATCH 3/5] fix logic gate for final step --- .github/workflows/secret-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index bee9611..44ae7f2 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -131,5 +131,5 @@ jobs: "$SIEM_WEBHOOK_URL" \ || echo "::warning::SIEM alert failed (non-blocking)" - name: Fail workflow if secret detected - if: ${{ !cancelled() && steps.scan.outcome != 'success' }} + if: ${{ !cancelled() && steps.scan.outcome == 'failure' }} run: exit 1 From d800b5d8dba85bbe51132722252d24fd995c013c Mon Sep 17 00:00:00 2001 From: geoffg-sentry <165922362+geoffg-sentry@users.noreply.github.com> Date: Fri, 11 Sep 2026 13:15:59 -0400 Subject: [PATCH 4/5] fix(secret-scan): annotate the PR when the scan is skipped A setup failure now leaves a green check, so without an annotation there is no sign on the PR that the change went unscanned. Report which stage broke. Co-Authored-By: Claude Opus 5 Co-authored-by: Cursor --- .github/workflows/secret-scan.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index 44ae7f2..ab8848b 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -86,6 +86,15 @@ jobs: args+=(--exclude-paths=.secret_scan_ignore) fi trufflehog "${args[@]}" + - name: Report scan skipped + if: ${{ !cancelled() && steps.scan.outcome == 'skipped' }} + env: + COSIGN_OUTCOME: ${{ steps.cosign.outcome }} + RELEASE_OUTCOME: ${{ steps.trufflehog_release.outcome }} + DOWNLOAD_OUTCOME: ${{ steps.download.outcome }} + EXTRACT_OUTCOME: ${{ steps.extract.outcome }} + run: | + echo "::warning::TruffleHog unavailable, this change was not scanned: cosign=$COSIGN_OUTCOME release=$RELEASE_OUTCOME download=$DOWNLOAD_OUTCOME extract=$EXTRACT_OUTCOME" - name: Send Alert to SIEM if: ${{ always() && !cancelled() }} env: From 52a2292c4d2de0663ca97d09c8ed390a4e0b9d05 Mon Sep 17 00:00:00 2001 From: geoffg-sentry <165922362+geoffg-sentry@users.noreply.github.com> Date: Fri, 11 Sep 2026 13:18:29 -0400 Subject: [PATCH 5/5] ci(secret-scan): drop redundant always() from the SIEM condition always() is true even when cancelled, so ANDing it with !cancelled() reduces to !cancelled(), which is the form GitHub recommends. Co-Authored-By: Claude Opus 5 Co-authored-by: Cursor --- .github/workflows/secret-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index ab8848b..c753664 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -96,7 +96,7 @@ jobs: run: | echo "::warning::TruffleHog unavailable, this change was not scanned: cosign=$COSIGN_OUTCOME release=$RELEASE_OUTCOME download=$DOWNLOAD_OUTCOME extract=$EXTRACT_OUTCOME" - name: Send Alert to SIEM - if: ${{ always() && !cancelled() }} + if: ${{ !cancelled() }} env: SIEM_WEBHOOK_URL: ${{ vars.SECRET_SCAN_SIEM_WEBHOOK_URL }} SCAN_OUTCOME: ${{ steps.scan.outcome }}