fix: the BOM guard was fail-open wherever xxd is not installed #798
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6a6ce36b2c |
fix(797): the twin recipe was still broken, and the mutation proof was green over a dead guard
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 9s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 18s
PR Gates / Docs update reminder (pull_request) Successful in 18s
PR Gates / decisions lifecycle (pull_request) Successful in 28s
Review verdict / Set review-verdict status (pull_request_target) Successful in 17s
PR Gates / Script tests (pytest) (pull_request) Successful in 2m6s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m19s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m42s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m19s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 5s
review-verdict/h10 Review-verdict: MERGEABLE @ 6a6ce36 (base: main)
Two independent reviews of #798. No Blocker; the functional fix is confirmed sound — one reviewer ran a 17-input matrix on BSD od, GNU od, and inside the actual CI runner image, identical in every cell, with `xxd` confirmed absent there. Everything below is what they found around it. THE FIX STOPPED AT THE HOOK. `docs/decisions/records/process/bom-format-detection-recipe.md` (active) and `docs/contributing.md:120` both still prescribed `head -c3 | xxd -p | grep -q '^efbbbf'` as the standing manual pre-push check — same absent xxd, same silent all-clean, on the path a human runs PRECISELY when the hook is being bypassed with --no-verify. Worse, that record's "Verify your detector" paragraph rejected an `od` form by name, so the active record argued against the hook this PR ships. Both corrected. The record keeps its original warning, which is still right and was never about `od` as a tool: the form that reported all-clean over 19 dirty files was `od -An -c | grep '357 273 277'` — octal character output, whose spacing and escaping vary. The replacement is `od -A n -t x1 -N 3`, hexadecimal bytes, measured across the matrix above. The record now says its own prescribed detector had been an all-clean detector for three weeks, which is the thing it was written to prevent. THE MUTATION PROOF WAS GREEN OVER A DEAD GUARD. Run against the pre-fix hook on Linux, `test_DISARMING_the_BOM_comparison_stops_detection` PASSED while the guard detected nothing at all — "the mutant is silent" is trivially true when the original is silent too. The inventory row cites that function by name. It now asserts the unmutated guard DOES detect, first. THE STAND-IN PATH STARVED THE HOOK. `_path_without_xxd` hand-listed six tools the hook never calls and omitted `tail`, which it does call for cd-detection — so a payload whose cwd differs from the repo failed open for a reason unrelated to xxd. The list is derived from the hook's own source now, with a required-set assertion so a starved PATH fails loudly instead of passing quietly. Also: the inventory narrative restated the NONE count and drifted the moment this guard was regraded, invisibly to the summary parser. The duplicate count is removed rather than corrected. Refs: #797 Decisions-Edit: yes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
4873870727 |
fix: the BOM guard was fail-open wherever xxd is not installed
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 9s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 20s
PR Gates / Docs update reminder (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 25s
review-verdict/h10 Awaiting review verdict for 4873870
Review verdict / Set review-verdict status (pull_request_target) Successful in 12s
PR Gates / Script tests (pytest) (pull_request) Successful in 2m9s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 21s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
`pretooluse-bom-guard.sh` detected a BOM with `head -c3 | xxd -p`. `xxd` ships with vim and is ABSENT on this repo's Linux CI runner — verified on the runner host — so the command substitution yielded empty, never equalled `efbbbf`, and the guard allowed every BOM in silence. It has been fail-open on any machine without vim since it was written. `od -A n -t x1 -N 3` is POSIX and byte-identical on macOS and Linux. Why nobody noticed: `docs/guard-inventory.md` graded this guard NONE — no proof it could go red — and every review of it ran on macOS, where xxd exists. The environment was a sampled population and the sample was unanimous. It surfaced only because an unrelated change (#776) added an assertion that this hook must reach a real decision, and that assertion ran on Linux. So it ships with the proof it never had: the real hook driven end to end, driven again with xxd removed from PATH (the regression), a negative control on a clean file, an anti-vacuity check that the fixture really stages a BOM, and a clause-level mutation — disarm the comparison in an isolated copy and detection must stop. Verified RED against the pre-fix hook and green against this one. The inventory row moves NONE -> MUTATION, and the "gaps ranked by what a silent failure would let through" list records that its first entry was ranked correctly for a worse reason than intended. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |