{"id":"CVE-2026-69205","aliases":[],"url":"https://o3.security/vulnerability/CVE-2026-69205","summary":"Http4s Ember Transfer-Encoding value parsing (TE.CL / TE.0 request smuggling)","details":"## Summary\n\nEmber's HTTP/1.1 header parser matches the `Transfer-Encoding` header value\nwith a case-sensitive substring test (`hValue.contains(\"chunked\")`). RFC\n9112 §7 requires transfer-coding names to be compared case-insensitively. A\nrequest carrying `Transfer-Encoding: Chunked` (capital C) is therefore not\nrecognised as chunked, and Ember falls back to framing by `Content-Length`\n(or zero if absent) while a compliant intermediary frames the same bytes by\nchunked encoding. The two parsers then disagree on where the request body\nends, enabling HTTP request smuggling (TE.CL / TE.0).\n\nThe same line of code admits two further variants:\n\n- The substring test misfires on `Transfer-Encoding: notchunked` (an inverse\n  desync — Ember treats it as chunked while a compliant intermediary\n  rejects the unknown coding).\n- Header field bytes are decoded with the platform-default charset. Under\n  UTF-8 the wire bytes `E2 84 AA` decode to U+212A KELVIN SIGN, which\n  `String.equalsIgnoreCase` Unicode-case-folds to `k`, so\n  `Transfer-Encoding: chun<U+212A>ed` matches `chunked` once the comparison\n  is made case-insensitive without also pinning the decode to ISO-8859-1.\n\n## Impact\n\n### Server\n\nRequest smuggling when ember-server is an origin behind an intermediary that\nhonours `Transfer-Encoding` case-insensitively per RFC, forwards the header\nvalue verbatim, and reuses keep-alive connections to the backend:\n\n- Front-end security bypass: the smuggled request reaches paths the\n  intermediary's ACL/auth layer would have blocked, with attacker-chosen\n  method and headers.\n- Cross-user request hijack: a partial smuggled prefix left in Ember's\n  connection buffer is concatenated with the next victim's request on the\n  same pooled backend connection, exposing its headers (e.g. `Cookie`,\n  `Authorization`) to the attacker.\n- Cache poisoning: the smuggled response is associated with the next request\n  key in a caching proxy.\n\n### Client\n\nember-client shares the same `HeaderP.parse` on the response path, enabling\nresponse smuggling when http4s is used as a gateway. This is less severe: it\nrequires a malicious or compromised upstream rather than an anonymous remote\nclient.\n\n## Preconditions\n\n- Unauthenticated remote attacker (server)\n- ember-server as origin behind a keep-alive intermediary\n- Intermediary treats `Transfer-Encoding` case-insensitively (per RFC) and\n  forwards the header value without lowercasing it\n- Malicious or compromised upstream (client)\n\n## Workarounds\n\n- Intermediary fully buffers and re-encodes request bodies (e.g. nginx with\n  default `proxy_request_buffering on`)\n- Intermediary normalises the `Transfer-Encoding` value (lowercases the\n  token) before forwarding\n- Disable backend keep-alive between the intermediary and Ember","published":"2026-09-15T19:54:25Z","modified":"2026-09-15T20:00:40.521015729Z","cvss":{"score":8.7,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"Maven","name":"org.http4s:http4s-ember-core_3","fixedVersion":"0.23.35"},{"ecosystem":"Maven","name":"org.http4s:http4s-ember-core_2.13","fixedVersion":"0.23.35"},{"ecosystem":"Maven","name":"org.http4s:http4s-ember-core_2.12","fixedVersion":"0.23.35"},{"ecosystem":"Maven","name":"org.http4s:http4s-ember-core_2.13","fixedVersion":"1.0.0-M47"},{"ecosystem":"Maven","name":"org.http4s:http4s-ember-core_3","fixedVersion":"1.0.0-M47"}],"fix":{"url":"https://github.com/http4s/http4s/commit/5e88b2e7b4e6ea2f0c61040a4bc9de0d73e51217","label":"http4s/http4s@5e88b2e"},"references":[{"type":"WEB","url":"https://github.com/http4s/http4s/security/advisories/GHSA-9998-894r-fwvr"},{"type":"WEB","url":"https://github.com/http4s/http4s/commit/5e88b2e7b4e6ea2f0c61040a4bc9de0d73e51217"},{"type":"PACKAGE","url":"https://github.com/http4s/http4s"},{"type":"WEB","url":"https://github.com/http4s/http4s/releases/tag/v0.23.35"},{"type":"WEB","url":"https://github.com/http4s/http4s/releases/tag/v1.0.0-M47"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-09-15T20:00:40.521015729Z"}}