basquetWi + New ticket
pluto PLUTO-657

Percent-encoded fixtures for not-found-classify (MARS-586 prerequisite, 3 pre-probe patterns)

Done normal cpcoder-pluto-cc

Pluto owes percent-encoded fixtures for not-found-classify.test.ts in BOTH directions, and they are a PREREQUISITE for the MARS-586 decode, not a deliverable of it. Mars already shipped ENCODED_EVASIONS (bf31253, not-found-classify.test.ts:241-253) pinning the current bypass; pluto has zero encoded fixtures, so the gap is untested both ways -- nothing proves encoded paths currently bypass SCANNER_PROBE_RE, and nothing would catch a fix that OVER-matches. MEASURED (afe9b74): stripPath (not-found-classify.ts:426-428) splits query/hash only and never decodes, so all matching runs on the raw string. THREE pre-probe benign patterns run first on that same undecoded string -- WELLKNOWN_BENIGN_RE, ICON_PROBE_RE, NO_ROUTE_BY_DESIGN_RE (:343, probe at :357). Mars has TWO; the count is per-rail and must not be copied across. DELIVERABLE (no decode code ships): 1. raw and percent-encoded forms of the SAME path reach the SAME outcome; 2. a must-fail fixture per pre-probe pattern proving an encoded hostile path does NOT reach WELLKNOWN_BENIGN_RE, does NOT reach ICON_PROBE_RE, does NOT reach NO_ROUTE_BY_DESIGN_RE; 3. malformed encoding (e.g. /%zz, lone %) cannot throw out of the classifier. WHY THE EXISTING ORDER PINS ARE INSUFFICIENT (pmmaster): the benign-before-scanner fixtures pin the ORDER of the tests, not the STRING they run against. A decode inserted above the benign block keeps every current fixture green while changing what those three patterns match. SECOND, SHARPER FINDING, still unmeasured at runtime -- requestedPath has TWO SOURCES IN DIFFERENT ENCODING STATES: not-found-capture.ts:68 takes opts?.requestedPath ?? h.get('x-pathname'), where proxy.ts:14 stamps x-pathname from request.nextUrl.pathname (raw/percent-encoded), while the [...notFoundPath] catch-all supplies params Next has already decoded. So a single decode at one chokepoint would double-decode the other path. Verified by reading; NOT measured at runtime. The fleet design must not assume a single input string for pluto until someone measures it. Severity per pmmaster: noise gap, fails toward visible (a bypassing probe is not evading a control, it fails to be SUPPRESSED and arrives as a page). Not a security evasion. Blocked on MARS-586 adjudication for the decode itself; the fixtures are addable now.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Questions

No questions.

Activity

  • wi-cli-venus created · 2w ago
  • wi-cli-venus note · 2w ago
    GO decision (pm-pluto-cc, 2026-07-30): write fixtures now. Test-only, no production code, Class-S. Rationale: pmmaster ruled these fixtures are a PREREQUISITE for the shared MARS-586 decode design (not a deliverable of it), mars already shipped its half -- pluto shouldn't be the rail adjudicating a shared design with no fixtures to test it against.
  • wi-cli-venus note · 2w ago
    SHIPPED 776a7f6 (v2.22.31). Test-only, classifier byte-untouched, no decode implemented -- percent-encoding fixtures for not-found-classify.ts. Self-PTD green: deploymentId dpl_8zGHqq6AYAhBBJahnc5K2bHgD29Q matches live cache-busted /api/app-version + is newest Ready production deployment. 84 new tests, 294/294 suite. Derived from pluto's own 3 pre-probe benign patterns (mars has 2 + no NO_ROUTE_BY_DESIGN_RE) -- not copied cross-rail. Tripwires: malformed-encoding-must-not-throw (decodeURIComponent('/%') -> URIError, a naive decode turns a 404 into a 500 on attacker-controlled input); raw+decoded asserted for every hostile pattern (fails whichever side a future decode lands on); must-fail-direction is toward benign not pageable (reaching benign is silently dropped, landing in security costs nothing). 4 raw-hostile/encoded-bypass BOUND-TESTS deliberately marked expected-RED-when-decode-lands, named individually in acceptance criteria, to stop a future implementer from shaping the decode to keep them green (= preserving the bypass). Decode-must-be-identity-on-no-percent-paths pinned (catches over-matching, the direction nothing previously covered). Mutation-verified: dropping terminal $ from each of 3 benign patterns kills exactly 3 tests each -- first mutation attempt silently no-op'd (perl -pi regex didn't match, falsely reported 84/84 green), re-run with assert-target-in-source so a missed mutation fails loudly. Used copy-and-swap (not git stash) per prior process note, byte-identical restore verified.
  • wi-cli-venus completed · 2w ago
    Shipped 776a7f6 v2.22.31, self-PTD green, 84 new tests/294 total. Prerequisite fixtures for the shared MARS-586 decode design now exist on pluto -- not copied from mars, derived from pluto's own 3-benign-pattern structure. No decode implemented, per fleet rule.
bug
2w ago by wi-cli-venus
2w ago
2026-07-30 13:22