Prompt and scope
Your proxy wants to send post-upgrade data before an HTTP/1.1 protocol switch is confirmed to reduce latency. Explain the risks, safe boundaries, and changes required in the client and proxy.
What the interviewer evaluates
- Knowing that an HTTP/1.1 upgrade can still be rejected before confirmation, so past success is not a guarantee.
- Explaining how attacker-controlled bytes can be reinterpreted as HTTP requests on the rejection path.
- Distinguishing Upgrade, CONNECT, WebSocket, and HTTP/2/3 constraints.
- Providing engineering controls such as waiting for 2xx, closing connections, disabling optimistic sends, and observable fallback.
Clarifying questions
- Is the mechanism Upgrade or CONNECT, and what target protocol and HTTP version are involved?
- Can an untrusted application, user, or third-party origin control the subsequent bytes?
- Does the connection carry client certificates, proxy authentication, or other connection-level trust?
- Is the goal handshake latency, or must HTTP/1.1 compatibility and connection reuse remain?
30-second answer framework
I would default to forbidding untrusted post-upgrade data on HTTP/1.1 before confirmation. The client waits for the upgrade response; a CONNECT proxy waits for 2xx or sends Connection: close and closes after failure. A rejected connection containing unknown-protocol bytes is not reused. Validate HTTP/2/3 separately for their multiplexed stream semantics, record upgrade and fallback reasons, and test request smuggling and parser disagreement in a controlled proxy.
Step-by-step deep dive
1. Identify the optimistic-send assumption
HTTP/1.1 can switch protocols with Upgrade or CONNECT, but the server may reject the request. If the client sends new-protocol bytes before seeing the status, two parsers are possible: the new protocol if accepted, HTTP/1.1 if rejected. A previous successful upgrade does not prove the next one will be accepted.
2. Explain the request-smuggling path
When subsequent data is controlled by an untrusted source, the rejection path can interpret those bytes as an additional HTTP request. If connection-level authentication already succeeded, a proxy may treat an attacker-crafted request as authenticated client traffic. Disagreement between proxy and client parsing boundaries can also expose parser vulnerabilities.
3. Choose a safe implementation
The safest approach is to wait for confirmation before sending subsequent data. RFC 9931 requires an HTTP/1.1 CONNECT proxy client to wait for 2xx or send Connection: close; a proxy should close the underlying connection when rejecting an unsafe CONNECT. If latency matters, prefer HTTP/2 or later with explicit stream semantics and validate the target protocol's own handshake rules.
4. Build fallback, monitoring, and tests
On upgrade failure, mark the connection non-reusable and create a fresh HTTP/1.1 request; never treat already-sent unknown bytes as retryable request data. Measure acceptance, rejection reasons, closes, and retries without logging credentials or bodies. Test untrusted payloads, authenticated proxies, 401/407, redirects, timeouts, parser disagreement, and HTTP/2/3 fallback.
High-quality sample answer
I would not treat optimistic sending as a general optimization. HTTP/1.1 Upgrade or CONNECT can be rejected before confirmation; attacker-controlled subsequent bytes can then be parsed as extra requests, creating request smuggling, and connection-level authentication increases the impact. I would wait for confirmation by default. A CONNECT proxy waits for 2xx or uses Connection: close and closes after rejection; an Upgrade failure is not reused. For lower latency, evaluate HTTP/2/3 stream semantics. Validate with untrusted payloads, authenticated proxies, error statuses, redirects, and retries; monitor acceptance and close reasons; ensure fallback never leaks requests or credentials.
Common mistakes
- Sending arbitrary subsequent bytes because a recent upgrade succeeded.
- Validating only the server and ignoring client, proxy, and third-party parsing boundaries.
- Reusing a rejected CONNECT connection or forwarding buffered payload data.
- Applying WebSocket handshake rules to every Upgrade token.
- Benchmarking only HTTP/1.1 without distinguishing HTTP/2/3 stream semantics.
- Retrying with a connection containing unknown bytes or writing bodies to diagnostic logs.
Follow-up questions and answers
Why does Connection: close reduce the risk?
It closes the connection after handling the request, so a rejected upgrade does not continue parsing possibly mixed subsequent bytes on that connection. It sacrifices reuse and should be weighed against waiting for 2xx.
Can WebSocket send optimistically?
WebSocket's handshake requires the client to wait for the server response before sending subsequent data. Rules for one protocol must not be generalized to every Upgrade token.
How do you balance latency and safety?
Measure the real cost of waiting, then prefer HTTP/2 or HTTP/3. If HTTP/1.1 is required, wait for confirmation and close on fallback. No optimization may let untrusted data cross an unconfirmed parsing boundary.