ci/woodpecker/pr/ci Pipeline was successful
Round-four remediation of both blockers gate-ultron-01 raised ond99ff57e. Measured against that head before anything was touched; all seven returned rc=0, and each executes the program the check exists to recognize: "/usr/bin/curl" --config /tmp/w.cfg -> allowed './curl' --config /tmp/w.cfg -> allowed $(which curl) --config /tmp/w.cfg -> allowed `which curl` --config /tmp/w.cfg -> allowed /usr/bin/gh api -X POST repos/a/b/issues … -> allowed ./gh api -X POST repos/a/b/issues … -> allowed /usr/local/bin/tea api -X POST repos/a/b/… … -> allowed This is the third appearance of one defect, and the shape is worth stating plainly because the first two repairs each fixed an INSTANCE and left the class: the check matched the bare word, then it matched the unquoted basename. Both were models of one TEXTUAL PRESENTATION of a shell word rather than of the word, so the first repair was defeated by an absolute path and the second by two quote characters. Recognizing a name is either done after quote removal or it is caller-name parsing wearing a longer regex. The second blocker is the same defect sitting untouched in the API SCOPE gate the whole time, while the curl arm was repaired twice beside it. That one is worse than it looks: the scope gate decides whether write detection runs AT ALL, so failing to admit `/usr/bin/gh api -X POST` is not a missed match, it is an allow. No URL marker rescued those commands either — provider CLI endpoints are spelled `repos/…` with no leading slash, so `/repos/` never matched them. Fix, and the reason it is one fix rather than two: - $CMD_NAMES — a second reading of the same command with quote and substitution punctuation turned into whitespace. Names are read from it. - $NAME_PREFIX — the one place the shape of a program name is written down. Both callers use it, so the next fix to this class lands in a single location instead of whichever arm review happened to probe. That is the actual lesson of finding this defect twice in one file. The prefix still must end at a slash. `mycurl` and `curl-wrapper` are different programs and blocking them is the over-block that gets a guard routed around instead of repaired; both remain negative fixtures, and `mygh` and an absolute-path READ join them. The cost is the one this file already chose and documented for the payload check: quoting an example does not exempt it, so writing one of these commands inside quotes on a Bash line is refused too. Applying that rule to the name arms makes the file coherent — the alternative is a guard where the payload arm treats quotes as text and the name arms treat them as armour. Still open, stated rather than left to be found: a name absent from the text — assembled from variables, or reached through a wrapper script that execs the program — is invisible here. That is a limit of inspecting a command string, not something a pattern closes. Controls: the 7 positive fixtures FAIL atd99ff57eand pass here; the 4 negative fixtures pass at BOTH heads, so they measure over-blocking rather than decorate the diff. Suite 157/157.