All checks were successful
check / check (push) Successful in 2m45s
The access log wrote one INFO line per request carrying the full attacker-controlled URL, on the unauthenticated public receiver, so a client inventing paths wrote unbounded arbitrary text into the operator's logs. Rejected requests now log the chi route pattern instead of the concrete URL — extended to 3xx as well as 4xx, because RequireAuth answers 303 and so /user/<anything> was an unauthenticated path-varying vector. The query is redacted on the branches that keep a concrete path, and every client-supplied field is capped: url, useragent and referer at 512 bytes, request_id at 128, method at 32. The caps are spent in ENCODED bytes, so escaping cannot multiply them. One INFO line per request, at most 2,560 bytes — a figure derived arithmetically rather than observed, with the fixed portion measured at 336 (JSON) and 286 (text). Independently reviewed four times, and broken three of those times on the same class of defect: a stated bound the code did not have. Round 1 left the 2xx query and the headers unbounded; round 2 counted raw bytes against an encoded ceiling and broke at 2,611; round 3 charged 6 bytes for every non-printable when strconv.Quote spells astral ones as \UXXXXXXXX, and broke at 2,676. Two independent exhaustive audits over all 1,112,064 code points, built by different methods, now both report zero undercharged runes on either handler. Measured worst case over a real TCP socket is 1,972 bytes, 77% of the ceiling. Follow-up filed to assert that charge against every code point in the suite, so the ceiling defends itself rather than resting on one hand-picked rune.
18 KiB
18 KiB