bug(test): the tier-3 credential scan fails on the branch NAME #1295
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1295
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
TestHookEnviron_dropsEveryPushCredentialUnderTier3fails on the BRANCH NAME, so any PR whose branch contains the stringdeploy-keygoes red for a reason that has nothing to do with its diff.Measured by @bosun on 2026-09-06 from the job log of
#1290, which is blocked by it.The failure
The branch is
i/1105-deploy-key-whitelist. The fixture credential value is the literal stringdeploy-key.⚠️ The scan is
strings.Containsover EVERY environment value, and the CI runner injectsFORGEJO_HEAD_REF/GITHUB_HEAD_REFcarrying the branch name. A branch named after the feature it implements collides with the fixture by construction.The assertion is right; the discriminator is not
✅ The property under test is correct and load-bearing: no push credential VALUE may reach a consumer-authored hook under any name. A key-only check would miss a value copied into a differently-named variable, which is exactly what this scan exists to catch.
🔴 But the fixture value is an ordinary English phrase. Any string that can occur incidentally in the environment makes the scan indiscriminate — and a branch name is the most likely place for it, because branches are named after the thing being built.
Fix
Use fixture values that cannot occur incidentally — a per-test sentinel with no natural-language content, e.g.
push-cred-git-8f3a1c/push-cred-single-…/push-cred-auto-….✅ This strengthens the test rather than weakening it: a sentinel makes a genuine leak unambiguous, where today a real hit and a branch-name collision render identically.
⚠️ It also fails on
alcatraz-infra's runners for any adopter branch naming, so it is not specific to this repo's conventions.AC
hookEnvironto copy a push value into a new key and watch it fire…deploy-key…no longer reddens the suiteRelated
#1106(the tier-3 separation this test guards),#1290/#1105(blocked by it today)Anchor
@bosun, 2026-09-06, read from the job log after
#1290went red on a diff that touches none of this.All three ACs ticked against PR #1298 @
635bbfe5.AC1 — collision-proof sentinels.
push-cred-git-8f3a1c,push-cred-single-4d9e2b,push-cred-auto-7a1f60, andapi-cred-narrow-c3b5d8for the credential that must survive. None can plausibly appear in a ref, a path or a hostname.🔑 Plus the part the AC does not name and the bug actually needed: a guard that makes a future collision fail HONESTLY. Before setting them, the test asserts each sentinel is absent from the ambient environment — so if one ever does collide, the failure reads "sentinel … is already present in the ambient environment — pick a new one" instead of fabricating a leak. Uniqueness is a probability; being able to tell the two apart is a construction. A sentinel scheme without that only makes the same wrong answer rarer.
AC2 — an arm asserts the scan still reddens on a genuine leak. Two pieces, because the mutation cannot be committed and the arm cannot run itself:
hookEnvironininternal/prep/hooks.goaltered to copy the git push credential's value underSOME_OTHER_NAME. Result —FAIL: a push credential value survived under another name: "SOME_OTHER_NAME=push-cred-git-8f3a1c".TestHookEnviron_theLeakScanCanActuallyFailextracts the value check asleakedValues()and exercises it both ways — a value copied under another key must be found, and an environment carrying the old colliding branch names must not fire. Without it a mistyped sentinel would pass every leak silently and the tier-3 arm would be green for the wrong reason.AC3 — a
…deploy-key…branch no longer reddens. Run with the exact failing environment:⚠️ One instrument note from doing it. The mutation run needed
-count=1: a cachedokprinted and read as "the mutation is inert" — while the mutation had not applied at all, because I was editinginternal/prep/hook_environ.go, a file that does not exist.hookEnvironlives inhooks.go. A cached result and an inert mutation are indistinguishable from the output alone, which is the same two-situations-one-rendering shape as the bug this tracker is about.✅ CLOSED —
#1298merged ate4e8a1d5. All three ACs verified againstorigin/main.🔑 THE GUARD AT :71 IS THE PART THE AC DID NOT ASK FOR AND IT IS WHAT ACTUALLY FIXES THE BUG:
Before setting them, the test asserts each sentinel is ABSENT from the ambient environment — so a future collision reports "pick a new sentinel" instead of fabricating a leak. ✅ A sentinel swap alone would have been a longer fuse; this is a different failure mode with a different, honest report.
📌 And
leakedValuesextracted as a named function is what makes AC2 possible at all — the scan can now be positive-controlled in both directions rather than only observed passing.The verification, end to end
AC2 needed both halves recorded because the mutation cannot be committed and the arm cannot run itself: the mutation WAS run, and
TestHookEnviron_theLeakScanCanActuallyFailis the permanent positive control.📌 The original defect, for the record: the fixture value was the literal
deploy-key, the branch wasi/1105-deploy-key-whitelist, and the runner injects it asFORGEJO_HEAD_REF/GITHUB_HEAD_REF. A branch named after the feature it implements collided by construction.✅ The ASSERTION was never wrong — no push credential VALUE may reach a hook under any name, and a key-only check would miss a value copied into a differently-named variable. The DISCRIMINATOR was: an ordinary English phrase cannot tell a credential from a branch name.
⚠️ One instrument note from the fix, worth keeping: the mutation run needed
-count=1. A cachedokread as "the mutation is inert" while the mutation had NOT APPLIED AT ALL — the edit went tointernal/prep/hook_environ.go, a file that does not exist;hookEnvironlives inhooks.go. A cached result and an inert mutation are indistinguishable from the output alone.📌 Same shape as the defect itself: two situations rendering identically, fixed by a construction that separates them rather than by care.
#1290unblocks.