Found by cross-model review during #588 (PR #598), and measured against both origin/main and the PR head before filing — pre-existing on both, not introduced by #588.
The defect
|
verdict |
| oracle |
inert — this builds an array, it does not run anything |
origin/main |
BLOCK |
| PR #598 head |
BLOCK |
An array assignment's elements are words, not a command. git here is element zero of args, exactly as -m is element two. Nothing is invoked.
Why the gate is fooled
The detector anchors git to positions bash can begin a command, and ( is one of them — legitimately, since (cd sub; git commit) is a real subshell invocation that must stay blocked. But name=( opens an array literal, not a subshell, and the text layer does not distinguish them.
Direction and cost
False POSITIVE. It fails closed: the cost is a rephrase, never an unreviewed commit. That is why it is filed rather than folded into #598, which is seven review rounds deep.
The constraint any fix inherits
Distinguishing args=( from a bare ( is narrow enough to look trivial, but it must not weaken the ( anchor itself — (cd sub; git commit -m x) and ( git commit -m x ) are pinned oracle rows in tests/test-codex-gate-command-position.sh and both must stay BLOCKED. The obvious shape of a fix is to require that ( not be preceded by an assignment-name-and-equals, using the existing GATE_ASSIGN name grammar rather than a new one.
Worth checking as part of the same fix: args+=(git commit) and declare -a args=(git commit) are the same class.
Acceptance criterion
args=(git commit -m x) is allowed; (cd sub; git commit -m x) and ( git commit -m x ) stay refused; every existing row in tests/test-codex-gate-command-position.sh still passes. Want values generated by that suite's bash oracle — a fake git on PATH that logs when an argument is exactly commit — rather than hand-asserted.
Superseded in scope by #603
#603 is the general form of this: the punctuation anchors ( ) { } ! all fire on prose because #588's "the anchor must itself be at a boundary" fix was applied to the keyword anchors and never to the punctuation ones. This issue is the specific ( case where the preceding text is an assignment name. A fix for #603 should subsume this one; close this as part of that work rather than fixing it separately.
Related
Same family as #600 (relocation flag matched in prose) and #601 (heredoc bodies): a guard that matches text without a notion of what the shell will actually execute. #533's ruling against positive command parsing bounds all three.
Found by cross-model review during #588 (PR #598), and measured against both
origin/mainand the PR head before filing — pre-existing on both, not introduced by #588.The defect
origin/mainAn array assignment's elements are words, not a command.
githere is element zero ofargs, exactly as-mis element two. Nothing is invoked.Why the gate is fooled
The detector anchors
gitto positions bash can begin a command, and(is one of them — legitimately, since(cd sub; git commit)is a real subshell invocation that must stay blocked. Butname=(opens an array literal, not a subshell, and the text layer does not distinguish them.Direction and cost
False POSITIVE. It fails closed: the cost is a rephrase, never an unreviewed commit. That is why it is filed rather than folded into #598, which is seven review rounds deep.
The constraint any fix inherits
Distinguishing
args=(from a bare(is narrow enough to look trivial, but it must not weaken the(anchor itself —(cd sub; git commit -m x)and( git commit -m x )are pinned oracle rows intests/test-codex-gate-command-position.shand both must stay BLOCKED. The obvious shape of a fix is to require that(not be preceded by an assignment-name-and-equals, using the existingGATE_ASSIGNname grammar rather than a new one.Worth checking as part of the same fix:
args+=(git commit)anddeclare -a args=(git commit)are the same class.Acceptance criterion
args=(git commit -m x)is allowed;(cd sub; git commit -m x)and( git commit -m x )stay refused; every existing row intests/test-codex-gate-command-position.shstill passes. Want values generated by that suite's bash oracle — a fakegiton PATH that logs when an argument is exactlycommit— rather than hand-asserted.Superseded in scope by #603
#603 is the general form of this: the punctuation anchors
( ) { } !all fire on prose because #588's "the anchor must itself be at a boundary" fix was applied to the keyword anchors and never to the punctuation ones. This issue is the specific(case where the preceding text is an assignment name. A fix for #603 should subsume this one; close this as part of that work rather than fixing it separately.Related
Same family as #600 (relocation flag matched in prose) and #601 (heredoc bodies): a guard that matches text without a notion of what the shell will actually execute. #533's ruling against positive command parsing bounds all three.