Ember's HTTP/1.1 header parser matches the Transfer-Encoding header value
with a case-sensitive substring test (hValue.contains("chunked")). RFC
9112 §7 requires transfer-coding names to be compared case-insensitively. A
request carrying Transfer-Encoding: Chunked (capital C) is therefore not
recognised as chunked, and Ember falls back to framing by Content-Length
(or zero if absent) while a compliant intermediary frames the same bytes by
chunked encoding. The two parsers then disagree on where the request body
ends, enabling HTTP request smuggling (TE.CL / TE.0).
The same line of code admits two further variants:
Transfer-Encoding: notchunked (an inverse
desync — Ember treats it as chunked while a compliant intermediary
rejects the unknown coding).E2 84 AA decode to U+212A KELVIN SIGN, which
String.equalsIgnoreCase Unicode-case-folds to k, so
Transfer-Encoding: chun<U+212A>ed matches chunked once the comparison
is made case-insensitive without also pinning the decode to ISO-8859-1.Request smuggling when ember-server is an origin behind an intermediary that
honours Transfer-Encoding case-insensitively per RFC, forwards the header
value verbatim, and reuses keep-alive connections to the backend:
Cookie,
Authorization) to the attacker.ember-client shares the same HeaderP.parse on the response path, enabling
response smuggling when http4s is used as a gateway. This is less severe: it
requires a malicious or compromised upstream rather than an anonymous remote
client.
Transfer-Encoding case-insensitively (per RFC) and
forwards the header value without lowercasing itproxy_request_buffering on)Transfer-Encoding value (lowercases the
token) before forwarding{
"cwe_ids": [
"CWE-444"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-15T19:54:25Z",
"nvd_published_at": null,
"severity": "HIGH"
}