GHSA-g586-ccqf-7x4r

Suggest an improvement
Source
https://github.com/advisories/GHSA-g586-ccqf-7x4r
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-g586-ccqf-7x4r/GHSA-g586-ccqf-7x4r.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-g586-ccqf-7x4r
Aliases
Published
2026-07-09T23:19:29Z
Modified
2026-07-09T23:30:09Z
Severity
  • 8.2 (High) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N CVSS Calculator
Summary
mint: Unbounded streams map growth via PUSH_PROMISE without follow-up HEADERS
Details

Summary

Mint's HTTP/2 client accepts PUSH_PROMISE frames from any server it connects to and inserts every promised stream into a per-connection map without consulting max_concurrent_streams. A malicious or compromised HTTP/2 server can flood the client with PUSH_PROMISE 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':handle_push_promise/3 in lib/mint/http2.ex dispatches every inbound PUSH_PROMISE frame to 'Elixir.Mint.HTTP2':decode_push_promise_headers_and_add_response/5, which inserts a :reserved_remote entry into conn.streams for the promised ID. The only validation applied is that the promised ID is even and not already present; client_settings.max_concurrent_streams 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 PUSH_PROMISE frames and never sends the matching HEADERS never trips that check, and the existing tally counts only streams in open states, not :reserved_remote entries.

HTTP/2 server push is accepted by default (client_settings.enable_push 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 PUSH_PROMISE 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 PUSH_PROMISE frames (flags = END_HEADERS) 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 PUSH_PROMISE 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 client_settings: [enable_push: false] to 'Elixir.Mint.HTTP':connect/4. Mint will then reject any inbound PUSH_PROMISE frame with a PROTOCOL_ERROR before the vulnerable code path is reached.

Resources

Database specific
{
    "cwe_ids":  [
        "CWE-770"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-07-09T23:19:29Z",
    "nvd_published_at":  "2026-06-02T16:16:44Z",
    "severity":  "HIGH"
}
References

Affected packages

Hex / mint

Package

Name
mint
Purl
pkg:hex/mint

Affected ranges

Type
SEMVER
Events
Introduced
0.2.0
Fixed
1.9.0

Affected versions

0.*
0.2.0
0.2.1
0.3.0
0.4.0
0.5.0
1.*
1.0.0
1.1.0
1.2.0
1.2.1
1.3.0
1.4.0
1.4.1
1.4.2
1.5.0
1.5.1
1.5.2
1.6.0
1.6.1
1.6.2
1.7.0
1.7.1
1.8.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-g586-ccqf-7x4r/GHSA-g586-ccqf-7x4r.json"