HTTP request smuggling is an attack where a front-end proxy (load balancer, CDN, reverse proxy) and a back-end server disagree about where one HTTP request ends and the next begins. That disagreement — a "desync" — lets an attacker craft a single request that the front end reads as one request but the back end reads as two, smuggling a hidden second request into another user's connection. The result: cache poisoning, session hijacking, credential capture, and silent bypass of front-end access controls. This guide covers the CL.TE, TE.CL, and TE.TE desync mechanics, how to discover them safely, real-world impact, and the defences that actually close the gap.
Why This Attack Still Works in 2026
Most Indian web stacks are not a single server — they're a chain: CDN, WAF, load balancer, application server, sometimes an internal proxy in front of a microservice. Each hop in that chain runs its own HTTP parser, often from a different vendor, often a different version. HTTP/1.1 was never designed with a single unambiguous way to signal request length, and that ambiguity is exactly what request smuggling exploits.
The Root Cause: Two Ways to Say "This Is How Long I Am"
HTTP/1.1 gives a request two independent headers to declare its body length:
Content-Length— an exact byte count for the body.Transfer-Encoding: chunked— the body is sent in chunks, each prefixed with its own length, terminated by a zero-length chunk.
Transfer-Encoding header value that's subtly malformed (extra whitespace, unusual casing, a duplicate header). When both are present, RFC 7230 says Transfer-Encoding takes priority and Content-Length should be ignored — but not every parser implements that rule, and that's the seam attackers exploit.
The Three Desync Variants
CL.TE — the front end uses Content-Length to frame the request, the back end uses Transfer-Encoding. The front end forwards what it thinks is a complete request, but the back end, reading chunked encoding, treats the leftover bytes after the terminating chunk as the start of the next request on that connection — a request the attacker fully controls.
TE.CL — the reverse: the front end honours Transfer-Encoding, the back end honours Content-Length. The front end forwards the full chunked body, but the back end stops reading at the declared Content-Length and treats the remaining chunked data as a smuggled prefix to the next request.
TE.TE — both servers nominally support Transfer-Encoding, but one of them can be tricked into ignoring it via header obfuscation (a stray space, a non-standard character, or a duplicated Transfer-Encoding header). Whichever server disregards it falls back to Content-Length, recreating a CL.TE or TE.CL condition through obfuscation rather than absence.
Know your vulnerabilities before attackers do
Run a free VAPT scan — takes 5 minutes, no signup required.
Book Your Free ScanDiscovery Methodology: Finding Desyncs Without Breaking Production
Discovery has to be careful — a badly timed smuggling probe on a shared connection pool can corrupt a real user's session in production. The standard methodology, popularised by PortSwigger's research on HTTP desync attacks, uses timing-based detection before any exploitation attempt:
- Send a CL.TE probe. Craft a request with both headers where the
Content-Lengthis short and theTransfer-Encodingbody is left unterminated. If the back end is TE-based, it waits for more chunked data that never arrives — a measurable response delay confirms the desync without corrupting another user's traffic. - Send a TE.CL probe. Invert the test — a short chunked body followed by data the back end (if CL-based) will treat as part of the next request, causing a timeout on that connection specifically.
- Confirm with a differential response, not a live victim. Once timing suggests a desync, confirm by smuggling a request against your own second connection (a self-targeted probe) rather than an unpredictable live user, and observe the response prefix left behind.
- Fuzz header obfuscation for TE.TE. Test variants:
Transfer-Encoding: chunked,Transfer-Encoding : chunked(trailing space before colon), duplicateTransfer-Encodingheaders, and non-standard casing, to find which one a given server in the chain silently ignores. - Test HTTP/2 downgrade paths separately. Many front ends terminate HTTP/2 from the browser and re-issue HTTP/1.1 to the back end. The downgrade step itself can introduce a request-smuggling surface even if no client ever speaks HTTP/1.1 directly — this is now one of the most common real-world smuggling vectors in CDN-fronted architectures.
Impact: What a Successful Desync Actually Buys an Attacker
Request smuggling is rarely the end goal — it's a primitive that enables several higher-impact attacks:
- Cache poisoning. If the front end is a caching proxy or CDN, a smuggled request can trick it into caching a malicious response against a legitimate URL, serving that poisoned response to every subsequent visitor until the cache expires.
- Session hijacking and credential capture. A smuggled request prefix gets prepended to the next unrelated user's request on the shared back-end connection. If that next request is theirs, the attacker's smuggled prefix can capture their session cookie, auth header, or form submission in the response that comes back.
- Bypassing front-end access controls. WAFs, rate limiters, and auth checks that live only on the front end never see the smuggled portion of the request — it arrives at the back end as if it came from inside the trusted perimeter, bypassing rules the front end was supposed to enforce.
- Request queue poisoning. On connection-reuse architectures, a single successful smuggle can corrupt the request queue for every subsequent request on that TCP connection until it's torn down, affecting multiple unrelated users in sequence.
The DPDP Act 2023 sets a substantial penalty ceiling for failure to safeguard personal data, and a smuggled request that exposes session cookies or user data can trigger exactly that liability — see MeitY for the full penalty schedule.
CL.TE vs TE.CL: A Quick Comparison
| Aspect | CL.TE | TE.CL | TE.TE |
|---|---|---|---|
| Front end trusts | Content-Length | Transfer-Encoding | Either, depending on obfuscation |
| Back end trusts | Transfer-Encoding | Content-Length | Falls back to CL or TE if TE header is malformed |
| Detection signal | Back end hangs waiting for chunk data | Front-end connection times out | Depends on which obfuscation variant succeeds |
| Common in | Older reverse proxies paired with modern app servers | CDNs that prioritise chunked streaming | Chains with mismatched HTTP libraries |
| Fix | Normalise or reject dual-header requests | Normalise or reject dual-header requests | Strict RFC 7230 header parsing on all hops |
Defence: Closing the Desync Gap
The permanent fix is architectural, not a single patch:
- Use HTTP/2 end-to-end wherever possible. HTTP/2 frames requests with explicit length-prefixed binary framing — there is no
Content-LengthvsTransfer-Encodingambiguity to exploit. The risk reappears only at HTTP/2-to-HTTP/1.1 downgrade points, so keeping the entire chain on HTTP/2 (or gRPC where applicable) removes the root cause rather than mitigating it. - Normalise ambiguous requests at the front end. Configure the front-end proxy to reject, not silently reformat, any request carrying both
Content-LengthandTransfer-Encoding, or a malformed/duplicatedTransfer-Encodingheader. Most modern reverse proxies (recent NGINX, HAProxy, Envoy releases) support this as a strict-parsing mode — enable it explicitly, don't assume it's default. - Reject conflicting headers outright rather than guessing. Per RFC 7230, a request with both headers should be treated as malformed and rejected with a 400, not "resolved" by picking one. Guessing is what creates the disagreement between hops.
- Disable connection reuse to untrusted or legacy back ends where consistent header handling can't be guaranteed, so a smuggled prefix can't bleed into another user's request even if a desync condition exists.
- Keep every hop's HTTP parser current. Desync bugs are frequently patched at the library level (web servers, proxy software, load balancer firmware) — a proxy chain running mismatched, outdated parser versions is the most common real-world root cause.
Where Bachao.AI Fits
Automated VAPT platforms like Bachao.AI, from Dhisattva AI Pvt Ltd, include desync and request-smuggling checks as part of proxy-chain testing for Indian SMB web applications, flagging CL.TE/TE.CL inconsistencies across CDN, WAF, and application-server hops. Deeper manual exploitation and chain-specific validation is typically delivered with a CERT-In empanelled partner as part of a full penetration test. You can start with a free VAPT scan to get a baseline read on your proxy chain, and browse the Bachao.AI blog for related web application security methodology. Organisations handling personal data through these stacks should also review their DPDP compliance posture, since a smuggled request that exposes session or personal data carries breach-notification obligations under the Act.
Further Reading
- PortSwigger — HTTP Request Smuggling — the primary methodology reference for CL.TE, TE.CL, and TE.TE discovery.
- CERT-In — advisories on web application and infrastructure vulnerabilities relevant to Indian organisations.
- NIST — Guide to General Server Security (SP 800-123) — baseline hardening guidance applicable to proxy and application server chains.
Frequently Asked Questions
What is HTTP request smuggling in simple terms?
What's the difference between CL.TE and TE.CL smuggling?
Content-Length to frame the request while the back end uses Transfer-Encoding, causing leftover bytes to be read as a new request by the back end. TE.CL is the reverse: the front end trusts Transfer-Encoding, the back end trusts Content-Length, and the mismatch happens at the back end's stopping point instead.