ci/woodpecker/pr/ci Pipeline was canceled
Round-five remediation of both blockers gate-ultron-01 raised ondf83a9ee. Measured against that head first; all eight returned rc=0 and each executes the program the check exists to recognize: cu"rl" --config /tmp/w.cfg -> allowed cu'rl' --config /tmp/w.cfg -> allowed /usr/bin/cu\rl --config /tmp/w.cfg -> allowed g"h" api -X POST repos/a/b/issues … -> allowed /usr/bin/g\h api -X POST repos/a/b/… … -> allowed curl --con"fig" /tmp/w.cfg -> allowed /usr/bin/gh api -X POST repos/a/b/$EP … -> allowed g"h" api -X POST repos/a/b/$EP … -> allowed BLOCKER 1. The previous commit said names are recognized "after quote removal" and did not do that. It replaced quote characters with whitespace, which is token SEPARATION: a shell removes a quote WITHOUT splitting the word around it, so `cu"rl"` is one word naming curl, while whitespace made it two words naming neither. `"/usr/bin/curl"` blocked under that version only because the inserted space happened to land after a slash — a passing case that established nothing about quote removal, and I read it as confirmation. The characters are now DELETED, which is what quote removal is. Backslashes go with them, because escaping is ordinary word formation too. Deletion still handles substitution: `$(which curl)` becomes `which curl`, where the name is a word on its own. The flag is read from the same normalized copy for the same reason — `--con"fig"` is one word spelling --config. No review raised that; the name was simply the easier half to reach, and reading both halves the same way is the entire point of having one normalization. BLOCKER 2. A THIRD name consumer never went through the shared site: the unreadable-endpoint arm kept a private bare-name copy of the scope gate's regex against raw $CMD. A caller could be admitted by the repaired gate and then go unrecognized by the fail-closed refinement — a gate and its own refinement disagreeing about who the caller is, which is the defect one layer downstream. Fixing that surfaced the same mistake a third time inside this very edit: my first version left the NAME in the refinement's tail regex, so the name gate recognized `g"h" api` while the tail still demanded the undressed spelling, and the two halves disagreed exactly as before. Caught by the fixture, not by reading. Each half now asks one question: the name gate asks WHO, from the normalized copy; the tail asks whether the ENDPOINT is readable, from the raw text — deliberately raw, because the expansion markers that make an endpoint unreadable are the characters the normalized copy removes, and reading the tail from it would erase the evidence. Controls: the 8 positive fixtures FAIL atdf83a9eeand pass here; the negatives — mycurl, curl-wrapper, mygh, mygh with an assembled endpoint, an absolute-path read, and -K on a non-curl — pass at BOTH heads. Suite 166/166. Unchanged and still stated in the comment rather than this message: a name ABSENT from the text, assembled from variables or reached through a wrapper script that execs the program, is invisible to any of this.