GitHub Advisoryadvisory · PyPI
GHSA-pf96-p4fj-6566 HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated
MEDIUM
Official page ↗
- Aliases
- CVE-2026-84380
- Ecosystem
- PyPI
- Packages
- httpx2
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Weaknesses
- CWE-444
- Reviewed
- 2026-09-08
Affected packages
• PyPI httpx2: < 2.11.0 → fixed in 2.11.0
Description
Summary
HTTPX2 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.
Details
When 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.
For example:
```python
import httpx2
request = httpx2.Request(
"POST",
"http://example.com/",
headers={"Transfer-Encoding": "chunked"},
content=b"test 123",
)
print(request.headers)
```
The request contains both:
```text
Transfer-Encoding: chunked
Content-Length: 8
```
On 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.
Streaming 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.
Impact
An 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.
Depending 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.
Mitigation
Upgrade to HTTPX2 `2.11.0` or later. Patched versions treat `Content-Length` and `Transfer-Encoding` as mutually exclusive when applying automatically generated request headers.
If 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.
Related
Alias · CVE (1)
- CVE-2026-84380 HTTPX2 is a next generation HTTP client for Python. vulnerability
Weakness · CWE (1)
- CWE-444 Inconsistent Interpretation of HTTP Requests weakness
References
- https://github.com/pydantic/httpx2/security/advisories/GHSA-pf96-p4fj-6566 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-84380 advisory
- https://github.com/pydantic/httpx2/pull/1137 web
- https://github.com/pydantic/httpx2/commit/829b93a2393212996f613e635261f777d9ec6eab web
- https://github.com/pydantic/httpx2 package
- https://github.com/pydantic/httpx2/releases/tag/v2.11.0 web