CVE-2026-42786 - Bandit Buffers Unbounded WebSocket Continuation Frames, Allowing Unauthenticated
CVE-2026-42786 - Bandit Buffers Unbounded WebSocket Continuation Frames, Allowing Unauthenticated
GHSA-pf94-94m9-536p HIGH erlang/bandit
CVE: CVE-2026-42786
Summary
A single unauthenticated WebSocket client can exhaust server memory in any Bandit-fronted application that accepts WebSocket connections. The fragmented-message reassembly path appends every Continuation{fin: false} frame's payload to a per-connection iolist with no cumulative size cap, so a peer that streams continuation frames indefinitely (never setting fin=1) grows BEAM heap linearly until the OS or a supervisor kills the process. max_frame_size only bounds individual frames; there is no max_message_size option available today.
Details
The bug is in lib/bandit/websocket/connection.ex, in the fragment branch of handle_frame/3 (around lines 80–95). When a non-final continuation arrives, Bandit builds the next accumulator as [connection.fragment_frame.data | frame.data] with no running byte-count check. A peer can therefore stream max-sized continuations forever and grow BEAM resident memory without bound. When fin=1 finally arrives (if ever), IO.iodata_to_binary/1 flattens the whole iolist, briefly doubling peak memory. The attacker does not need to send fin=1 — simply holding the connection open is enough to pin the bytes.
Suggested fix: track a running cumulative byte count on the connection state and add a configurable max_message_size. When exceeded, terminate the connection with RFC 6455 close code 1009 (:max_message_size_exceeded) instead of continuing to append.
PoC
A self-contained reproduction script is below. It starts Bandit 1.10 on 127.0.0.1:4321 with a trivial WebSock echo handler, completes a WebSocket handshake, sends one text frame with fin=0, then streams up to 4096 continuation frames of 1 MiB each — also fin=0. A background sampler logs :erlang.memory(:total) every 250 ms.
A correctly-fixed server would close the connection with code 1009 once max_message_size is exceeded.
Impact
Unauthenticated DoS via memory exhaustion. A single connection can drive BEAM heap to gigabytes; a
📌 来源: GitHub-Advisory | 🆔 CVE-2026-42786 | 📅 2026-05-07