From 64fd5ee3e39bf47e774d5bc51f096eca7d9afb34 Mon Sep 17 00:00:00 2001 From: wshallwshall Date: Fri, 7 Aug 2026 15:16:04 -0500 Subject: [PATCH 1/2] backlog: file #1097, an interpreter flag PREFIX hides its argument from every rule Found by the adversarial verification of a candidate fix for #1086, and separated from that candidate by measuring both against the committed gate: this half is PRE-EXISTING and LIVE. worktree_gate.ps1:285 recurses into an interpreter argument for a FIXED list of spellings. PowerShell accepts any unambiguous PREFIX, so these run code and are not on the list: pwsh -NoProfile -Com "..." -> runs pwsh -NoProfile -Comm "..." -> runs pwsh -NoProfile -Cm "..." -> not recognized, so the family is bounded Their argument is therefore blanked as an ordinary quoted span and its contents are invisible to EVERY rule, not only 3c. Whatever a session may not do directly, it may do inside one of these. THE SINGLE-LINE FORM ALREADY ALLOWS TODAY. The here-string and multi-line forms still deny, but only BY ACCIDENT -- every line of a multi-line span reaches the scanner raw, so the disarm is caught as ordinary text rather than because the interpreter was recognised. That accident is load-bearing and trivially removed: the #1086 candidate blanked message bodies correctly and in doing so converted the accident into a clean fail-open across all forms. Which is why the item says the fix must be verified against the gate as it will ship, not as it is. AND THE OBVIOUS FIX IS INSUFFICIENT, MEASURED: adding the three spellings to the list closes every form on the committed gate, but on a message-blanking gate it closes only the single-line one and leaves the here-string route open behind it. The item asks for prefix recognition bounded to the shells that actually accept prefixes -- pwsh and powershell do, bash and sh do not -- and for the test to enumerate the FAMILY from -C through -Command plus a bounding negative, because a test pinning one spelling cannot see the next one. That is the same defect as the third verifier accepting the candidate: its corpus contained no such payload, so its evidence could not see the class. --- docs/BACKLOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 5fd541f1..c31de0a5 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -6298,3 +6298,31 @@ Both readings reach the same operational conclusion, which is the whole point of **Related:** #1073 (the pass), #1089โ€“#1092 (the findings that got their own numbers). **Source:** BACKLOG #1073's ASCQM 1.1 catalogue pass over all 74 live elements, with an adversarial refutation stage on every non-not-applicable verdict. + +## 1097. The interpreter recursion list is a fixed set of flag spellings, but PowerShell accepts unambiguous prefixes, so `-Com` hides its argument from every rule + +> ๐Ÿ”ข **Filed 2026-08-07 โ€” not started. โ›” LIVE ON THE INSTALLED GATE, and it is a FAIL-OPEN, not a wording defect.** Value **8/10** ยท Difficulty **2/10** ยท _do it_. `worktree_gate.ps1:285` recurses into an interpreter argument for a FIXED list of spellings -- `-c` / `-lc` / `-Command` / `/c` / `/k`. **PowerShell accepts any unambiguous PREFIX**, so `-Com` and `-Comm` run code and are not on the list. Their argument is therefore blanked as an ordinary quoted span and its contents are invisible to EVERY rule. + +**Cluster:** Session-drift controls / gate integrity. **Priority:** P1. **Verdict:** build. **Severity:** no product effect and no PHI effect. It is a live route-around of the whole gate: whatever a session may not do directly, it may do inside `pwsh -Com '...'`. + +**Measured against real PowerShell, not inferred:** + +``` +pwsh -NoProfile -Com 'Write-Output RAN_Com_OK' -> RAN_Com_OK +pwsh -NoProfile -Comm 'Write-Output RAN_Comm_OK' -> RAN_Comm_OK +pwsh -NoProfile -Cm '...' -> not recognized (ambiguous, so inert) +``` + +So `-Com` and `-Comm` are working spellings. `-Cm` is not, which bounds the family: it is every unambiguous prefix of `-Command` from `-C` upward, not any letter cluster. + +**Reachability on the committed gate.** The single-line form already ALLOWs today. A newline-spanning or here-string form currently DENIES, but only by accident: every line of a multi-line span reaches the scanner raw, so the disarm is seen as ordinary text rather than because the interpreter was recognised. **That accident is load-bearing and easy to remove** -- a change that blanks message bodies correctly deletes it, which is exactly what a candidate fix for #1086 did, converting the accident into a clean fail-open across all forms. + +**โ›” THE OBVIOUS FIX IS INSUFFICIENT AND WAS MEASURED SO.** Adding `-C|-Com|-Comm` to the list closes every spelling on the committed gate -- and on a gate that also blanks message bodies it closes only the single-line one, leaving the here-string route open behind it. So the fix must be verified against the gate as it will ship, not against the gate as it is. + +**The work.** Recognise the interpreter flag by PREFIX rather than by literal, for the shells that accept prefixes. `pwsh`/`powershell` accept any unambiguous prefix of `-Command` (and of `-EncodedCommand`, `-File`, `-NoProfile`); `bash`/`sh` do not -- their flags are single letters and clusters (`-c`, `-lc`, `-ec`), which the current list already handles. Bound it to the shells that actually behave this way rather than widening globally. + +**Test it by the PREFIX FAMILY, not by one spelling.** A test that pins `-Command` cannot see this, and a test that pins `-Com` alone cannot see `-Comm`. Enumerate `-C` through `-Command` and assert each denies, plus `-Cm` asserting the family is bounded -- that negative is what stops a fix widening into any-letters-ending-in-m, which is the shape that produced a separate fail-open in the #1086 candidate. + +**Related:** #1072 (text shapes rule 3c does not read -- this is the interpreter-recursion instance and the most severe of them), #1086 (the candidate fix that would have converted this from accidental-deny to clean fail-open), #1069, #1071, #1000 (a control green because its tests pin one spelling of a family). + +**Source:** found 2026-08-07 by the adversarial verification of a candidate fix for #1086. Two verifiers independently measured the abbreviation family; the third accepted the candidate because its corpus contained no such payload, which is itself the #1000 shape. The pre-existing half was separated from the introduced half by measuring both against the committed gate. \ No newline at end of file From 73cb8f78d1b9887b11bbf499a219ae94602ab3a0 Mon Sep 17 00:00:00 2001 From: wshallwshall Date: Fri, 7 Aug 2026 15:42:22 -0500 Subject: [PATCH 2/2] backlog: #1086 records the measured correction, so a fresh pool applies it not re-derives it A candidate was built and put through three adversarial verifiers today. NOT READY, for exactly one defect. Recording the correction in the item rather than leaving it in a workflow synthesis, because the next session should spend its budget verifying a one-line change, not rediscovering which line. WHAT WAS RIGHT, both pinned by killed mutants and not to be undone: key on the CONSUMING FLAG rather than the delimiter, and run the message-blanking AFTER the interpreter recursion. The blank-before-recursion mutant is killed by seven to nine interpreter payloads in all three mutation runs. WHAT WAS WRONG, and it is the whole rejection: the flag classifier matched an OPEN-ENDED letter cluster. PowerShell accepts unambiguous parameter PREFIXES, so -Com and -Comm are working spellings of -Command that contain no lowercase c or e and end in m. They were classified as MESSAGE and their code was blanked -- four rows went from DENY to ALLOW across rules 3, 3c and 3d. THE REPLACEMENT IS MEASURED, not proposed: a closed set of git message flags. Two verifiers independently confirmed it returns those four rows to DENY, keeps all eleven ALLOW cases and every narrowness case, and produces ZERO other verdict movement. TWO THINGS THE CANDIDATE DID NOT DISCLOSE are now in the item. A mutant relaxing the separator survives the entire suite -- found independently by two verifiers, same hash -- so that quantifier is load-bearing and no test says so. And two glued spellings of this item's OWN defect remain refused, which belongs in the disclosure list. AND THE READING RULE THE ROUND EARNED: two of three verifiers found the fail-open; the THIRD ACCEPTED, because its corpus contained no such payload. Its evidence could not see the class it was approving -- #1000's shape occurring inside the verification of a #1000 fix. Do not read "one verifier accepted" as evidence; read what its corpus covered. Also records that this item and #1097 are separable and must both be fixed: #1097 is the pre-existing interpreter-recursion gap, and this candidate would have converted #1097's accidental here-string denial into a clean fail-open. Verify either against the gate as it will SHIP, not as it is. --- docs/BACKLOG.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index c31de0a5..ed5ac684 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -5319,6 +5319,61 @@ cd ../Unrelated && git -C . config core.hooksPath /dev/null **Source:** found 2026-08-07 by being refused. The commit that filed #1085 was blocked by the very rule the item documents, which is how the intermittency was noticed โ€” several earlier commits in the same series had quoted the same class of command and passed. +--- + +### โญ A FIX WAS BUILT, VERIFIED, AND REJECTED โ€” and the correction is MEASURED. Start here, do not redesign. + +A candidate was written and put through three adversarial verifiers on 2026-08-07. **Verdict NOT READY**, +for one defect. The design is right and should be kept; only a single classifier regex is wrong. Patch +banked at `FINDINGS-1061-verifiers-2026-08-06\1086-patch-NOT-READY.diff`, synthesis beside it. Resume +with `resumeFromRunId: "wf_b4050e2f-77d"` โ€” **re-apply the banked patch first**, or the verifiers inspect +a clean tree and verify nothing. + +**WHAT WAS RIGHT** (both pinned by killed mutants, do not undo either): key on the CONSUMING FLAG, not +the delimiter; and run the message-blanking **AFTER** the interpreter recursion. The "blank before +recursion" mutant is killed by seven to nine interpreter payloads in all three mutation runs. + +**WHAT WAS WRONG โ€” the whole rejection.** The flag classifier `-(?![A-Za-z]*[ce])[A-Za-z]*m` matches an +**open-ended letter cluster**. PowerShell accepts unambiguous parameter PREFIXES, so `-Com` and `-Comm` +are working spellings of `-Command` that contain no lowercase `c` or `e` and end in `m` โ€” they were +classified as MESSAGE and their code was blanked: + +``` +pwsh -Com @'...'@ committed DENY/3c -> candidate ALLOW +pwsh -Comm @'...'@ committed DENY/3c -> candidate ALLOW +pwsh -Com @'git reset --hard'@ committed DENY/3 -> candidate ALLOW +pwsh -Com @'git worktree remove ...'@ committed DENY/3d -> candidate ALLOW +``` + +**THE MEASURED REPLACEMENT.** Replace the open-ended cluster with a CLOSED set of git message flags โ€” +`--message`, `-m`, `-am`, or a bounded class such as `-[amsSnqve]*m`. Two verifiers independently +measured that this returns those four rows to DENY, keeps all eleven #1086 ALLOW cases and every +narrowness case ALLOW, and produces **zero other verdict movement**. It also stops `-Cm`, `-Em` and +`-Program` being misclassified. + +โ›” **TWO THINGS THE CANDIDATE DID NOT DISCLOSE, both must be in the redo:** +1. **A surviving mutant.** Relaxing the separator `[ \t=]+` to `[ \t=]*` survives the entire suite โ€” + found independently by two verifiers, same mutant hash. Non-equivalence: `git commit -m"a\n\nb"` + and the `-m'...'` and `-m@'...'@` glued forms go DENY to ALLOW under it. **The `+` is load-bearing and + no test says so.** Add one. +2. **Two spellings of #1086's own defect remain refused**: `git commit -m"multi-line"` and + `-m'multi-line'` โ€” glued, no separator โ€” because of that same `[ \t=]+`. Narrow, but it is this + item's own shape and belongs in the disclosure list. + +**TEST BY THE PREFIX FAMILY, NOT ONE SPELLING** (this is #1097's requirement and it applies here too): +enumerate `-C` through `-Command` asserting each DENIES, plus `-Cm` as the bounding negative proving the +family does not widen into any-letters-ending-in-m. + +โš ๏ธ **AND THE READING RULE THIS ROUND EARNED:** two of three verifiers found the fail-open; **the third +ACCEPTED, because its corpus contained no `-Com` payload.** Its evidence could not see the class it was +approving โ€” #1000's shape occurring inside the verification of a #1000 fix. **Do not read "one verifier +accepted" as evidence; read what its corpus covered.** + +**Relationship to #1097.** They are separable and must both be fixed: #1097 is the PRE-EXISTING +interpreter-recursion gap on the committed gate; this item's candidate would have converted #1097's +accidental here-string denial into a clean fail-open. Fix #1097 first or together, and verify either +against the gate **as it will ship**, not as it is. + **Source:** identified 2026-08-05 while fixing #1032, and deliberately deferred rather than swept in, so that fix stayed scoped to one rule. Recorded here because a deferral nobody files is a deferral dropped. ## 1036. A Rule 4 deny names the first allowlisted repo's tooling regardless of which repo fired it