Skip to content

EEF-CVE-2026-109584 CVE-2026-109584 GHSA-7gfj-7gvq-3xqj

HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit

Not rated yet Hex
Severity
0.0 / 10
Unknown · CVSS 4.0
Exploit chance (EPSS)
0.60%
Chance of exploitation in the next 30 days. Higher than 48.83% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)
Fix
1.14.0
Upgrade bandit to this version or later

Description

Summary

Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large cookie value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter's run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.

Bandit.HTTP2.Connection caps only the compressed block (max_header_block_size), and its check of the decoded list against max_header_list_size never fires because that setting defaults to :infinity. combine_cookie_crumbs/1 in lib/bandit/http2/stream.ex then joins every crumb into one binary.

This issue affects bandit: from 0.3.3 before 1.14.0.

Details

1. Compression

The attacker's header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte max_header_block_size. It inserts one 4,058-byte cookie into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. HPAX.decode returns a list whose entries all point at the same binary, so decoding itself stays cheap.

2. Missing decoded limit (lib/bandit/http2/connection.ex, lib/bandit/http2/settings.ex)

After decoding, the connection compares header_list_size(headers) against local_settings.max_header_list_size. That setting defaults to :infinity, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.

3. Expansion (lib/bandit/http2/stream.ex)

read_headers calls combine_cookie_crumbs/1, which joins every crumb with Enum.map_join/3 into a single binary of about 183 MB before Plug.call/2 runs. max_concurrent_streams also defaults to :infinity, so N streams allocate N times as much.

Proof of concept

  1. Against a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte cookie stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.
  2. Send it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with END_HEADERS on the last.
  3. The request reaches the plug with a cookie header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it.

Impact

An unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node's memory, taking down every application on the node.

Workarounds

On 1.12.2 and later, set a finite decoded header list limit, for example http_2_options: [default_local_settings: [max_header_list_size: 65_536]], which resets the stream before the cookie crumbs are joined. From 0.7.0, disabling HTTP/2 with http_2_options: [enabled: false] removes the vulnerable path.

Affected versions

Hex

PackageVulnerableFixed in
bandit
>= 0.3.3, < 1.14.0
1.14.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.

bandit Hex → 1.14.0

mix
{:bandit, "~> 1.14.0"} # then: mix deps.update bandit

Severity breakdown

CVSS 4.0 0.0

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
None
User interaction
None
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
None
Availability (vulnerable system)
High
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None

Weakness

CWE-409: Improper Handling of Highly Compressed Data (Data Amplification)

The product does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
EEF-CVE-2026-116078
HTTP/2 request bodies made of 1-byte DATA frames amplify memory use in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-108529
SETTINGS and stream-0 WINDOW_UPDATE frames trigger quadratic work over blocked streams in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-110499
Client-chosen HPACK encoder table size is applied uncapped, growing per-connection state with every response in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-111103
HTTP/2 StreamError recovery rolls back connection state and bypasses per-connection limits in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-111101
HTTP/1.1 chunked request bodies made of 1-byte chunks amplify memory use in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-113436
Quadratic bignum parsing of Content-Length and Host port values in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-110314
WebSocket frames keep reaching the WebSock after a server-initiated close in Bandit
Not rated yet Also affects bandit
EEF-CVE-2026-114213
WebSocket 1-byte continuation frames bypass `max_fragmented_message_size` in Bandit
Not rated yet Also affects bandit

Credits: Jonatan Männchen / EEF, Mat Trudel, Peter Ullrich

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