VYPR
Medium severityNVD Advisory· Published Jun 2, 2026· Updated Jun 2, 2026

CVE-2026-49753

CVE-2026-49753

Description

Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling') vulnerability in elixir-mint Mint allows attacker-controlled HTTP/1 servers to desynchronise response framing on shared connections.

Mint's HTTP/1 Content-Length parser, Mint.HTTP1.Parse.content_length_header/1 in lib/mint/http1/parse.ex, parses the header value with Integer.parse/1, which accepts an optional + or - sign prefix. The length >= 0 guard rejects negatives, but inputs such as +0 or +123 are returned as valid lengths. RFC 7230 specifies Content-Length = 1*DIGIT, with no sign character permitted.

A fronting proxy or load balancer that strictly enforces the grammar will reject or reframe a header like Content-Length: +0, while Mint silently treats it as zero. When Mint reuses the socket (keep-alive, pipelining, or any pooled connection shared across requesters), the parser disagreement is a response-smuggling primitive: the proxy delimits the body one way, Mint another, and bytes from one response get attributed to the next. Where the same Mint connection is shared across trust boundaries, an attacker-controlled upstream can leak bytes into a different consumer's response stream.

This issue affects mint: from 0.1.0 before 1.9.0.

Affected products

1

Patches

1
47e480274802

Merge commit from fork

https://github.com/elixir-mint/mintEric Meadows-JönssonJun 2, 2026via body-scan
2 files changed · +28 3
  • lib/mint/http1/parse.ex+10 3 modified
    @@ -18,12 +18,19 @@ defmodule Mint.HTTP1.Parse do
       def ignore_until_crlf(<<_char, rest::binary>>), do: ignore_until_crlf(rest)
     
       def content_length_header(string) do
    -    case Integer.parse(String.trim_trailing(string)) do
    -      {length, ""} when length >= 0 -> {:ok, length}
    -      _other -> {:error, {:invalid_content_length_header, string}}
    +    trimmed = String.trim_trailing(string)
    +
    +    if only_digits?(trimmed) do
    +      {:ok, String.to_integer(trimmed)}
    +    else
    +      {:error, {:invalid_content_length_header, string}}
         end
       end
     
    +  defp only_digits?(<<char>>) when is_digit(char), do: true
    +  defp only_digits?(<<char, rest::binary>>) when is_digit(char), do: only_digits?(rest)
    +  defp only_digits?(_other), do: false
    +
       def connection_header(string) do
         split_into_downcase_tokens(string)
       end
    
  • test/mint/http1/parse_test.exs+18 0 modified
    @@ -14,6 +14,24 @@ defmodule Mint.HTTP1.ParseTest do
     
         assert content_length_header("-10") ==
                  {:error, {:invalid_content_length_header, "-10"}}
    +
    +    assert content_length_header("+0") ==
    +             {:error, {:invalid_content_length_header, "+0"}}
    +
    +    assert content_length_header("+123") ==
    +             {:error, {:invalid_content_length_header, "+123"}}
    +
    +    assert content_length_header("") ==
    +             {:error, {:invalid_content_length_header, ""}}
    +
    +    assert content_length_header("  100") ==
    +             {:error, {:invalid_content_length_header, "  100"}}
    +
    +    assert content_length_header("1 0") ==
    +             {:error, {:invalid_content_length_header, "1 0"}}
    +
    +    assert content_length_header("0x10") ==
    +             {:error, {:invalid_content_length_header, "0x10"}}
       end
     
       test "connection_header/1" do
    

Vulnerability mechanics

Root cause

"The Content-Length header parser incorrectly accepted values with a leading '+' sign, violating RFC 7230."

Attack vector

An attacker controls an HTTP/1 server that sends a Content-Length header with a leading '+' sign, such as 'Content-Length: +0'. A fronting proxy or load balancer that strictly enforces RFC 7230 will reject or reframe this header, while the vulnerable Mint client will silently parse it as a zero-length body. When Mint reuses a connection, this parser disagreement causes bytes from one response to be attributed to the next, enabling response smuggling [ref_id=1].

Affected code

The vulnerability resides in the `content_length_header/1` function within `lib/mint/http1/parse.ex`. This function previously used `Integer.parse/1`, which allowed optional sign prefixes, leading to incorrect parsing of Content-Length headers.

What the fix does

The patch modifies the `content_length_header/1` function in `lib/mint/http1/parse.ex` to explicitly check if the trimmed header value consists solely of digits using a new `only_digits?/1` helper function. This ensures that values with leading signs like '+0' or '+123', or other non-digit characters, are rejected as invalid content lengths, aligning with RFC 7230 and preventing parser disagreements [patch_id=4518411].

Preconditions

  • inputThe attacker must be able to control an upstream HTTP/1 server that sends a Content-Length header with a leading '+' sign.
  • networkThe vulnerable Mint client must be communicating through a fronting proxy or load balancer that strictly enforces RFC 7230's Content-Length grammar, while Mint itself does not.
  • configThe Mint connection must be shared across trust boundaries, such as through connection pooling or keep-alive, to enable response smuggling.

Reproduction

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>. Connect a Mint HTTP/1 client to the server and issue a request. 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 [ref_id=1].

Generated on Jun 2, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.