Cross-backend credential-header robustness probe — the auth sibling of
body_size_smuggling.ts.
The auth middleware reads a single credential per header (Authorization,
X-Daemon-Token). What a *duplicated*, *oversized*, or *control-char-injected*
credential header does is framework-territory — Hono reads its headers via the
Web Headers API, axum via http::HeaderMap — and the two could resolve a
duplicate differently (first-vs-last), cap header size differently, or parse a
malformed value differently. None of that is exercised over fetch (the
FetchTransport can't emit a duplicate or malformed header), so it had no
cross-impl pin. This raw-socket suite sends hand-framed requests and asserts
the security invariants that must hold regardless of how each framework
resolves the ambiguity — so it pins a real property without blessing one
resolution over the other:
- a duplicated credential header never escalates — a request carrying a
valid keeper
X-Daemon-Token *and* a second, conflicting one must not
perform a keeper operation. The target omits confirm, so the documented
confirm guard (purge_not_confirmed) makes the honored-token branch a
guaranteed non-2xx with zero side effect, and the discarded-token
branch is a non-2xx auth/credential refusal — so whichever copy the
framework picks, the outcome is non-2xx. The same shape with two garbage
Authorization headers pins the bearer path can't be escalated either. - a control-char-injected credential header can't smuggle or authenticate
— embedded
CRLF / bare CR in the value never frames a second request
(no smuggle) and never authenticates (the truncated / rejected value is no
token). - no response desync — each crafted request yields exactly one HTTP
response (a duplicate header that reframed the request would surface as a
second status line, like the body-size smuggling probe).
- an oversized credential header can't wedge the server — after a request
with a 64 KiB
X-Daemon-Token (well past both frameworks' header caps), a
subsequent normal request on a fresh connection still gets a response. The
oversized request's own outcome (4xx / 431 / connection close) is
don't-care; surviving it is the property.
Raw-socket by necessity (fetch can't emit duplicate or malformed headers),
so — like body_size_smuggling.ts — this is cross-process only and
fixture-free: it needs only the base URL, the RPC path, and a valid daemon
token (handle.daemon_token, kept current for the run by the same rotation
the _testing_reset channel relies on). Cited property: docs/security.md
§"Credential Type Hierarchy" (a leaked / conflicting credential header can't
escalate the credential ceiling) + §"API Token Security" (bearer handling).
$lib-free by contract (relative + node: specifiers only).