Repository navigation
fix(scan): let the history scan see every path, and make the SOPS check read the values - #1187
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The self-test mode currently accepts trailing arguments despite the documented rejection requirement.
1 open finding
What changed in this PR
Splits Gitleaks configurations by scan scope and strengthens SOPS ciphertext validation.
Changes:
- Uses a dedicated working-tree Gitleaks configuration while keeping history scans unrestricted.
- Validates SOPS values and adds fixture-based self-tests.
- Documents the security rationale and historical exposure implications.
| File | Description |
|---|---|
.gitleaks.toml |
Removes gitignored-path exclusions from history scans. |
.gitleaks-worktree.toml |
Adds working-tree-only path exclusions. |
.github/workflows/ci.yml |
Uses the worktree configuration in CI. |
Makefile |
Separates worktree and history scan configurations. |
scripts/validate.sh |
Uses the worktree configuration locally. |
scripts/check-tracked-artefacts.sh |
Updates configuration-split documentation. |
scripts/check-sops-encrypted.sh |
Validates ciphertext values and adds fixtures. |
docs/security.md |
Records the stricter history-scan behavior. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ck read the values Two checks that claimed more than they proved. gitleaks path allowlists apply to every commit a history scan walks, not only to the working tree. .gitleaks.toml allowlisted certificates/, .rendered/, .env and the installed Ansible collections so a deployed host's `make validate` stays green, and the same file fed the history scan — so the purged CA key under certificates/ was exactly the path the scan docs/security.md calls the evidence of the purge could never report. The gitignored paths move to .gitleaks-worktree.toml, which extends .gitleaks.toml and is what the working-tree scans read; the history scan keeps .gitleaks.toml, now with no allowlist for anything gitignored. scripts/check-tracked-artefacts.sh is still what keeps those paths out of the tree, and in history a tracked copy is now a finding as well. scripts/check-sops-encrypted.sh passed any file carrying a `sops:` block. A value pasted back in the clear leaves the block in place, passes gitleaks (the ciphertext is path-allowlisted), and `make render` would copy it through. It now also requires every value above the block to be ENC[...], in POSIX awk because the hosts run mawk, with a failed read counted as a failure and eleven fixtures under --self-test, which scripts/self-tests.sh discovers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013Dchg9vmfKeQd7uzRzPcLR
Gerrrt
force-pushed
the
review/gitleaks-history-sees-every-path
branch
from
October 14, 2026 05:19
1033681 to
e2dcb69
Compare
`--self-test bogus` ran the fixtures and exited 0; the usage guard below only saw an argument that was not --self-test. Review finding on #1187. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013Dchg9vmfKeQd7uzRzPcLR
4 of 6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What changed
Two verification checks that claimed more than they proved, found during a repository review.
gitleaks. The path allowlists for gitignored files (
.rendered/,certificates/,.env,ansible/.ansible/,ansible/.collections/) move out of.gitleaks.tomlinto a new.gitleaks-worktree.toml, which[extend]s it. The working-tree scans (make scan's first line,scripts/validate.sh, the workflow's "gitleaks — working tree" step) now read the worktree file. The history scan (scripts/gitleaks-history.sh, untouched) keeps reading.gitleaks.toml, which no longer allowlists anything gitignored. Comments in.gitleaks.toml,ci.ymlandscripts/check-tracked-artefacts.shsay why, anddocs/security.md§ Known historical exposure records the change under its "a history scan that passes is the evidence the purge worked" sentence.SOPS.
scripts/check-sops-encrypted.shnow also requires every value above thesops:block to beENC[...], not only that the block exists. It gains--self-testwith eleven fixtures, whichscripts/self-tests.shdiscovers automatically, and rejects any other argument.Why
A gitleaks path allowlist applies to every commit a history scan walks, not only to the working tree. With
certificates/allowlisted in the one shared config, the purged CA key named inSECURITY.mdwould never have been reported if it reappeared in history, yetdocs/security.mdcites the passing history scan as the evidence the purge worked. The repo's own comment on the Ansible paths already noted that "an allowlisted path is invisible to the history scan as well"; this makes that true only of the working tree.The SOPS check tested for the metadata block alone. A value pasted back in the clear leaves the block in place, so such a file passed this check, passed gitleaks (
secrets/*.sops.yamlis path-allowlisted there because ciphertext trips the entropy rules), andmake renderwould have copied it through. sops itself refuses the file on its MAC, but only on a host holding the key, which the push does not.Blast radius
None at runtime.
make validateon a deployed host behaves as before: the worktree config carries the same allowlists the shared file did. The history scan becomes stricter, which on a clean history changes nothing.secrets/*.sops.yamlVerification
Run here (no Docker daemon, so gitleaks itself could not be run; CI's two scans are the test of the config split):
The awk is POSIX (the hosts run mawk; the first draft used a gawk-only
match()form, which mawk rejected and which would have passed every file silently, so a failed read is now itself a failure).make validatepasses (CI)prometheuswill run the newvalidate.sh)docs/security.md)🤖 Generated with Claude Code
https://claude.ai/code/session_013Dchg9vmfKeQd7uzRzPcLR
Generated by Claude Code