Files
amethyst/quic/plans
Claude a80f4ea19d fix(quic): RFC 9000 §17.2/§17.3 fixed-bit + §10.1 idle-timeout enforcement
The two High-severity gaps from the 2026-05-09 four-RFC compliance audit.

Fixed-bit (RFC 9000 §17.2 long-header, §17.3 short-header): the spec
says fixed-bit (0x40) MUST be 1 in every v1 packet; receivers MUST
discard packets where it's 0. Pre-fix the parsers checked only the
form-bit (0x80) and accepted any fixed-bit value — a peer or off-path
attacker could route packets through AEAD that aren't valid v1 packets.
Both `parseAndDecrypt` paths and the `peekKeyPhase` shortcut now
silently drop fixed-bit=0. The bit isn't header-protected (HP only
XORs the low 5 bits), so the check runs on the raw wire byte before
HP unmask + AEAD. Test: `FixedBitValidationTest` (3 cases).

Idle timeout (RFC 9000 §10.1): `max_idle_timeout` was decoded into
config and advertised via the ClientHello transport-params extension,
but never enforced — a black-holed connection lived indefinitely.
This commit:

  * adds `QuicConnection.lastActivityMs`, bumped on (a) successful
    inbound packet decrypt and (b) outbound ack-eliciting send per
    §10.1.1
  * adds `effectiveIdleTimeoutMs()` returning the min of local and
    peer advertisements (skipping any side that advertised 0), with
    the §10.1 `3 * PTO` floor applied
  * folds the idle deadline into the driver's send-loop
    `withTimeoutOrNull` so an idle connection wakes exactly at expiry
  * silently transitions to CLOSED via `markClosedExternally` per
    §10.2.1 ("the connection enters the closing state silently —
    discarding the connection state without sending a CONNECTION_CLOSE")

Test: `IdleTimeoutTest` (8 cases) covers the min-of-two computation,
0-means-disabled handling, the 3*PTO floor, deadline math, and
postpone-on-activity. Plan updated to mark both items resolved.

https://claude.ai/code/session_01XGmmaVuy2wsSZQx2AqN2ik
2026-05-09 04:29:32 +00:00
..