Repository navigation
Conversation
… histories
Two defects in `range_secret_scan`, both found the same day by four separate
repositories being onboarded with sscsb — ADE-Bootstrapper, flawde-submission-
sample, VCF and OCEAN all hit them.
1. The range scan never read `[controls.secrets]`. The pre-commit path,
`run_secret_scan_staged`, reads `control_opt_bool("secrets", "trufflehog")` and
`"gitleaks"` before deciding what to run; the pre-push range path beside it read
neither and ran whichever tool happened to be on PATH. A repository that had
turned gitleaks OFF in its own `.sscsb/config.toml` was still gitleaks-scanned
on every push, and blocked by the tool it had explicitly disabled. A gate that
contradicts the config file it ships with is not enforcing policy; it is
overriding it. `range_secret_scan` now takes the `Config` and honours both
switches the same way, including the degrade messages and the fail-closed
"nothing could run" bail the pre-commit path already had.
2. A branch with no remote counterpart had its ENTIRE history scanned as if it
were outgoing. A new branch arrives on pre-push stdin with the zero sha as
`remote_sha`, and both scanners read that literally as "no lower bound":
gitleaks got `--log-opts=<tip>`, which is every commit reachable from the tip,
and trufflehog got no `--since-commit` at all. OCEAN's reproduction is the shape
that matters — the real outgoing range (`f565d53..b50b020`) was clean under both
scanners, while the actual `git push` on that same new branch raised ~20
gitleaks findings out of years-old strings in vendored Go source and lockfile
digests that appear nowhere in the diff being pushed. Blocking a legitimate push
over content the push does not contain is how a team learns to reach for
`--no-verify`, which costs far more than those findings were ever worth.
The range is now bounded by `<tip> --not --remotes`: everything reachable from
the tip that is not already on a remote-tracking ref. That is the definition
`commits_in_range` already used for the signing gate, so the two pre-push gates
now answer for one range rather than two different ones. TruffleHog takes a
single commit rather than a revision set, so `range_since_commit` bounds it by
the first parent of the oldest unpublished commit — the point the branch was cut
from — and leaves it unbounded only when the outgoing range genuinely reaches a
root commit, where the branch really is its own whole history.
Both fixes carry a regression test, and both tests were verified RED against the
pre-fix logic before being accepted. With the config read reverted, the gitleaks
test reports the shim being invoked with a full argv despite `gitleaks = false`.
With the range bound reverted, the new-branch test resolves `--log-opts` through
git itself and gets all 6 commits in the fixture where 2 are outgoing. The
config test asserts in both directions on purpose: the "did not run" half alone
would pass just as happily if the fake scanner were never reachable on PATH,
which is a vacuous green. Both tests drive `range_secret_scan` directly rather
than through the `pre_push` wrapper, because they install fake scanners on PATH
and must own the environment lock across the whole call — `with_env` and
`serialized` both acquire that lock and it is not reentrant, per the composition
rules in src/testutil.rs.
AI-Assisted: true
AI-Tool: Claude Code
AI-Model: claude-sonnet-5
AI-Role: draft
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm
rustls 0.23.41 -> 0.23.45 and rustls-webpki 0.103.13 -> 0.103.15. The advisory was published after this branch's last CI run; osv-scanner flagged it on the next one. AI-Assisted: true AI-Tool: Claude Code AI-Model: Opus 5.5 AI-Role: draft AI-Dependency-Review: approved Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012hwWMsTiv9Uf2gNbMh75uk
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. Ignoring alerts on:
|
Socket alert triage:
|
|
@SocketSecurity ignore cargo/rustls@0.23.45 |
Root cause fix for a defect that surfaced in four downstream repositories
While onboarding four repositories with
sscsbon 2026-09-12 — ADE-Bootstrapper, flawde-submission-sample, VCF and OCEAN — all four hit the same two defects inrange_secret_scan(src/hooks.rs, the pre-push path). This is the upstream fix, not a per-repo workaround. No repository's secrets policy is changed by this PR;.sscsb/config.tomlis untouched.1. The range scan never read
[controls.secrets]The pre-commit path,
run_secret_scan_staged, readscfg.control_opt_bool("secrets", "trufflehog")and"gitleaks"before deciding what to run. The pre-push range path beside it read neither, and ran whichever tool happened to be onPATH.So a repository with
gitleaks = falsein its own.sscsb/config.tomlwas still gitleaks-scanned on every push — and blocked by the tool it had explicitly turned off. A gate that contradicts the config file it ships with is not enforcing policy, it is overriding it.range_secret_scannow takes theConfigand honours both switches exactly as the pre-commit path does, including the per-tool degrade messages and the fail-closed "no secret scanner ran" bail when nothing is left to run.2. A new branch had its entire history scanned as if it were outgoing
A branch with no remote counterpart arrives on pre-push stdin with the zero sha as
remote_sha. Both scanners read that literally as "no lower bound":--log-opts=<tip>— every commit reachable from the tip--since-commitat allOCEAN's reproduction is the shape that matters. The real outgoing range (
f565d53..b50b020) was clean under both scanners, while the actualgit pushon that same new branch raised ~20 gitleaks findings out of years-old strings in vendored Go source and lockfile digests that appear nowhere in the diff being pushed. Blocking a legitimate push over content the push does not contain is how a team learns to reach for--no-verify, which costs far more than those findings were ever worth.The range is now bounded by
<tip> --not --remotes: everything reachable from the tip that is not already on a remote-tracking ref. That is the definitioncommits_in_rangealready used for the signing gate, so the two pre-push gates now answer for one range rather than two different ones.TruffleHog takes a single commit rather than a revision set, so the new
range_since_commitbounds it by the first parent of the oldest unpublished commit — the point the branch was cut from — and leaves it unbounded only when the outgoing range genuinely reaches a root commit, where the branch really is its own whole history.Tests
Two regression tests in
hooks::tests, both verified RED against the pre-fix logic before being accepted (the production logic was reverted in place, keeping the tests compiling, and re-run):the_pre_push_range_scan_obeys_the_secrets_control_switches[controls.secrets] gitleaks = false must keep gitleaks out of the pre-push range scan, but it was invoked with ["version", "git", …, "--log-opts=9d56ed6… --not --remotes", "--report-format", "json", "--report-path", …]a_brand_new_branch_scans_only_its_own_commits_not_the_whole_historyleft(6 commits, the whole fixture history) vsright(the 2 that are actually outgoing)Notes on their construction:
PATH— a vacuous green — so the first half proves the shim is wired before the second half proves the switch is honoured.git rev-listitself, not on the spelling of the--log-optsargument. It builds a real repo: four commits published torefs/remotes/origin/main, then a feature branch with two more.range_secret_scandirectly rather than through thepre_pushwrapper, because they install fake scanners onPATHand must own the environment lock across the whole call.with_envandserializedboth acquire that lock and it is not reentrant, so nesting them would panic by design — the composition rules documented insrc/testutil.rs.tools::detect's version probe, so "was it invoked at all" is distinguishable from "was it probed".Verification
cargo fmt --checkclean,cargo clippy --all-targetsclean.cargo test: 950 passed / 9 failed, against a clean-mainbaseline on the same machine of 949 passed / 8 failed. The delta is exactly the two new tests, both passing.hooks::plus onesigners::test fail witherror: 1Password: invalid ssh public key … fatal: failed to write commit object, because this machine's globalgpg.ssh.programpoints at 1Password'sop-ssh-sign, which rejects the tests' own ephemeral SSH keys.signing_setup::tests::setup_agent_refuses_identity_blur_and_writes_nothing, is a pre-existing flake unrelated to this change — reproduced 8 times in 10 runningcargo test --lib -- signing_setupalone, with nohooks::test in the run at all. It reads the real machine'sgit config --global user.emailviagit_globalwhile holding no environment lock, thensetup_agent_claude_codereads it a second time; a siblingFakeMachinefixture repointingGIT_CONFIG_GLOBALbetween those two reads makes the guard see two different values. That is exactly the documented race class insrc/testutil.rs. Worth its own PR; deliberately out of scope here.Scope
.sscsb/config.tomland this repository's own secrets-control policy are untouched. This is a code-correctness fix, independent of any policy question about where gitleaks stays enabled.🤖 Generated with Claude Code
https://claude.ai/code/session_017N6Qc2T7buVAXHZ9vYa1xm