| Package | Affected versions | Patched versions |
|---|---|---|
| org.http4s:http4s-ember-core_2.12 | < 0.23.35 | 0.23.35 |
| org.http4s:http4s-ember-core_2.13 | ≥ 1.0.0-M1, < 1.0.0-M47< 0.23.35 | 1.0.0-M470.23.35 |
| org.http4s:http4s-ember-core_3 | ≥ 1.0.0-M1, < 1.0.0-M47< 0.23.35 | 1.0.0-M470.23.35 |
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 itRunning one of these products? Scan your site to see whether it exposes a vulnerable version.
Scan my site freeproxy_request_buffering on)Transfer-Encoding value (lowercases the
token) before forwarding