This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

2026-08-01 — itd-105 / spc-21, FOURTH round: two fresh independent reviews of the seam-removal fix pass above (one security, one correctness) both returned MERGE, each naming a short list of cheap items rather than a blocker — three rounds of BLOCK was not treated as licence to manufacture a fourth by inflating what these were. All were landed on this branch directly rather than deferred, since none needed a fresh review cycle to verify. (1) The structural regression test guarding the seam removal, `TestBootstrapFetchOriginsAreConstants`, was a DENYLIST — it scanned for `${`, `$ABCD`, `$HTTP`, `$CURL` — so a bypass renamed to any other variable (`$GH_MIRROR` was the reviewer's example) would satisfy it while still redirecting a fetch; reproduced by planting exactly that shape against the committed script and watching the old test pass regardless. Replaced with an ALLOWLIST: every `$NAME`/`${NAME}` reference in the script, after subtracting names the script assigns to itself, must be `CLAUDE_PLUGIN_ROOT` and nothing else — verified this catches the planted `$GH_MIRROR` bypass and passes on the real script. (2) `safe()`'s `tr -d` range stripped ESC and other C0 controls but not CR (`\015`) or DEL (`\177`); a bare CR overprints from column zero, the exact attack class `internal/termsafe`'s own doc comment names, and DEL is the same family. Range widened to `\000-\010\013-\037\177` (keeps only tab and newline, as before); the existing control-character test now plants CR and DEL alongside ESC in the same specimen and watches both survive the pre-fix range before the widened one strips them. (3) `mv -f` onto an existing DIRECTORY at `$binary` moves the downloaded file INTO the directory rather than replacing it — reproduced: the script reported success, exited 2, wrote a truthful-looking `.binary-meta`, and the binary landed at `$binary/abcd-<os>-<arch>` while the hooks stayed broken forever, since the fast path's `[ -f ]` check never becomes true. A guard now refuses before any download when `$binary` exists and is not a regular file; the existing directory-fast-path test was tightened to assert the actual refusal (it had previously accepted a substring of the SUCCESS message as if it proved a refusal happened, which is why the bug had a green test). (4) `plugin_root_basename`'s control-character stripping and 120-byte cap (added in the prior round) had no detector: deleting the sanitisation left the full suite green, and a directory literally named `aa\nrelease_sha=<40 hex>` forged a second `release_sha` line that `skew.go`'s last-wins map parsing would have preferred over the genuine one. Two new cases prove the fix is load-bearing: an embedded-newline specimen asserting `.binary-meta` holds exactly its six declared lines and the genuine value survives, and an oversized-basename specimen asserting the recorded value is exactly 120 bytes. Noted, not landed: the structural allowlist test is still a snapshot of the *shape* the script must hold, not a guarantee against every conceivable future evasion of that shape — it is the cheapest check that catches the two concrete bypasses two independent reviewers actually constructed, not a formal proof.

decisiondcn-2608010000000009

2026-08-01 — itd-105 / spc-21, FOURTH round: two fresh independent reviews of the seam-removal fix pass above (one security, one correctness) both returned MERGE, each naming a short list of cheap items rather than a blocker — three rounds of BLOCK was not treated as licence to manufacture a fourth by inflating what these were. All were landed on this branch directly rather than deferred, since none needed a fresh review cycle to verify. (1) The structural regression test guarding the seam removal, TestBootstrapFetchOriginsAreConstants, was a DENYLIST — it scanned for ${, $ABCD, $HTTP, $CURL — so a bypass renamed to any other variable ($GH_MIRROR was the reviewer's example) would satisfy it while still redirecting a fetch; reproduced by planting exactly that shape against the committed script and watching the old test pass regardless. Replaced with an ALLOWLIST: every $NAME/${NAME} reference in the script, after subtracting names the script assigns to itself, must be CLAUDE_PLUGIN_ROOT and nothing else — verified this catches the planted $GH_MIRROR bypass and passes on the real script. (2) safe()'s tr -d range stripped ESC and other C0 controls but not CR (\015) or DEL (\177); a bare CR overprints from column zero, the exact attack class internal/termsafe's own doc comment names, and DEL is the same family. Range widened to \000-\010\013-\037\177 (keeps only tab and newline, as before); the existing control-character test now plants CR and DEL alongside ESC in the same specimen and watches both survive the pre-fix range before the widened one strips them. (3) mv -f onto an existing DIRECTORY at $binary moves the downloaded file INTO the directory rather than replacing it — reproduced: the script reported success, exited 2, wrote a truthful-looking .binary-meta, and the binary landed at $binary/abcd-<os>-<arch> while the hooks stayed broken forever, since the fast path's [ -f ] check never becomes true. A guard now refuses before any download when $binary exists and is not a regular file; the existing directory-fast-path test was tightened to assert the actual refusal (it had previously accepted a substring of the SUCCESS message as if it proved a refusal happened, which is why the bug had a green test). (4) plugin_root_basename's control-character stripping and 120-byte cap (added in the prior round) had no detector: deleting the sanitisation left the full suite green, and a directory literally named aa\nrelease_sha=<40 hex> forged a second release_sha line that skew.go's last-wins map parsing would have preferred over the genuine one. Two new cases prove the fix is load-bearing: an embedded-newline specimen asserting .binary-meta holds exactly its six declared lines and the genuine value survives, and an oversized-basename specimen asserting the recorded value is exactly 120 bytes. Noted, not landed: the structural allowlist test is still a snapshot of the shape the script must hold, not a guarantee against every conceivable future evasion of that shape — it is the cheapest check that catches the two concrete bypasses two independent reviewers actually constructed, not a formal proof.

Frontmatter

iddcn-2608010000000009
typedecision
date2026-08-01

mentions2