RESOLUTION (2026-07-05): WON'T-FIX — a sound curl/wget extractor is structurally impossible
An 8-round dual/triple-independent adversarial investigation (Design D+) concluded that a by-construction-sound curl/wget merge-endpoint extractor is not achievable — for the same reason the denylist failed below: curl/wget's value-flag vocabulary is unbounded. The "sound argv parse" reframing (see Fix direction) does not escape the wall; it relocates it from the flag-denylist to the URL-gather, in both directions:
- Launder wall (gather): binding "the request-URL positional / the value of the URL flag" requires distinguishing a non-request URL in a flag value (
-A '<url>') from a request URL in a flag value (--url <url>). A positionals-only gather skips both (misses --url → launder); gathering flag values counts -A (→ over-block). Distinguishing them requires enumerating every value-flag's semantics = the unbounded vocabulary. Confirmed launder on curl 8.7.1: curl -X PUT .../pulls/6/merge --url .../pulls/9/merge binds PR6 while curl merges 6 AND 9 (baseline mints nothing here, so a cure would introduce this).
- Over-block wall (mirror): any read-method allow-list is incomplete —
-X HEAD / -X OPTIONS are real reads outside it, so a today-correct delete main --next -X HEAD dev compound gets DECLINED (cardinal over-block).
Both directions hit uncompletable enumerations — the structural impossibility this issue's own Fix direction tried to avoid, re-confirmed. Per the SACROSANCT rule "cure only if provably sound, else keep baseline," the gated-but-unmintable baseline is retained (safe: no launder, no over-block; curl/wget merges still route through the user's approval click — today's behavior, no regression). What did prove sound (and would seed any future attempt): target-locality, the sole-mutating-destructive-token bind, char-decode-stability + path-transform-boundedness (by-construction), and the fail-safe method axis. Full 8-round record in the comment below. #1109 (git/refs first-match launder) remains a separately-tracked pre-existing residual.
Class
Feature gap / deferred-cure. PR #1095 landed the API-based PR-merge mint (#1096) gh-api-only after review found the curl/wget endpoint extraction structurally unsound. This tracks extending the cure to curl/wget with a sound extractor. Supersedes the earlier accepted-residual (option-1) approach — that approach is abandoned; do not file it separately.
Background
The first #1096 implementation recognized gh api, curl, and wget merge spellings, extracting the endpoint PR by skipping a denylist of value-taking flags. An adversarial audit proved this denylist is structurally unsound for curl/wget: their flag vocabulary is unbounded and grows per release, so any un-enumerated value-flag can carry a decoy pull-request URL that binds the wrong PR into the approval token — a target-confusion laundering class (52+ leaking flags confirmed, including the most common). PR #1095 removed the curl/wget mint arm; curl/wget merge reverts to its pre-existing gated-but-unmintable state (still read-gated). gh-api remains covered (finite flags + first-positional-endpoint = provably sound).
Desired outcome
A faithful curl/wget API-based PR-merge command mints an approval token that authorizes only that exact merge — closing the pre-existing gated-but-unmintable over-block for those clients without reopening the target-confusion laundering surface.
Fix direction
Do not extend the value-flag denylist (it cannot be a security boundary over an unbounded flag space). Bind the endpoint from a real argv parse (the request-URL positional / the value of the URL flag), not a substring first-match. The extractor must:
- bind only the pull-request merge endpoint that is the actual request URL, never a decoy in a flag value or another leg;
- never fail-to-bind a faithful merge (that would be a cardinal-sin over-block);
- carry a bidirectional certification (no new over-block; no laundering) parametrized over a broad flag corpus, not a fixed sample.
Related
PR #1095; the gh-api-only narrowing and its adversarial audit; the shared per-leg endpoint helper (the sound gh-api reference implementation).
RESOLUTION (2026-07-05): WON'T-FIX — a sound curl/wget extractor is structurally impossible
An 8-round dual/triple-independent adversarial investigation (Design D+) concluded that a by-construction-sound curl/wget merge-endpoint extractor is not achievable — for the same reason the denylist failed below: curl/wget's value-flag vocabulary is unbounded. The "sound argv parse" reframing (see Fix direction) does not escape the wall; it relocates it from the flag-denylist to the URL-gather, in both directions:
-A '<url>') from a request URL in a flag value (--url <url>). A positionals-only gather skips both (misses--url→ launder); gathering flag values counts-A(→ over-block). Distinguishing them requires enumerating every value-flag's semantics = the unbounded vocabulary. Confirmed launder on curl 8.7.1:curl -X PUT .../pulls/6/merge --url .../pulls/9/mergebinds PR6 while curl merges 6 AND 9 (baseline mints nothing here, so a cure would introduce this).-X HEAD/-X OPTIONSare real reads outside it, so a today-correctdelete main --next -X HEAD devcompound gets DECLINED (cardinal over-block).Both directions hit uncompletable enumerations — the structural impossibility this issue's own Fix direction tried to avoid, re-confirmed. Per the SACROSANCT rule "cure only if provably sound, else keep baseline," the gated-but-unmintable baseline is retained (safe: no launder, no over-block; curl/wget merges still route through the user's approval click — today's behavior, no regression). What did prove sound (and would seed any future attempt): target-locality, the sole-mutating-destructive-token bind, char-decode-stability + path-transform-boundedness (by-construction), and the fail-safe method axis. Full 8-round record in the comment below.
#1109(git/refs first-match launder) remains a separately-tracked pre-existing residual.Class
Feature gap / deferred-cure. PR #1095 landed the API-based PR-merge mint (#1096) gh-api-only after review found the curl/wget endpoint extraction structurally unsound. This tracks extending the cure to curl/wget with a sound extractor. Supersedes the earlier accepted-residual (option-1) approach — that approach is abandoned; do not file it separately.
Background
The first #1096 implementation recognized
gh api, curl, and wget merge spellings, extracting the endpoint PR by skipping a denylist of value-taking flags. An adversarial audit proved this denylist is structurally unsound for curl/wget: their flag vocabulary is unbounded and grows per release, so any un-enumerated value-flag can carry a decoy pull-request URL that binds the wrong PR into the approval token — a target-confusion laundering class (52+ leaking flags confirmed, including the most common). PR #1095 removed the curl/wget mint arm; curl/wget merge reverts to its pre-existing gated-but-unmintable state (still read-gated). gh-api remains covered (finite flags + first-positional-endpoint = provably sound).Desired outcome
A faithful curl/wget API-based PR-merge command mints an approval token that authorizes only that exact merge — closing the pre-existing gated-but-unmintable over-block for those clients without reopening the target-confusion laundering surface.
Fix direction
Do not extend the value-flag denylist (it cannot be a security boundary over an unbounded flag space). Bind the endpoint from a real argv parse (the request-URL positional / the value of the URL flag), not a substring first-match. The extractor must:
Related
PR #1095; the gh-api-only narrowing and its adversarial audit; the shared per-leg endpoint helper (the sound gh-api reference implementation).