HTTP request smuggling is a protocol-level attack that exploits disagreements between a front-end proxy and a back-end server over where one HTTP request ends and the next begins. When a load balancer, CDN, or reverse proxy forwards traffic to an origin server, both sides must agree on request boundaries using the Content-Length and Transfer-Encoding headers. If they parse those headers differently, an attacker can craft a single TCP connection that the front end sees as one request but the back end sees as two — smuggling a hidden, attacker-controlled request into another user's traffic stream. First formalized by researcher James Kettle in 2019, the technique has since been used to hijack sessions, bypass authentication, and poison caches at scale. It remains dangerous today because so much modern infrastructure — API gateways, service meshes, WAFs — chains multiple HTTP parsers together.
How does HTTP request smuggling actually work?
It works by abusing ambiguity in how two servers determine a request's length when both Content-Length (CL) and Transfer-Encoding: chunked (TE) headers are present or malformed. The HTTP/1.1 specification (RFC 9112) says that when both headers appear, Transfer-Encoding should take precedence and Content-Length should be ignored — but not every server implementation follows this consistently, and some tolerate malformed variants like Transfer-Encoding: chunked (trailing space) or Transfer-Encoding: xchunked. When a front-end proxy and a back-end server pick different interpretations of the same request, the byte stream gets split in two different places on each server. The attacker plants a second, hidden request inside the body of the first one; the back end processes it as a standalone request prepended to whatever the next legitimate user sends over that reused connection.
What is the difference between CL.TE, TE.CL, and TE.TE desync attacks?
The difference is which header each server trusts: CL.TE means the front end uses Content-Length while the back end uses Transfer-Encoding, TE.CL is the reverse, and TE.TE means both use Transfer-Encoding but can be tricked into ignoring it via header obfuscation. In a CL.TE attack, the front end forwards a fixed-length body based on Content-Length, but the back end reads that body as chunked, stops at the terminating 0\r\n\r\n, and treats the remaining bytes as the start of a new request. TE.CL inverts this: the front end streams chunks while the back end expects a fixed length, causing it to read past the chunk boundary. TE.TE attacks target servers in a chain that both claim to support chunked encoding, using a malformed second Transfer-Encoding header (e.g., Transfer-Encoding: chunked, identity) so one server ignores it while the other honors it. All three produce the same outcome: a desynchronized connection an attacker can use to inject requests other users' traffic gets appended to.
Which real CVEs show request smuggling in production software?
Several CVEs in widely deployed servers confirm this isn't a theoretical issue. CVE-2019-16869, disclosed in Netty in September 2019, allowed a malformed Content-Length header combined with Transfer-Encoding to smuggle requests past Netty-based proxies; it was patched in Netty 4.1.44. CVE-2021-33037 in Apache Tomcat, fixed in versions 10.0.7, 9.0.46, and 8.5.66, stemmed from Tomcat's improper handling of malformed trailer headers in chunked requests, enabling smuggling behind certain reverse-proxy configurations. CVE-2023-25725 in HAProxy, patched in version 2.7.3 (released February 2023), involved an empty Transfer-Encoding header value that HAProxy accepted while downstream servers rejected it, creating an exploitable desync. CVE-2022-31813 in Apache HTTP Server's mod_proxy module, fixed in Apache httpd 2.4.54, went a step further: it let an attacker suppress the X-Forwarded-For and related headers that back-end applications relied on for IP-based access control, effectively smuggling a request that appeared to originate from inside the trusted network. Each case followed the same pattern: two HTTP implementations in the same request path, each lenient in a slightly different way, and each individually "compliant enough" to ship.
What can an attacker actually do with a smuggled request?
An attacker can hijack other users' sessions, bypass front-end access controls, and poison shared caches by injecting a request that gets processed as if it came from the victim. In his 2019 Black Hat USA talk "HTTP Desync Attacks," James Kettle demonstrated smuggling attacks against PayPal, Netflix, and several other high-traffic sites, capturing live victim requests — including session cookies and authorization headers — and collecting more than $70,000 in bug bounty payouts within months of publishing the research. Because many architectures reuse back-end TCP connections across multiple front-end clients, a single smuggled request can land in front of the next unrelated visitor, turning a parsing bug into a mass credential-theft or cache-poisoning primitive rather than a one-off exploit against a single account.
Request smuggling is also a reliable vector for web cache poisoning: if the smuggled portion of the request targets a cacheable URL and the front-end CDN stores the resulting response, every subsequent visitor to that URL receives the attacker's payload — a stored cross-site scripting hit or a malicious redirect — until the cache entry expires or is purged. Kettle's research showed this could turn a single desynchronized request into a persistent, self-propagating attack against a cached endpoint rather than a one-time hit against a single connection. Front-end access control bypass follows the same logic: many gateways enforce authentication or IP allow-listing before forwarding to the origin, but a smuggled request that the gateway never inspects as a "new" request skips that check entirely, landing directly on internal endpoints the gateway was supposed to protect.
How can security teams detect and prevent HTTP request smuggling vulnerabilities?
Teams prevent it by eliminating ambiguity between HTTP parsers in the request path — the safest fix is terminating HTTP/1.1 at the edge and speaking HTTP/2 or HTTP/3 exclusively between the front end and back end, since those protocols use a binary framing layer that removes the CL/TE ambiguity entirely. Where HTTP/1.1 must stay in the chain, configure both front-end and back-end servers to reject requests with duplicate Content-Length headers, malformed Transfer-Encoding values, or both headers present at once, rather than silently normalizing them. Disabling back-end connection reuse per client, or at minimum closing the connection after any request with ambiguous framing, limits blast radius even if a parser disagreement slips through. For detection, tools like PortSwigger's Burp Suite HTTP Request Smuggler extension and differential testing against staging front-end/back-end pairs surface CL.TE and TE.CL mismatches before attackers do, and this class of finding should be part of any pre-release check on gateway, load balancer, or proxy configuration changes. Version pinning matters too: because CVE-2019-16869, CVE-2021-33037, and CVE-2023-25725 were each fixed in specific point releases, an inventory that tracks exact proxy and application-server versions — not just "Netty" or "HAProxy" as a product name — is what turns a published advisory into an actionable patch list.
How Safeguard Helps
Safeguard's reachability analysis flags which HTTP-parsing libraries and proxy components in your stack are actually exercised by production traffic paths, so a CVE like CVE-2023-25725 or CVE-2021-33037 gets triaged by real exploitability rather than by version number alone. Griffin AI correlates the specific proxy-to-origin topology in your SBOM against known desync patterns and prioritizes the pairs most likely to disagree on request framing. Continuous SBOM generation and ingest keep an accurate inventory of every HTTP server and proxy version across gateways, sidecars, and origin services, closing the visibility gap that lets mismatched parsers persist unnoticed. When a smuggling-relevant CVE lands, Safeguard's auto-fix PRs push the patched version directly into the affected service's manifest, cutting the time between disclosure and remediation.