Grouped by test, not by client, because that is what makes the interesting case visible: a clause several independent implementations get wrong the same way is not several bugs. Four teams reading one sentence and arriving at one wrong answer is evidence about the sentence.
Every entry below is a MUST or a SHOULD the client did not meet, with the clause it was judged against. Discretionary tests cannot appear here: where the RFC permits either behaviour, the report says which was chosen and grades nothing. Nor can inconclusive runs — a test the client was never actually put through is not a failure of the client.
These are specification violations, not vulnerabilities. Some have security relevance and most are simply behaviour a document prohibits; calling every one a vulnerability is how a conformance suite loses the right to be believed about the ones that are.
PUSH_PROMISE for a push the client never allowed
h-push-promise-unsolicited
· RFC 9114 §7.2.5, §4.6 · correctness · MUST · 5 of 7 implementations
5 independent implementations fail this one. Worth reading as a question about the clause before reading it as a question about the clients.
Close the connection with H3_ID_ERROR. §7.2.7 leaves the maximum push ID unset until the client sends MAX_PUSH_ID, so a server "cannot push until it receives a MAX_PUSH_ID frame" and every push ID is larger than the client has advertised. §7.2.5 is explicit about the answer: a client "MUST treat receipt of a PUSH_PROMISE frame that contains a larger push ID than the client has advertised as a connection error of H3_ID_ERROR".
| Implementation | Version | What it did |
|---|---|---|
| quinn | noq fork | Fail Rejected, but with error 0x105 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| aioquic | 1.3.0 | Fail Rejected, but with error 0x105 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| chromium | build 1223 | Fail Rejected, but with error 0x106 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| quiche | 0.30.0 | Fail Rejected, but with error 0x105 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| neqo | unknown | Fail Rejected, but with error 0x105 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
Transport parameter carrying a value the specification forbids
q-invalid-transport-param
· RFC 9000 §7.4, §18.2 · correctness · MUST · 3 of 7 implementations
3 independent implementations fail this one. Worth reading as a question about the clause before reading it as a question about the clients.
Close the connection with TRANSPORT_PARAMETER_ERROR. §18.2 makes an ack_delay_exponent above 20 invalid, and §7.4 is a MUST: "An endpoint MUST treat receipt of a transport parameter with an invalid value as a connection error of type TRANSPORT_PARAMETER_ERROR." Distinct from a *duplicate* parameter, which the same clause makes only a SHOULD — this port sends one parameter, once, with a value outside its permitted range. The parameter travels in the handshake, so every client that connects here reads it. Only a client that answers with a CONNECTION_CLOSE this endpoint can read is scored: one that simply abandons the handshake is recorded as inconclusive, because a close that was sent and lost looks exactly like one that was never sent.
| Implementation | Version | What it did |
|---|---|---|
| chromium | build 1223 | Fail rejected the out-of-range parameter with PROTOCOL_VIOLATION, where RFC 9000 §7.4 requires TRANSPORT_PARAMETER_ERROR. The violation was detected; the code reported is wrong. |
| quic-go | quic-go v0.61.0 | Fail rejected the out-of-range parameter with INTERNAL_ERROR, where RFC 9000 §7.4 requires TRANSPORT_PARAMETER_ERROR. The violation was detected; the code reported is wrong. |
| neqo | unknown | Fail rejected the out-of-range parameter with Code::crypto(2f), where RFC 9000 §7.4 requires TRANSPORT_PARAMETER_ERROR. The violation was detected; the code reported is wrong. |
103 Early Hints before the final response
h-early-hints
· RFC 9110 §15.2, RFC 8297 · resilience · MUST · 2 of 7 implementations
2 independent implementations fail this one. Worth reading as a question about the clause before reading it as a question about the clients.
Treat 103 as informational and keep reading for the final response. RFC 9110 §15.2 makes this a MUST: a client "MUST be able to parse one or more 1xx responses received prior to a final response, even if the client does not expect one". Ignoring the hints is fine — a user agent MAY do that — but closing the connection is not.
CANCEL_PUSH for a push ID that was never promised
h-cancel-push-unsolicited
· RFC 9114 §7.2.3 · correctness · MUST · 2 of 7 implementations
2 independent implementations fail this one. Worth reading as a question about the clause before reading it as a question about the clients.
Close the connection with H3_ID_ERROR. No MAX_PUSH_ID was granted, so every push ID is greater than currently allowed, and §7.2.3 requires a CANCEL_PUSH referencing one to be treated as a connection error of that type.
| Implementation | Version | What it did |
|---|---|---|
| quinn | noq fork | Fail Rejected, but with error 0x105 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| chromium | build 1223 | Fail Rejected, but with error 0x106 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
Push stream opened for a push nobody allowed
h-push-stream-unpromised
· RFC 9114 §6.2.2 · correctness · MUST · 2 of 7 implementations
2 independent implementations fail this one. Worth reading as a question about the clause before reading it as a question about the clients.
Close the connection with H3_ID_ERROR. §6.2.2 does not require the push to have been promised first — the stream alone is enough: a client "MUST treat receipt of a push stream as a connection error of type H3_ID_ERROR when no MAX_PUSH_ID frame has been sent", and no client under test sends one. Distinct from the PUSH_PROMISE test, which puts the same violation in a frame on the control stream. This one opens the push stream itself, which a client has to recognise by its stream type before any frame inside it is read.
| Implementation | Version | What it did |
|---|---|---|
| chromium | build 1223 | Fail Rejected, but with error 0x101 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
| quiche | 0.30.0 | Fail Rejected, but with error 0x103 where the specification requires 0x108. The violation was detected; the code reported is wrong. |
Unknown frame type in a 1-RTT packet
q-reserved-frame
· RFC 9000 §12.4 · correctness · MUST · 1 of 7 implementations
Close the connection with FRAME_ENCODING_ERROR. Unlike HTTP/3, QUIC reserves no ignorable frame types — §12.4 makes an unknown frame a connection error, so ignoring it is the failure here.
Stateless reset
q-stateless-reset
· RFC 9000 §10.3 · correctness · MUST · 1 of 7 implementations
Recognise the token in the last 16 bytes of the datagram, enter the draining period, and send no further packets on the connection. The packet cannot be authenticated, so there is nothing to reply with and nothing to report to the peer — continuing to send is the failure §10.3.1 names.
| Implementation | Version | What it did |
|---|---|---|
| aioquic | 1.3.0 | Fail kept sending after the Stateless Reset: 76 more datagram(s) arrived in the following 3 seconds. RFC 9000 §10.3.1 requires a client that recognises the token to enter the draining period and send nothing further, so this connection is wedged against an endpoint that has forgotten it. |
GOAWAY sent mid-connection
h-goaway
· RFC 9114 §5.2 · resilience · SHOULD · 1 of 7 implementations
Stop opening requests, finish those in flight, and retry idempotent ones elsewhere.
DATA frame before any HEADERS on the response stream
h-data-before-headers
· RFC 9114 §4.1 · correctness · MUST · 1 of 7 implementations
Close the connection with H3_FRAME_UNEXPECTED. A response begins with a field section, and §4.1 makes "receipt of an invalid sequence of frames" a connection error of that type — a body arriving before the headers that describe it is exactly that.
SETTINGS_H3_DATAGRAM with a value that is neither 0 nor 1
h-datagram-setting-invalid
· RFC 9297 §2.1.1 · correctness · MUST · 1 of 7 implementations
Close the connection with H3_SETTINGS_ERROR. Unusually for a setting, RFC 9297 pins down the invalid-value case rather than leaving it open: the value "MUST be either 0 or 1", and if one "is received with a value that is neither 0 nor 1, the receiver MUST terminate the connection with error H3_SETTINGS_ERROR". This is the setting that gates HTTP Datagrams and so WebTransport, which means a client that implements either has real parsing behind it rather than an ignored identifier.
A second GOAWAY naming a larger identifier than the first
h-goaway-increasing
· RFC 9114 §5.2 · correctness · MUST · 1 of 7 implementations
Close the connection with H3_ID_ERROR. §5.2 permits multiple GOAWAY frames but requires the identifier in each to be no greater than any previously sent, because the identifier is a promise about what will still be processed and raising it takes that promise back. "Receiving a GOAWAY containing a larger identifier than previously received MUST be treated as a connection error of type H3_ID_ERROR."
What this suite is · The full grid · All clients · All tests · Findings