Skip to content

GHSA-h4x7-gw46-3wm6 CVE-2026-84379 PYSEC-2026-3848

HTTPX2: Multipart part header injection via unvalidated file Content-Type and custom headers

Medium PyPI
Severity
5.3 / 10
Medium · CVSS 3.1
Exploit chance (EPSS)
0.32%
Chance of exploitation in the next 30 days. Higher than 24.69% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-93 Improper Neutralization of CRLF Sequences ('CRLF Injection')
Fix
2.11.0
Upgrade httpx2 to this version or later

Description

Summary

HTTPX2 serializes the per-file Content-Type and custom headers supplied through the files= tuple API directly into the multipart/form-data body without validating custom header names or values. An attacker who can influence upload metadata passed to HTTPX2 can use CR or LF characters to terminate a multipart part header and inject additional part headers or end the part header block early.

Details

The three-element file tuple accepts (filename, content, content_type), and the four-element form accepts (filename, content, content_type, headers). FileField.render_headers() interpolates the supplied header names and values between CRLF delimiters without validating them.

For example:

import httpx2

request = httpx2.Request(
    "POST",
    "https://example.com/upload",
    headers={"Content-Type": "multipart/form-data; boundary=BOUNDARY"},
    files={
        "file": (
            "safe.txt",
            b"payload",
            "text/plain\r\nX-Injected: true",
        )
    },
)

print(request.read().decode())

The generated body contains an attacker-injected part header:

--BOUNDARY
Content-Disposition: form-data; name="file"; filename="safe.txt"
Content-Type: text/plain
X-Injected: true

payload
--BOUNDARY--

The same issue affects names and values in the custom header mapping from the four-element tuple.

Field names and filenames are serialized through a separate escaping path and do not permit CRLF header injection.

Impact

Applications are affected when they pass attacker-controlled upload metadata into the per-file content_type or custom headers arguments. The receiving server interprets injected lines as genuine multipart part headers. Depending on how that server validates and processes uploads, this can alter part semantics or bypass checks based on part headers.

This does not split the outer HTTP request: the injected headers are contained within the multipart body. The concrete security impact therefore depends on the downstream multipart parser and application behavior.

Mitigation

Upgrade to HTTPX2 2.11.0 or later. Patched versions reject forbidden control characters in multipart part header names and values and raise ValueError before serializing the request.

If upgrading is not immediately possible, applications should validate custom multipart header names as HTTP field-name tokens. They should reject NUL, CR, LF, other C0 controls except horizontal tab, and DEL in per-file content types and custom header values before passing them to HTTPX2.

Affected versions

PyPI

PackageVulnerableFixed in
httpx2
< 2.11.0
2.11.0
httpx2
< 2.11.0
2.11.0

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

httpx2 PyPI → 2.11.0

pip
pip install --upgrade "httpx2>=2.11.0"
poetry
poetry add "httpx2>=2.11.0"
uv
uv add "httpx2>=2.11.0"

Severity breakdown

CVSS 3.1 5.3

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

Weakness

CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')

The product uses CRLF (carriage return line feeds) as a special element, e.g. to separate lines or records, but it does not neutralize or incorrectly neutralizes CRLF sequences from inputs.

How to prevent it
  • Implementation: Avoid using CRLF as a special sequence.
  • Implementation: Appropriately filter or quote CRLF sequences in user-controlled input.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-8xx6-hgc6-gc2m
HTTPX2: Streaming response decompression does not bound peak memory (decompression amplification)
High Also affects httpx2
GHSA-7mj9-2mp8-4m2p
HTTPX2: Secure WebSocket traffic sent without TLS through SOCKS proxies
High Also affects httpx2
GHSA-pf96-p4fj-6566
HTTPX2: Conflicting Content-Length and Transfer-Encoding headers can be auto-generated
Medium Also affects httpx2
GHSA-f2fp-rgf2-35cp
HTTPX2: Quadratic SSE line buffering can cause CPU denial of service
Medium Also affects httpx2
GHSA-j9f9-w8pj-32f8
Spring Framework Server Sent Event stream corruption while rendering fragments
Critical Same weakness, CWE-93
EEF-CVE-2026-75484
HTTP/2 header field values containing CR, LF or NUL are passed to the application unvalidated in Bandit
Not rated yet Same weakness, CWE-93
GHSA-8c48-q9wj-3w37
rclone: FTP Command Arguments Permit CRLF Injection When Custom Encoding Preserves Newlines
Medium Same weakness, CWE-93
GHSA-m8rv-5g2x-5cg5
undici vulnerable to CRLF Injection via blob-like body 'type' property
Medium Same weakness, CWE-93

Credits: maxisbey

Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor