q-zero-rtt-replay
· RFC 8470 §5.2 · discretionary · layer quic · udp/4497 · SHOULD
Passing this means: The RFC permits either behaviour; the report says which was chosen.
Anomaly type: response_stream
How each client answered
| Client | Version | Verdict | What happened |
|---|---|---|---|
| curl | libcurl/8.23.0 ngtcp2/1.25.0 | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| quinn | noq fork (189b0ed) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| aioquic | 1.3.0 (PyPI wheel) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| chromium | build 1248 | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| quic-go | quic-go v0.61.0 (h1:9So2anK4Tp22) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| quiche | 0.30.0 (1c8e976) | Unsupported | does not deliver early data to an endpoint that negotiates versions, so it was never answered 425. It offered a GREASE QUIC version first, which this endpoint answered with Version Negotiation (RFC 8999 §6), and it did not re-offer early data on the v1 retry -- so the 0-RTT it intended never reached the wire. Both sides are conformant; the early data is lost between them. |
| neqo | 0.31.1 (cac2b74) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| picoquic | 8162550 | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| ngtcp2 | 3c23148 | Pass | Rejected it (rejected at the QUIC layer with INTERNAL_ERROR). The specification permits this but does not require it; a client that ignored it would also be conformant. |
| lsquic | 4.9.4 (2b30189) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| xquic | 2060a44 | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
| msquic | 2.7.0 (7e6525d) | Unsupported | does not resume sessions, so it was never answered 425. An earlier connection to this port in the same session completed its exchange, and with it received session tickets that permit 0-RTT; this connection, opened afterwards, ran a full handshake instead of resuming, and a client that does not resume cannot offer early data. |
| quico | 0.7.0 (npm) | Pass | Tolerated it and continued. The specification permits this but does not require it; a client that rejected it would also be conformant. |
What the clause requires
Handle being told the request arrived too early. §5.2 says a user agent "SHOULD retry automatically, but any retries MUST NOT be sent in early data" — so retrying on the 1-RTT keys and handing the 425 back to the caller are both conformant, and the report says which happened. Falling over is not one of the options. This is the only port that *accepts* early data instead of refusing it, which is what makes the 425 exchange possible at all. What it does not check is §4's rule that unsafe methods must never be sent in early data: reading the method would mean QPACK-decoding the request, which this suite deliberately never does. Reaching it needs a session ticket from an earlier connection to this same port, so a client that connects once has none.
Judged against RFC 8470.
Run this one yourself
Every test is reachable from your own client. Nothing here needs an account.
curl -s https://conformance.pqcrypta.com/catalog.json \
| jq '.tests[] | select(.id == "q-zero-rtt-replay")'