HTTP/1.1 Response Desynchronization via conflicting CL/TE headers in Proxy CONNECT

Disclosed: 2026-03-25 13:37:02 By 3lcarry To curl
Low
Vulnerability Details
## Summary: curl fails to prioritize the `Transfer-Encoding: chunked` header over `Content-Length` in HTTP/1.1 proxy responses (specifically 407/401 auth challenges), violating RFC 9112 Section 6.1. I have identified the root cause in `cf-h1-proxy.c`. In the response-handling loop (around line 466), the code checks for a `Content-Length` based body (`if(ts->cl)`) before checking for `chunked_encoding`. Because it finds a `CL` value, it decrements the counter and sets the state to `KEEPON_DONE` once the short `CL` is reached, skipping the chunked-encoding parser entirely. This leaves the remainder of the chunked message in the socket buffer. On the subsequent `CONNECT` retry (e.g., after providing Digest credentials), curl reads the leftover smuggled data as the start of the new response, leading to a protocol desynchronization and a connection failure. ## Affected version I use a local build from the commit `80b6cd92af1891d9645923db3bbd453c99e99d45` ``` ./build/src/curl -V curl 8.19.1-DEV (Darwin) libcurl/8.19.1-DEV OpenSSL/3.6.1 zlib/1.2.12 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 libpsl/0.21.5 nghttp2/1.68.0 OpenLDAP/2.4.28/Apple Release-Date: [unreleased] Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt mqtts pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile libz NTLM PSL SSL threadsafe TLS-SRP UnixSockets zstd ``` ## Steps To Reproduce: 1. I've include a POC proxy Python script, `proxy_cl_te_desync.py`. 2. Run the proxy `python3 proxy_cl_te_desync.py` 3. Execute curl using the proxy `curl -v -x http://127.0.0.1:9999 --proxy-user user:pass --proxy-digest https://example.com` 4. Observe that curl reads only the bytes specified by CL, leaving the chunked data to "poison" the next read, resulting in Invalid response header ``` ./build/src/curl -v -x http://127.0.0.1:9999 --proxy-user user:pass --proxy-digest https://example.com * Trying 127.0.0.1:9999... * CONNECT: no ALPN negotiated * allocate connect buffer * Proxy auth using Digest with user 'user' * Establish HTTP proxy tunnel to example.com:443 > CONNECT example.com:443 HTTP/1.1 > Host: example.com:443 > User-Agent: curl/8.19.1-DEV > Proxy-Connection: Keep-Alive > < HTTP/1.1 407 Proxy Authentication Required < Proxy-Authenticate: Digest realm="test", nonce="abc123", qop="auth" < Content-Length: 5 < Transfer-Encoding: chunked * CONNECT responded chunked < * Ignore 5 bytes of response-body * Proxy auth using Digest with user 'user' * Establish HTTP proxy tunnel to example.com:443 > CONNECT example.com:443 HTTP/1.1 > Host: example.com:443 > Proxy-Authorization: Digest username="user", realm="test", nonce="abc123", uri="example.com:443", cnonce="Q9bDz1eQ+MAmeNi2", nc=00000001, qop=auth, response="df6fbefe412a23d6edddc1f42109537f" > User-Agent: curl/8.19.1-DEV > Proxy-Connection: Keep-Alive > < THIS-SHOULD-BE-IGNORED < 0 * Invalid response header * closing connection #0 curl: (43) Invalid response header ``` ### Additional Notes (Disclosure): I have used an AI assistant strictly to help format this report and ensure grammatical clarity. All technical research, including the identification of the specific flaw in cf-h1-proxy.c, the log analysis, and the creation of the functional Python PoC, were performed and verified manually by me. ## Impact ## Summary: An attacker can smuggle a custom message into the connection buffer, although this is unlikely to be a primary attack vector since a malicious proxy already possesses the privileges required to modify or drop traffic. The real significance of this finding is **RFC 9112 correctness** and the integrity of curl’s internal state machine. By prioritizing Content-Length over Transfer-Encoding, curl creates a protocol desynchronization where the client and proxy lose track of the byte stream. This breaks the expected isolation between separate HTTP transactions on the same connection, potentially allowing injected data to be processed as the response to a subsequent, sensitive request (like a credentialed retry).
Actions
View on HackerOne
Report Stats
  • Report ID: 3623064
  • State: Closed
  • Substate: informative
  • Upvotes: 3
Share this report