CVE-2026-42786 Overview
CVE-2026-42786 is a resource exhaustion vulnerability in the mtrudel/bandit Elixir HTTP server. The flaw resides in the WebSocket fragment reassembly path inside Elixir.Bandit.WebSocket.Connection.handle_frame/3. Bandit appends every incoming Continuation{fin: false} frame to a per-connection iolist without enforcing a cumulative size cap. An unauthenticated remote peer can stream continuation frames indefinitely, growing the BEAM heap until the operating system or supervisor kills the process. Phoenix Channels and LiveView both run over WebSock on Bandit, so any stock Phoenix application that accepts socket connections exposes this attack surface. The vulnerability affects Bandit versions from 0.5.0 before 1.11.0 and is tracked under [CWE-770].
Critical Impact
Unauthenticated network attackers can exhaust server memory and crash Phoenix applications by sending a stream of WebSocket continuation frames that never set the FIN bit.
Affected Products
- mtrudel Bandit >= 0.5.0 and < 1.11.0
- Phoenix Channels applications running over Bandit
- Phoenix LiveView applications running over Bandit
Discovery Timeline
- 2026-05-01 - CVE-2026-42786 published to NVD
- 2026-05-05 - Last updated in NVD database
Technical Details for CVE-2026-42786
Vulnerability Analysis
The vulnerability lives in lib/bandit/websocket/connection.ex. When Bandit receives a fragmented WebSocket message, handle_frame/3 accumulates each Continuation frame's payload into a per-connection iolist. The reassembly continues until a frame with fin: true arrives. The existing max_frame_size option only constrains the size of a single frame on the wire. It does not bound the aggregate size of a fragmented message.
A malicious peer can therefore send small, individually valid continuation frames in an unbounded sequence. Each frame's payload is appended to the BEAM process heap. Memory grows linearly with the number of frames sent, eventually triggering the OOM killer or supervisor termination of the connection process.
Root Cause
The accumulation occurs before WebSock.handle_in/2 is invoked. The application layer never sees the partial message and has no opportunity to interpose a size check. This violates the resource-allocation guarantees expected of a network-facing protocol parser, mapping directly to [CWE-770] Allocation of Resources Without Limits or Throttling.
Attack Vector
An unauthenticated remote attacker establishes a WebSocket connection to any endpoint served by Bandit. The attacker then transmits a continuous stream of continuation frames with fin=0 and never sends a terminating frame. Because Phoenix Channels and LiveView both rely on WebSock over Bandit, default Phoenix deployments are exposed as soon as they accept socket upgrades.
# Patch excerpt from lib/bandit.ex
* `max_frame_size`: The maximum size of a single WebSocket frame (expressed as
- a number of bytes on the wire). Defaults to 0 (no limit)
+ a number of bytes on the wire). Use a value of 0 for no limit. Defaults to 8_000_000
+ * `max_fragmented_message_size`: The maximum size of a WebSocket message delivered across
+ multiple continuation frames (expressed as a number of bytes on the wire). Does NOT affect the
+ handling of single-frame messages. Use a value of 0 for no limit. Defaults to 8_000_000
Source: GitHub Commit 21612c7
The patch introduces the new max_fragmented_message_size option and changes the default max_frame_size from unlimited to 8_000_000 bytes. The fix in lib/bandit/extractor.ex updates the default applied during parser construction:
def new(frame_parser, primitive_ops_module, opts) do
- max_frame_size = Keyword.get(opts, :max_frame_size, 0)
+ max_frame_size = Keyword.get(opts, :max_frame_size, 8_000_000)
Source: GitHub Commit 21612c7
Detection Methods for CVE-2026-42786
Indicators of Compromise
- Sustained increases in BEAM virtual machine memory consumption tied to specific WebSocket connection PIDs.
- WebSocket connections that remain open for extended periods while transmitting only opcode=0x0 (continuation) frames.
- Supervisor restart events for Bandit.WebSocket.Connection processes terminated by :killed or :out_of_memory reasons.
- Operating system OOM killer events targeting the BEAM process serving the Phoenix endpoint.
Detection Strategies
- Instrument Bandit telemetry events such as [:bandit, :websocket, :recv] to track per-connection cumulative frame bytes and alert on sessions that exceed a defined threshold without delivering a final frame.
- Inspect WebSocket traffic at the proxy or load balancer for connections sending many continuation frames without a corresponding FIN bit set.
- Correlate BEAM :erlang.memory/0 snapshots with active WebSocket process counts to identify outlier connections.
Monitoring Recommendations
- Export BEAM process memory and message queue metrics to a centralized observability platform and alert on sudden growth.
- Monitor application logs for repeated WebSock connection terminations originating from the same client IP or token.
- Track Phoenix endpoint connection rates and per-IP connection counts to identify abusive sources.
How to Mitigate CVE-2026-42786
Immediate Actions Required
- Upgrade Bandit to version 1.11.0 or later, which introduces the max_fragmented_message_size cap and a non-zero default max_frame_size.
- Audit existing Bandit configuration for explicit max_frame_size: 0 overrides and remove them or replace with a bounded value.
- Review the GitHub Security Advisory GHSA-pf94-94m9-536p for vendor guidance.
Patch Information
The fix is delivered in Bandit 1.11.0 via commit 21612c7. It enforces a default 8 MB cap on both individual frames and reassembled fragmented messages. Operators who require larger payloads can tune the new options explicitly. Additional context is available in the CNA advisory and the OSV record.
Workarounds
- Place a WebSocket-aware reverse proxy in front of Bandit and enforce a maximum message size at the proxy layer.
- Apply per-connection rate limits and idle timeouts to terminate sessions that send continuation frames without making forward progress.
- Restrict WebSocket endpoints to authenticated users where possible to reduce the unauthenticated attack surface.
# Example Bandit configuration after upgrading to 1.11.0
# config/runtime.exs
config :my_app, MyAppWeb.Endpoint,
adapter: Bandit.PhoenixAdapter,
http: [
websocket_options: [
max_frame_size: 1_000_000,
max_fragmented_message_size: 4_000_000
]
]
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


