Summary
- An Upgrade or CONNECT request proposes a change on an HTTP/1.1 connection; it does not itself establish that the new protocol is in force.
- RFC 9931 treats early post-transition bytes as dangerous precisely because a rejected request leaves the receiver parsing HTTP/1.1, not the hoped-for protocol.
The attractive story about protocol transition is a story of momentum. A client sends an Upgrade header or CONNECT request. It has finished the HTTP message. It has a destination in mind. It may even have succeeded on a similar connection moments earlier. In a latency-sensitive design, it is tempting to treat those facts as sufficient permission to put the first bytes of the next protocol on the wire immediately. The wire is active; the intended path is obvious; why wait for one more response?
RFC 9931 identifies the missing fact. The recipient has not yet made its choice visible. HTTP/1.1 has two mechanisms by which the remainder of an existing connection can cease to be HTTP/1.1: an Upgrade accepted with 101 Switching Protocols, or a CONNECT accepted with a successful 2xx response. A completed request is necessary before a client can begin an upgraded protocol, but it is not sufficient. The server can decline the offered token, require authentication, redirect the resource, reject the destination, or apply a local policy. Until a response resolves that branch, the client knows what it proposed, not what parser the other side will use.
That distinction becomes operationally serious because a rejected request does not erase the connection. RFC 9931 explains that the server normally continues to interpret later bytes as HTTP/1.1. The same byte sequence can therefore be offered by the client as early material for a hoped-for protocol and received by the server as a further HTTP request. This is not a semantic footnote. It is a disagreement about the object on which subsequent policy, authentication and parsing rules operate.
The issue is especially sharp where a trusted client carries material supplied by an untrusted third party. A browser can carry path, header or content choices controlled by a different origin. A proxy client can forward payload chosen by a local application. If the client assumes a CONNECT tunnel has begun and forwards payload before 2xx, but the proxy rejects the CONNECT, the proxy might read that payload in the still-active HTTP/1.1 grammar. RFC 9931 describes request smuggling and parser exploitation as conditional risks of this mismatch. It does not say that every optimistic client is compromised, or that every post-transition byte becomes an attack. It tells engineers not to turn a prediction into a parser contract.
The RFC's connect-udp update makes the boundary concrete. Earlier language allowed a client to start sending HTTP Datagram UDP packets before receiving the proxying response. RFC 9931 excludes HTTP/1.x from that optimistic behaviour: a client may do it only with HTTP/2 or later, and HTTP/1.x clients MUST NOT do so because of request-smuggling risk. The rule is narrow. It does not certify an HTTP/2 proxy, a UDP destination, a delivered datagram or a permitted service. It says that a particular early-send optimisation has an unacceptable interpretation hazard in a particular protocol generation.
The corresponding CONNECT rule is deliberately legible. Proxy clients sending CONNECT on behalf of untrusted TCP clients must either wait for the successful response before forwarding TCP payload or include Connection: close. If the CONNECT is rejected, proxy servers must close the underlying connection before processing further requests. These are controls over ambiguity, not a declaration that every connection is trustworthy. They separate an untrusted payload, a proxy's transition decision, a connection-level authentication context and any downstream action rather than allowing the first to borrow the status of the second.
This is where the article's claim must remain modest. A packet capture can show bytes. A request log can show a proposal. A 101 or 2xx can show a bounded protocol acceptance. A tunnel-health record, an access-control decision and an application audit event can answer other questions. No single one supplies the rest. Heng Lu's running-code discipline strengthens rather than weakens this conclusion: running code is evidence at its own layer, but a local observation does not appoint itself to decide another party's policy or an unobserved business effect.
RFC 9931 also offers design lessons without offering a magic label. Future Upgrade tokens can forbid optimistic use, employ a preamble that terminates HTTP/1.1 processing, or apply high-entropy masking to client-to-server material. WebSocket already requires a client to wait for its opening-handshake response before sending more data. Those patterns reduce one family of ambiguity. They do not establish an implementation's current behaviour, prove that a peer accepts a connection, or prove that a protocol transition produced a valuable outcome.
The practical record should therefore preserve its verbs. Client proposed. Request completed. Server accepted or rejected. Payload was withheld, forwarded or parsed. Proxy closed or continued. A separate control decided whether the later connection could do anything consequential. The verbs cannot be collapsed merely because they appear on one TCP connection. A fast system is not one that declares the future early; it is one that knows which completed fact permits the next parser to act.
Sources
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
