Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling') vulnerability in elixir-mint mint allows a malicious HTTP/1 server to desynchronize an intermediary and the Mint client on a pooled connection, poisoning the responses to subsequent requests that share the connection.
messagebody/1 in lib/mint/http1.ex selects chunked framing when chunked is the first coding listed in a response's Transfer-Encoding fields. RFC 9112 section 6.3 applies chunked framing only when chunked is the final coding, and otherwise reads the body until the server closes the connection. For a response such as Transfer-Encoding: chunked, gzip, an intermediary that follows the RFC treats every byte up to the close as the body, while Mint ends the body at the zero-length chunk and parses the remaining bytes as the response to the next request on the connection.
Mint also keeps the connection open after an HTTP/1.0 response, final or 1xx, that carries Transfer-Encoding and Connection: keep-alive. RFC 9112 section 6.1 requires treating the framing of such a message as faulty and closing the connection after it, so bytes after its chunked body are parsed as the response to the next request in the same way.
This issue affects mint: from 0.1.0 before 1.11.0.
Allocation of Resources Without Limits or Throttling vulnerability in elixir-mint mint allows a malicious HTTP/2 server to make the client hold up to about 16 MiB per connection in frames it should reject, consuming client memory.
Mint.HTTP2.Frame.decodenext/2 in lib/mint/http2/frame.ex compares a frame with the client's maxframesize (16,384 bytes by default) only once the whole declared payload has arrived. Until then it returns :more, and Mint.HTTP2 keeps every received byte in the connection buffer. A server can declare a frame length of up to 16,777,215 bytes and withhold the last byte, keeping roughly 1,024 times the advertised limit buffered for as long as the connection stays open. The server has to send every byte the client buffers, so there is no amplification, and the buffer stops at the 24-bit frame length limit.
This issue affects mint: from 0.1.0 before 1.11.0.
Allocation of Resources Without Limits or Throttling vulnerability in elixir-mint mint allows a malicious HTTP/2 server to exhaust memory on the client host and cause a denial of service.
Mint.HTTP2 enforces the client's maxheaderlistsize setting only on the compressed size of an inbound header block, while RFC 9113 section 6.5.2 defines the limit on the decoded header list. An HPACK indexed field costs one byte on the wire and decodes to a dynamic table entry of up to 4 KB, and joincookieheaders/1 in lib/mint/http2.ex copies every cookie value of a response into one new binary. A header block under the default 256 KB wire limit therefore makes the client allocate about 1 GB for a single response, and several such responses in one delivery exhaust the memory of the process that owns the connection or of the whole VM.
This issue affects mint: from 1.1.0 before 1.11.0.
Summary
Mint's HTTP/1 client accepts Content-Length header values with a leading + sign (e.g. +0, +123), which RFC 7230 forbids (Content-Length = 1DIGIT). On a connection shared with a strict fronting proxy or load balancer, this parser disagreement is a response-smuggling primitive: the proxy frames the body one way, Mint frames it another, and bytes meant for one response leak into the next consumer's response stream.
Details
'Elixir.Mint.HTTP1.Parse':contentlengthheader/1 in lib/mint/http1/parse.ex parses the header value with Integer.parse/1. By design, Integer.parse/1 accepts an optional + or - sign prefix. The length >= 0 guard rules out negatives, but inputs such as "+0", "+123", or "+1" pass through and are returned as valid lengths.
A strict proxy or load balancer rejects or reframes Content-Length: +0\r\n, while Mint silently treats it as 0. When Mint reuses the socket (keep-alive, pipelining, or any pooled connection) and the connection is shared with a proxy that frames the same bytes differently, trailing bytes the proxy attributes to response N are attributed by Mint to response N+1. Across trust boundaries (shared pools, multi-tenant fronting) this enables response smuggling.
PoC
1. Stand up a raw TCP server that returns HTTP/1.1 200 OK\r\nContent-Length: +0\r\nConnection: keep-alive\r\n\r\n<smuggled bytes>. 2. Connect a Mint HTTP/1 client to the server and issue a request. 3. Observe that Mint reports the response as status 200 with Content-Length: "+0" and an empty body, leaving the smuggled bytes sitting in the socket buffer for the next response.
Impact
Response-smuggling / request-response desync primitive in Mint's HTTP/1 client parser. Anyone using Mint (directly or via Finch, Tesla's Mint adapter, Req, etc.) to talk through a shared or pooled connection where a fronting proxy enforces RFC 7230 strictly while Mint does not is exposed. The attacker is the response producer (a malicious or compromised upstream, or anything that can inject bytes into a shared origin response); exploitation into a cross-request data leak additionally requires the deployment to share a Mint connection across trust boundaries.
Resources
Introduction commit: https://github.com/elixir-mint/mint/commit/65e0e86d799a6d3b08e4372fccdd9747535e0dd6 Patch commit: https://github.com/elixir-mint/mint/commit/47e48027480228e4e32a0b4df39db497b4804921
Summary
Mint's HTTP/2 client accumulates CONTINUATION header-block fragments into a per-connection buffer with no cap on size or frame count. A malicious or compromised HTTP/2 server can drive the client's memory to arbitrary size by streaming an endless chain of CONTINUATION frames after a HEADERS frame that omits ENDHEADERS, causing memory exhaustion and BEAM process death. A single connection to an attacker-controlled HTTP/2 endpoint is sufficient.
Details
When Mint's HTTP/2 receive path observes a HEADERS frame without the ENDHEADERS flag, 'Elixir.Mint.HTTP2':handleheaders/3 parks the unparsed header-block fragment in conn.headersbeingprocessed. Every subsequent CONTINUATION frame on that stream is then appended to the accumulator by 'Elixir.Mint.HTTP2':handlecontinuation/3.
Nothing in the receive path bounds this accumulator: there is no per-stream size cap, no CONTINUATION frame-count cap, and maxheaderlistsize is only enforced on outgoing requests (its default is :infinity, and the only enforcement helper inspects serversettings for request encoding, never inbound header blocks). Each CONTINUATION payload can be up to the peer-advertised SETTINGSMAXFRAMESIZE, so the attacker can grow headersbeingprocessed to arbitrary size at line rate.
PoC
1. Stand up a raw TCP server that speaks the HTTP/2 handshake. 2. After the client's request HEADERS arrives, respond with a HEADERS frame on stream 1 with flags = 0 (no ENDHEADERS, no ENDSTREAM) and an empty header-block fragment. 3. Stream CONTINUATION frames on stream 1, each with flags = 0 and a payload up to SETTINGSMAXFRAMESIZE. Never set ENDHEADERS. 4. The client's process memory grows linearly with the flood and the BEAM process eventually crashes with OOM.
Impact
Remote, unauthenticated denial-of-service against any process using Mint as an HTTP/2 client against an untrusted or attacker-influenced server. A single connection is sufficient to drive memory to arbitrary size and crash the BEAM process. The default Mint configuration is vulnerable; no client-side opt-in is required. Scored CVSS v4.0 8.2 (HIGH).
Workarounds
Restrict Mint to HTTP/1 on connections to untrusted servers by passing protocols: [:http1] to 'Elixir.Mint.HTTP':connect/4. This avoids the vulnerable HTTP/2 receive path entirely, at the cost of losing HTTP/2 for those connections.
Resources
Introduction commit: https://github.com/elixir-mint/mint/commit/596ca4304504be68939c4929e0831557097962b8 Patch commit: https://github.com/elixir-mint/mint/commit/b662d127d3028b5426c88d4c9cc7fe430491a10b
Summary
Mint's HTTP/2 client accepts PUSHPROMISE frames from any server it connects to and inserts every promised stream into a per-connection map without consulting maxconcurrentstreams. A malicious or compromised HTTP/2 server can flood the client with PUSHPROMISE frames and withhold the matching response HEADERS, pinning one map entry per frame indefinitely until the client process runs out of memory.
Details
'Elixir.Mint.HTTP2':handlepushpromise/3 in lib/mint/http2.ex dispatches every inbound PUSHPROMISE frame to 'Elixir.Mint.HTTP2':decodepushpromiseheadersandaddresponse/5, which inserts a :reservedremote entry into conn.streams for the promised ID. The only validation applied is that the promised ID is even and not already present; clientsettings.maxconcurrentstreams is not consulted at promise time.
The concurrency cap is only checked when the response HEADERS for the promised stream arrive. A server that emits PUSHPROMISE frames and never sends the matching HEADERS never trips that check, and the existing tally counts only streams in open states, not :reservedremote entries.
HTTP/2 server push is accepted by default (clientsettings.enablepush defaults to true), so no application opt-in is required. A single long-lived HTTP/2 connection to a hostile server lets it pin one conn.streams entry per PUSHPROMISE frame, with no upper bound.
PoC
1. Stand up a raw TCP HTTP/2 server that completes the handshake and ACKs the client's SETTINGS. 2. Wait for the client's request HEADERS and capture its odd stream ID. 3. Send a flood of PUSHPROMISE frames (flags = ENDHEADERS) associated with the captured stream, each promising a fresh even stream ID and carrying a minimal HPACK-encoded header block. 4. Never send the matching response HEADERS for any of the promised IDs. 5. The client's conn.streams map grows by one entry per PUSHPROMISE frame (~148 bytes/entry); memory grows linearly and the BEAM process eventually crashes with OOM.
Impact
Remote, unauthenticated denial-of-service against any process using Mint as an HTTP/2 client against an untrusted or attacker-influenced server. Server push is on by default, so no application code change can prevent it short of disabling push or upgrading. Affected populations include outbound HTTP/2 clients in web backends, webhook delivery systems, scrapers, federated and proxy components, and any service that follows redirects to third-party HTTP/2 origins.
Workarounds
Disable HTTP/2 server push on connections to untrusted servers by passing clientsettings: [enablepush: false] to 'Elixir.Mint.HTTP':connect/4. Mint will then reject any inbound PUSHPROMISE frame with a PROTOCOLERROR before the vulnerable code path is reached.
Resources
Introduction commit: https://github.com/elixir-mint/mint/commit/65c6394d05a1b8aa4a7461708c3aa173e8d7a5cf Patch commit: https://github.com/elixir-mint/mint/commit/70b97b6a5209fb288b0e04d8e657dda26c59de67