From ff272158ccdd8227a4318a95056816fbd51647bf Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 12:13:08 +0000 Subject: [PATCH 1/2] fix(secret-scanner): stage the estate baseline only for repos without a local config The ungated "Fetch/Stage estate gitleaks baseline" steps copied .gitleaks-estate.toml into every caller's workspace. A repo with its own .gitleaks.toml scans with that config; if it does not [extend] the baseline, the staged file sits in the scanned tree with no allowlist for the fixture values its comments quote, and the gate reports the estate file as the caller's leak (echidnabot#185: three generic-api-key findings, lines 84-85). Gate both steps on hashFiles('.gitleaks.toml') == ''. Repos without a local config are unchanged (CONFIG still resolves to the staged baseline); repos that [extend] it are still staged by the existing gated block. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3 --- .github/workflows/secret-scanner-reusable.yml | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/secret-scanner-reusable.yml b/.github/workflows/secret-scanner-reusable.yml index 2eee815b..2a43a680 100644 --- a/.github/workflows/secret-scanner-reusable.yml +++ b/.github/workflows/secret-scanner-reusable.yml @@ -174,14 +174,22 @@ jobs: # a repo-specific blind spot stays local to the repo that justified it # instead of widening the allowlist for all 400+. # - # THIS STEP IS UNGATED ON PURPOSE. It is the only thing that creates - # `.gitleaks-estate.toml` for a consumer with no `.gitleaks.toml` of its - # own — the large majority — and that is exactly the consumer whose - # CONFIG resolves to that file in the scan step below. Do not delete it - # as a duplicate of the gated "Estate baseline — is it referenced?" - # block further down; that block fires only for repos that DO have a - # local config, so removing this one leaves CONFIG naming a file nothing - # creates, across most of the estate. + # THIS STEP RUNS FOR EVERY CONSUMER WITHOUT A `.gitleaks.toml`. It is the + # only thing that creates `.gitleaks-estate.toml` for that consumer — the + # large majority — and that is exactly the consumer whose CONFIG resolves + # to that file in the scan step below. Do not delete it as a duplicate of + # the gated "Estate baseline — is it referenced?" block further down; + # that block fires only for repos that DO have a local config, so + # removing this one leaves CONFIG naming a file nothing creates, across + # most of the estate. + # + # It is skipped when the repo HAS a `.gitleaks.toml`. That repo scans + # with its own config, and the gated block below stages the baseline + # only if that config `[extend]`s it. Staged anyway, the baseline sat + # inside the scanned tree under a config that does not allowlist the + # fixture values its own comments quote, and the gate reported the + # estate file as the caller's leak (echidnabot#185: three + # generic-api-key findings in .gitleaks-estate.toml). # # `ref` was `main` until 2026-09-04, and that was worse than a moving # pin: the file this step fetches has been RENAMED under it. Before @@ -196,6 +204,7 @@ jobs: # stood at the SHA it pins, and the path each SHA references exists at # that SHA (verified for all six gen-1 SHAs, 2026-09-04). - name: Fetch estate gitleaks baseline + if: hashFiles('.gitleaks.toml') == '' uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: hyperpolymath/standards @@ -207,6 +216,7 @@ jobs: persist-credentials: false - name: Stage estate gitleaks baseline + if: hashFiles('.gitleaks.toml') == '' run: | set -euo pipefail # Stage THE estate baseline, not standards' own repo config. From f206a94ceaf2cb7d7ebe4bf90be4bce0015ebe41 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 13:02:24 +0000 Subject: [PATCH 2/2] fix(secret-scanner): recognise a single-quoted [extend] path TOML literal strings are single-quoted, and gitleaks reads extend.path as a plain string, so `path = '.gitleaks-estate.toml'` is a valid reference. The detection matched only the double-quoted spelling. With the ungated staging now skipped for repos that have a .gitleaks.toml, such a repo would have scanned with an [extend] pointing at a file nothing staged. Accept either quote. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3 --- .github/workflows/secret-scanner-reusable.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/secret-scanner-reusable.yml b/.github/workflows/secret-scanner-reusable.yml index 2a43a680..c553cf60 100644 --- a/.github/workflows/secret-scanner-reusable.yml +++ b/.github/workflows/secret-scanner-reusable.yml @@ -269,7 +269,7 @@ jobs: run: | set -euo pipefail if [ -f .gitleaks.toml ] && \ - grep -qE '^[[:space:]]*path[[:space:]]*=[[:space:]]*"\.gitleaks-estate\.toml"' .gitleaks.toml; then + grep -qE "^[[:space:]]*path[[:space:]]*=[[:space:]]*[\"']\.gitleaks-estate\.toml[\"']" .gitleaks.toml; then echo "referenced=true" >> "$GITHUB_OUTPUT" echo "This repo extends the estate baseline; staging it." else