feat(gitleaks): make the estate baseline shareable instead of copy-only - #596
Conversation
The estate baseline could not be inherited, only duplicated. A consumer repo wanting the shared allowlist had to copy it (copies drift), or push its own repo-specific entries into the shared file (which blinds all 400+ repositories). There was no third option, because the sharing mechanism did not exist. stapeln #21 is what surfaced this. It ships a well-reasoned config that does `[extend] path = ".gitleaks-estate.toml"` on the stated premise that this workflow stages that file. It does not, and never did, so gitleaks aborts before scanning anything: FTL failed to load extended config, err: open .gitleaks-estate.toml: no such file or directory That is worse than a missing feature: the config loads nothing, the scan runs on no files, and the failure looks like a findings failure. WHAT THIS ADDS - config/gitleaks/estate-baseline.toml — the shared baseline, moved out of this repo's root .gitleaks.toml (git mv, history preserved). Only universally-true entries belong here. - .gitleaks.toml here is now a four-line consumer of it. Deliberate dogfooding: the mechanism is exercised by standards' own scan, so a change that breaks consumers breaks us first. - secret-scanner-reusable.yml stages the baseline as .gitleaks-estate.toml in the consumer workspace, but ONLY when the repo's config actually references it. A repo that does not extend it gains nothing in its scanned tree, so this is a no-op for every existing caller. - docs/GITLEAKS-ESTATE-BASELINE.adoc. TWO THINGS VERIFIED RATHER THAN ASSUMED `[extend] path` resolves against the process working directory, not the config file's directory. Tested directly: the same relative path resolves from the repo root and fails from a subdirectory. That is why the baseline is staged at the workspace root, and it confirms the premise #21 was written against. Moving the baseline out of the root made it scannable. As `.gitleaks.toml` gitleaks excluded it automatically as its own config; at its new path it is an ordinary file, and its documented placeholder shapes immediately tripped generic-api-key. Caught by scanning before and after the move: 9 findings before, 10 after, 9 again once both the canonical path and the staged name were allowlisted. Zero regressions. Pinned by construction: the baseline is fetched at github.job_workflow_sha, the commit of this workflow, so a caller pinned to an old SHA gets that SHA's baseline. The workflow and its baseline cannot disagree. Fails loudly: if the baseline is referenced but cannot be fetched, the job errors rather than scanning with a silently reduced config. A scan that quietly loses its allowlist produces a wall of false positives, and the usual response to that is to switch the gate off -- which is the history this file already records. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Note Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime. Code Review ✅ ApprovedMakes the Gitleaks estate baseline shareable via
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Important Your trial ends in 3 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
main moved under this branch. #597 ("close the baseline/alert split and stop the SPDX check fighting the lockfile") rewrote both files this branch touches, so the conflict is real rather than textual. Both conflicts were additive and both sides are kept: .gitleaks.toml -- #597 added a substantial measured finding to the baseline: gitleaks 8.18.4 matches allowlist `regexes` against the whole MATCH, not the extracted secret, and `regexTarget` does not change it, so an anchored `^value$` entry is silently INERT for generic-api-key (the estate's largest false-positive source). That documentation is preserved verbatim -- it now lives in config/gitleaks/estate-baseline.toml, where it reaches every repo that extends the baseline instead of only this one. The root .gitleaks.toml remains the thin consumer. secret-scanner-reusable.yml -- #597 added a comment explaining why --verbose is required (without it the gate blocks a merge while telling the author nothing, which is how 154 false positives sat untriaged across eleven repositories). Kept, alongside the estate-baseline staging steps. Verified in a clean worktree, same tree, both configs: main's config: 4 findings this branch: 3 findings regressions: NONE difference: the baseline file no longer flags itself Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|



The estate gitleaks baseline could not be inherited, only duplicated. This adds the sharing mechanism that several repos already assume exists.
The problem
A consumer repo wanting the shared allowlist had two options, both bad:
There was no third option, because the mechanism did not exist.
metadatastician/stapeln#21 is what surfaced it. It ships a well-reasoned config doing
[extend] path = ".gitleaks-estate.toml", on the stated premise that this workflow stages that file. It does not, and never did:That is worse than a missing feature. The config loads nothing, the scan runs over no files at all, and the failure presents as a findings failure — a scanner that appears to be working and is scanning nothing.
What this adds
config/gitleaks/estate-baseline.tomlgit mvd out of this repo's root config so history is preserved. Only universally-true entries belong here..gitleaks.toml(this repo)standards' own scan, so a change that breaks consumers breaks us first.secret-scanner-reusable.yml.gitleaks-estate.toml, only when the repo's config actually references it.docs/GITLEAKS-ESTATE-BASELINE.adocThis is a no-op for every existing caller. A repo that does not reference the baseline gains nothing in its scanned tree.
Two things verified rather than assumed
1.
[extend] pathresolves against the process working directory — not the config file's directory. Tested directly: the same relative path resolves from the repo root and fails from a subdirectory. That is why the baseline is staged at the workspace root, and it confirms the premise #21 was written against was correct.2. Moving the baseline made it scannable. As
.gitleaks.tomlgitleaks excluded it automatically as its own config. At its new path it is an ordinary file, and its documented placeholder shapes immediately trippedgeneric-api-key— a finding caused purely by renaming the file.Caught by scanning before and after:
Both the canonical path and the staged
.gitleaks-estate.tomlare now in the baseline's ownpaths. If it moves again, those entries move with it.Design notes
Pinned by construction. The baseline is fetched at
${{ github.job_workflow_sha }}— the commit of this reusable workflow — so a caller pinned to an old SHA gets that SHA's baseline. The workflow and the baseline it stages can never disagree, and there is no moving@mainfetch.The checkout is removed before scanning. Otherwise
standards' own tree is scanned as if it were the caller's, which is how a shared config turns into a wall of someone else's findings.Failure is loud. If the baseline is referenced but cannot be fetched, the job errors rather than scanning with a silently reduced config. A scan that quietly loses its allowlist produces a wall of false positives, and the usual response to that is to switch the gate off — which is exactly the history this file already records from before #500.
Verification
Unrelated pre-existing local edits in this checkout were deliberately left unstaged; this PR touches four files.
Follow-up
Once this lands, stapeln#21 becomes viable as written — its estate-extension approach and its documentation discipline ("each entry names what the value is"; plant a canary and confirm it is still detected) are better than the
useDefault-plus-local-paths approach currently proposed in stapeln#20.🤖 Generated with Claude Code
Summary by Gitar
ZIGZAG-TESTING.mdandZIGZAG-TESTING.adocdefining aspect-oriented testing methodologyTEST-NEEDS.mdto require Zigzag Testing for CRG Grade B/AThis will update automatically on new commits.