When a request passes through a front end and then a back end, both servers read the same bytes and both decide where the body ends. transfer encoding obfuscation is the family of tricks that makes them decide differently by mangling the Transfer-Encoding header so one server honors it and the other throws it away. It is the mechanism behind the TE.TE flavor of http request smuggling, and it turns a header both servers claim to support into a boundary they no longer agree on.
Why one mangled header splits the chain
Chunked encoding tells a server to read the body as a series of sized chunks ending in a zero length chunk, rather than counting a fixed Content-Length. When a request carries both headers, the standard says Transfer-Encoding wins and Content-Length is ignored. So if an attacker can make just one server in the chain stop seeing the Transfer-Encoding header, that server falls back to Content-Length while its neighbor still reads chunks. The two now slice the stream at different bytes, and the leftover becomes a smuggled prefix waiting for the next user.
The attacker never has to defeat chunked parsing itself. They only have to write the header so that one parser reads it as Transfer-Encoding: chunked and the other does not. Every technique below is a different way to hide that header in plain sight.
The techniques of transfer encoding obfuscation
Whitespace and tabs before the colon
A header name is supposed to be followed immediately by a colon. Some parsers are strict about that; others tolerate a space or a tab wedged between the name and the colon. An attacker sends this:
Transfer-Encoding : chunked
A lenient parser reads it as a normal Transfer-Encoding header and switches to chunked. A strict parser sees a name it does not recognize and refuses to treat it as Transfer-Encoding at all, so it reads the Content-Length instead. One request, two readings.
A leading space in the value
The same idea moves to the value side. A keyword padded with extra space can slip past one parser and trip another, so one server matches the chunked token and the other decides the value is malformed and ignores the header.
Bogus values and misspellings
A value the back end does not recognize can still change what the front end does. Writing Transfer-Encoding: xchunked gives one server a token it treats as unknown, so it ignores the header and falls back to length, while the other server matches on the chunked substring and reads chunks. A value list such as Transfer-Encoding: chunked, identity does the same by handing each parser a different thing to anchor on.
Line folding
Obsolete line folding let a header value continue on the next line when that line began with a space or tab. It was removed from the standard, but old parsers still honor it. Fold the header and one server joins the lines while the other does not:
Transfer-Encoding: chunked
A server that supports folding joins the two lines into Transfer-Encoding: chunked. A server that does not treats the first line as an empty value and the indented line as junk, then reads length instead. This is the same obsolete folding that has turned up in real edge platform advisories.
Duplicated headers
Nothing stops a request from carrying the header twice:
Transfer-Encoding: chunked Transfer-Encoding: identity
One server may act on the first occurrence, another on the last. If the front end honors identity and reads Content-Length while the back end honors chunked, the chain desyncs. A duplicate header is a boundary question dressed up as a formatting detail.
Every one of these tricks is valid enough to forward and broken enough to be read two ways. That gap between forwarded and understood is the whole attack.
From obfuscation to a desync
Put the pieces together against an invented app, Acme Notes. The attacker sends a request whose Transfer-Encoding header carries a tab before the colon, and also a Content-Length that covers only the first few bytes of the body. The front end has the strict parser. It rejects the odd header name, trusts Content-Length, reads a short body, and forwards the whole request on the shared connection believing it sent one ordinary POST.
The back end has the lenient parser. It accepts the tabbed header as Transfer-Encoding: chunked, ignores the length, and reads the body as chunks. It stops at the zero chunk early, and the bytes the attacker placed after it stay in the buffer as the start of a new request. When the next real user arrives, the back end glues the smuggled prefix onto that victim request. The attacker wrote a request that runs under someone else’s session, and the front end never saw it as a request because it was hiding in a body the front end approved.
This is exactly the desync described in our note on TE.TE request smuggling, and it sits in the same family of boundary bugs we group under injection and input. The header obfuscation is only the key; the lock is two parsers that disagree.
What actually stops it
There is no bad string to block here. Each mangled header is legal enough that a signature would either miss it or flag ordinary traffic. The fix is to make the front end own the framing: parse every header strictly, reject requests whose Transfer-Encoding is malformed or duplicated instead of guessing, and rewrite each request into one unambiguous form before forwarding. If the front end will not honor a header the way the back end does, it should strip the header, not pass it along for the back end to read differently. A request that carries both length headers should be refused and its connection closed, so no leftover prefix has anywhere to wait.
The reason these tricks keep working is that a filter sees a header string, not whether that string reaches a second parser that reads it a different way. UnboundCompute reasons about that reachability rather than matching header patterns, asking whether a mangled header actually crosses a parser boundary and desyncs the chain before it calls anything a finding. You can read more about that approach on our about page. The header is just bytes. The bug is two readers who will never agree on them.
Frequently asked questions
What is transfer encoding obfuscation?
It is the set of tricks that mangle the Transfer-Encoding header so one server in a chain honors it and another ignores it. The attacker does not break chunked parsing; they write the header so that one parser reads it as Transfer-Encoding: chunked and the other treats it as unrecognized and falls back to Content-Length. That disagreement is what lets a request smuggle work.
Which header tricks actually cause the disagreement?
The common ones are a space or tab wedged before the colon, a leading space in the value, a bogus or misspelled value such as xchunked, a value list like chunked, identity, obsolete line folding that continues the value on an indented next line, and the header sent twice so one server reads the first copy and another reads the last. Each one is valid enough to forward and broken enough to be read two ways.
How does this relate to TE.TE smuggling?
TE.TE is the smuggling variant where both the front end and the back end support chunked encoding, so in theory they agree. Transfer encoding obfuscation is the mechanism that breaks that agreement. By mangling the header so one server stops honoring it, the attacker turns a TE.TE pair back into a plain length disagreement, which is exactly the desync described in our note on TE.TE request smuggling.
How do you defend against it?
There is no bad string to block, because each mangled header is legal enough to miss or to flag ordinary traffic. The fix is to make the front end parse headers strictly, reject requests whose Transfer-Encoding is malformed or duplicated, strip any encoding it will not honor the same way the back end does, and rewrite each request into one unambiguous form before forwarding so the back end never has to choose.
Put an autonomous researcher on your own systems
UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.
