{"id":"CVE-2026-84380","aliases":["DEBIAN-CVE-2026-84380","EUVD-2026-70248","GHSA-pf96-p4fj-6566","PYSEC-2026-3849","UBUNTU-CVE-2026-84380"],"status":"published","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","severity":{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00275,"percentile":0.2008,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":true,"fix_available":true},"cwes":["CWE-444"],"published":"2026-09-02T17:58:55Z","modified":"2026-10-28T02:30:42Z","exploits":[{"source":"pocgithub","id":"federiconbaez/cortex9-httpx2-cl-te-framing-conflict-model","title":"federiconbaez/cortex9-httpx2-cl-te-framing-conflict-model","date":"2026-11-09","url":"https://github.com/federiconbaez/cortex9-httpx2-cl-te-framing-conflict-model"}],"fixes":[{"ecosystem":"PyPI","package":"httpx2","fixed_in":["2.11.0"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"python-httpx2","fixed_in":["2.12.0-1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"httpx2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.11.0"}]}]},{"source":"osv","ecosystem":"Debian:14","package":"python-httpx2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.12.0-1"}]}],"versions":["2.4.0-1","2.5.0-1"]},{"source":"osv","ecosystem":"PyPI","package":"httpx2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.11.0"}]}],"versions":["0.0.0","2.0.0","2.0.0b1","2.1.0","2.10.0","2.2.0","2.3.0","2.4.0","2.5.0","2.6.0","2.7.0","2.8.0","2.9.0","2.9.1"]},{"source":"osv","ecosystem":"PyPI","package":"httpx2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.11.0"}]}],"versions":["0.0.0","2.0.0","2.0.0b1","2.1.0","2.10.0","2.2.0","2.3.0","2.4.0","2.5.0","2.6.0","2.7.0","2.8.0","2.9.0","2.9.1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"python-httpx2","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.5.0-1"]}],"products":[{"vendor":"pydantic","product":"httpx2"}],"references":[{"url":"https://github.com/pydantic/httpx2/security/advisories/GHSA-pf96-p4fj-6566","tags":["x_refsource_CONFIRM","advisory","web","report"]},{"url":"https://github.com/pydantic/httpx2/pull/1137","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/pydantic/httpx2/commit/829b93a2393212996f613e635261f777d9ec6eab","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/pydantic/httpx2/releases/tag/v2.11.0","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-84380","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pf96-p4fj-6566","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/84xxx/CVE-2026-84380.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-84380","tags":["advisory"]},{"url":"https://github.com/pydantic/httpx2","tags":["package"]},{"url":"https://pypi.org/project/httpx2","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-84380","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-84380","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-84380","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T17:58:55.52Z","modified":"2026-09-02T18:07:36.98Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-444"],"updated_at":"2026-11-02T14:20:08.391556Z"}],"euvd":[{"id":"EUVD-2026-70248","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T17:58:55Z","modified":"2026-09-02T18:07:36Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T18:01:14.689075Z"}],"ghsa":[{"id":"GHSA-pf96-p4fj-6566","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"### Summary\n\nHTTPX2 can automatically add a `Content-Length` header to a request that already contains a caller-supplied `Transfer-Encoding` header. The resulting HTTP/1.1 request contains both framing headers, which can create an ambiguous message boundary and enable request smuggling or connection desynchronization when processed by intermediaries that disagree about which header takes precedence.\n\n### Details\n\nWhen a request body has a known size, HTTPX2's content encoder returns a default `Content-Length`. `Request._prepare()` applies each default header with `setdefault()`, which only checks whether that same header is already present. It does not check whether the mutually exclusive `Transfer-Encoding` header is present.\n\nFor example:\n\n```python\nimport httpx2\n\nrequest = httpx2.Request(\n    \"POST\",\n    \"http://example.com/\",\n    headers={\"Transfer-Encoding\": \"chunked\"},\n    content=b\"test 123\",\n)\n\nprint(request.headers)\n```\n\nThe request contains both:\n\n```text\nTransfer-Encoding: chunked\nContent-Length: 8\n```\n\nOn an HTTP/1.1 connection, the body is serialized using chunked transfer coding while both headers are sent on the wire. This violates HTTP message-framing requirements. Fixed-size byte, JSON, form, and known-length multipart bodies can reach the affected path.\n\nStreaming bodies with an explicit `Content-Length` are not affected in current HTTPX2 releases because the automatically generated `Transfer-Encoding` is already suppressed in that direction.\n\n### Impact\n\nAn attacker may be able to use the conflicting framing headers as a request-smuggling or desynchronization primitive. Exploitation requires an application to pass attacker-controlled request framing headers and associated body data to HTTPX2, use HTTP/1.1, and communicate through a proxy or origin that accepts conflicting headers and interprets them differently from another hop.\n\nDepending on the downstream infrastructure, successful exploitation could interfere with requests sharing a persistent connection, bypass front-end routing or authorization decisions, or poison responses or caches. Applications that do not forward attacker-controlled `Transfer-Encoding` headers are not directly exposed.\n\n### Mitigation\n\nUpgrade to HTTPX2 `2.11.0` or later. Patched versions treat `Content-Length` and `Transfer-Encoding` as mutually exclusive when applying automatically generated request headers.\n\nIf upgrading is not immediately possible, remove `Transfer-Encoding` and other hop-by-hop framing headers from untrusted input before constructing outbound requests. Applications acting as proxies should derive outbound framing from the body rather than forwarding inbound `Content-Length` or `Transfer-Encoding` headers.","status":"published","published":"2026-09-08T20:46:28Z","modified":"2026-09-08T20:46:28Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-444"],"updated_at":"2026-11-02T14:41:14.764963Z"}],"nvd":[{"id":"CVE-2026-84380","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T18:21:29.513Z","modified":"2026-09-09T21:05:23.237Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-444"],"updated_at":"2026-11-02T14:12:43.399612Z"}],"osv":[{"id":"CVE-2026-84380","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T17:58:55.52Z","modified":"2026-10-28T02:30:42.456507325Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-444"],"updated_at":"2026-11-02T15:45:18.482949Z"},{"id":"DEBIAN-CVE-2026-84380","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T18:21:29.513Z","modified":"2026-10-01T03:03:37.331768298Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T15:46:04.577397Z"},{"id":"GHSA-pf96-p4fj-6566","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"### Summary\n\nHTTPX2 can automatically add a `Content-Length` header to a request that already contains a caller-supplied `Transfer-Encoding` header. The resulting HTTP/1.1 request contains both framing headers, which can create an ambiguous message boundary and enable request smuggling or connection desynchronization when processed by intermediaries that disagree about which header takes precedence.\n\n### Details\n\nWhen a request body has a known size, HTTPX2's content encoder returns a default `Content-Length`. `Request._prepare()` applies each default header with `setdefault()`, which only checks whether that same header is already present. It does not check whether the mutually exclusive `Transfer-Encoding` header is present.\n\nFor example:\n\n```python\nimport httpx2\n\nrequest = httpx2.Request(\n    \"POST\",\n    \"http://example.com/\",\n    headers={\"Transfer-Encoding\": \"chunked\"},\n    content=b\"test 123\",\n)\n\nprint(request.headers)\n```\n\nThe request contains both:\n\n```text\nTransfer-Encoding: chunked\nContent-Length: 8\n```\n\nOn an HTTP/1.1 connection, the body is serialized using chunked transfer coding while both headers are sent on the wire. This violates HTTP message-framing requirements. Fixed-size byte, JSON, form, and known-length multipart bodies can reach the affected path.\n\nStreaming bodies with an explicit `Content-Length` are not affected in current HTTPX2 releases because the automatically generated `Transfer-Encoding` is already suppressed in that direction.\n\n### Impact\n\nAn attacker may be able to use the conflicting framing headers as a request-smuggling or desynchronization primitive. Exploitation requires an application to pass attacker-controlled request framing headers and associated body data to HTTPX2, use HTTP/1.1, and communicate through a proxy or origin that accepts conflicting headers and interprets them differently from another hop.\n\nDepending on the downstream infrastructure, successful exploitation could interfere with requests sharing a persistent connection, bypass front-end routing or authorization decisions, or poison responses or caches. Applications that do not forward attacker-controlled `Transfer-Encoding` headers are not directly exposed.\n\n### Mitigation\n\nUpgrade to HTTPX2 `2.11.0` or later. Patched versions treat `Content-Length` and `Transfer-Encoding` as mutually exclusive when applying automatically generated request headers.\n\nIf upgrading is not immediately possible, remove `Transfer-Encoding` and other hop-by-hop framing headers from untrusted input before constructing outbound requests. Applications acting as proxies should derive outbound framing from the body rather than forwarding inbound `Content-Length` or `Transfer-Encoding` headers.","status":"published","published":"2026-09-08T20:46:28Z","modified":"2026-09-10T12:25:28.219277036Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-444"],"updated_at":"2026-11-02T15:46:52.891208Z"},{"id":"PYSEC-2026-3849","title":"HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated","description":"### Summary\n\nHTTPX2 can automatically add a `Content-Length` header to a request that already contains a caller-supplied `Transfer-Encoding` header. The resulting HTTP/1.1 request contains both framing headers, which can create an ambiguous message boundary and enable request smuggling or connection desynchronization when processed by intermediaries that disagree about which header takes precedence.\n\n### Details\n\nWhen a request body has a known size, HTTPX2's content encoder returns a default `Content-Length`. `Request._prepare()` applies each default header with `setdefault()`, which only checks whether that same header is already present. It does not check whether the mutually exclusive `Transfer-Encoding` header is present.\n\nFor example:\n\n```python\nimport httpx2\n\nrequest = httpx2.Request(\n    \"POST\",\n    \"http://example.com/\",\n    headers={\"Transfer-Encoding\": \"chunked\"},\n    content=b\"test 123\",\n)\n\nprint(request.headers)\n```\n\nThe request contains both:\n\n```text\nTransfer-Encoding: chunked\nContent-Length: 8\n```\n\nOn an HTTP/1.1 connection, the body is serialized using chunked transfer coding while both headers are sent on the wire. This violates HTTP message-framing requirements. Fixed-size byte, JSON, form, and known-length multipart bodies can reach the affected path.\n\nStreaming bodies with an explicit `Content-Length` are not affected in current HTTPX2 releases because the automatically generated `Transfer-Encoding` is already suppressed in that direction.\n\n### Impact\n\nAn attacker may be able to use the conflicting framing headers as a request-smuggling or desynchronization primitive. Exploitation requires an application to pass attacker-controlled request framing headers and associated body data to HTTPX2, use HTTP/1.1, and communicate through a proxy or origin that accepts conflicting headers and interprets them differently from another hop.\n\nDepending on the downstream infrastructure, successful exploitation could interfere with requests sharing a persistent connection, bypass front-end routing or authorization decisions, or poison responses or caches. Applications that do not forward attacker-controlled `Transfer-Encoding` headers are not directly exposed.\n\n### Mitigation\n\nUpgrade to HTTPX2 `2.11.0` or later. Patched versions treat `Content-Length` and `Transfer-Encoding` as mutually exclusive when applying automatically generated request headers.\n\nIf upgrading is not immediately possible, remove `Transfer-Encoding` and other hop-by-hop framing headers from untrusted input before constructing outbound requests. Applications acting as proxies should derive outbound framing from the body rather than forwarding inbound `Content-Length` or `Transfer-Encoding` headers.","status":"published","published":"2026-09-10T09:45:01.065667Z","modified":"2026-09-10T12:15:06.096986959Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T15:52:57.255153Z"},{"id":"UBUNTU-CVE-2026-84380","description":"HTTPX2 is a next generation HTTP client for Python. Prior to 2.11.0, Request._prepare() in src/httpx2/httpx2/_models.py can add a body-derived Content-Length header to a request that already contains a caller-supplied Transfer-Encoding header because its setdefault() processing checks each default header independently rather than treating the two framing headers as mutually exclusive. Fixed-size byte, JSON, form, and known-length multipart bodies can therefore be serialized over HTTP/1.1 with both headers, allowing request smuggling or connection desynchronization when downstream intermediaries disagree about which framing header takes precedence. This issue is fixed in version 2.11.0.","status":"published","published":"2026-09-02T18:21:00Z","modified":"2026-10-17T13:01:13.113932439Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T16:57:22.213888Z"}]}}
