CVE-2026-65623 Overview
CVE-2026-65623 is an inefficient algorithmic complexity vulnerability in the mtrudel bandit HTTP server for Elixir. The flaw resides in the WebSocket fragment reassembly path and allows unauthenticated remote attackers to cause denial of service through CPU exhaustion. Affected versions include bandit from 1.11.0 before 1.12.1. The weakness is classified under [CWE-407: Inefficient Algorithmic Complexity].
Critical Impact
An unauthenticated remote attacker can send millions of tiny WebSocket continuation frames using modest bandwidth to pin CPU cores for minutes to hours, denying service to legitimate users across the server.
Affected Products
- mtrudel bandit versions 1.11.0 through 1.12.0
- Elixir/Erlang applications embedding vulnerable bandit releases
- Phoenix applications relying on bandit as the HTTP/WebSocket adapter
Discovery Timeline
- 2026-07-24 - CVE-2026-65623 published to the National Vulnerability Database (NVD)
- 2026-07-30 - Last updated in NVD database
Technical Details for CVE-2026-65623
Vulnerability Analysis
The defect exists in Elixir.Bandit.WebSocket.Connection. The size guard oversize_message?/2, called from handle_frame/3 in lib/bandit/websocket/connection.ex, appends each non-final continuation frame to a left-nested iolist. It then re-measures the entire accumulated buffer with IO.iodata_length/1 on every frame.
Because the buffer grows by one element per frame and is fully re-traversed each time, reassembly work becomes quadratic (O(n^2)) in the number of continuation frames. This behavior converts a linear-looking protocol operation into a super-linear cost that scales dangerously with attacker input.
Root Cause
The max_fragmented_message_size limit (default 8 MB) bounds total bytes but does not bound frame count. Each continuation frame can carry as little as one payload byte. An attacker can therefore stream millions of tiny continuation frames within the byte budget, forcing repeated full-buffer traversals inside a single synchronous callback.
The WebSocket read timeout provides no protection here. It is an idle timeout evaluated between reads and cannot preempt work performed inside a single frame-handling callback.
Attack Vector
The attack requires only network reachability to a WebSocket endpoint served by a vulnerable bandit release. No authentication or user interaction is needed. Many concurrent malicious connections can starve the entire BEAM scheduler pool of CPU, degrading or halting service for legitimate users.
// Patch excerpt from lib/bandit/websocket/connection.ex
compress: nil,
opts: [],
fragment_frame: nil,
+ fragment_size: 0,
span: nil,
metrics: %{}
Source: GitHub Bandit Commit 418ef7e
The patch introduces a running fragment_size counter maintained incrementally as frames arrive. This eliminates the repeated IO.iodata_length/1 traversal and restores linear-time reassembly.
Detection Methods for CVE-2026-65623
Indicators of Compromise
- Sustained high CPU utilization on BEAM schedulers correlated with active WebSocket connections
- Long-lived WebSocket sessions transmitting an unusually high count of small continuation frames (opcode 0x0) with payloads of 1 to a few bytes
- Client connections that never send a final fragment (FIN bit unset) for extended periods
Detection Strategies
- Instrument WebSocket handlers to log per-connection frame counts and average payload sizes, flagging outliers
- Monitor process message queue length and scheduler run time for processes handling WebSocket connections
- Alert on WebSocket sessions where continuation frame counts exceed reasonable application thresholds (for example, greater than 10,000 frames per message)
Monitoring Recommendations
- Track BEAM VM telemetry such as :erlang.statistics(:scheduler_wall_time) to detect scheduler saturation
- Deploy network telemetry that surfaces WebSocket frame counts per source IP over short intervals
- Correlate CPU exhaustion events with concurrent connection counts and source address distributions to identify coordinated abuse
How to Mitigate CVE-2026-65623
Immediate Actions Required
- Upgrade bandit to version 1.12.1 or later in all affected Elixir and Phoenix deployments
- Audit dependency lockfiles (mix.lock) across services to confirm no transitive pin to a vulnerable 1.11.x or 1.12.0 release
- Restart application nodes after the upgrade to ensure all WebSocket connections use patched code paths
Patch Information
The fix is delivered in bandit1.12.1 and is described in the GitHub Security Advisory GHSA-vg8x-66vg-5pxh. The remediation commit 418ef7e tracks fragment size incrementally rather than re-measuring the entire accumulated iolist on every frame. Additional coordinated details are available in the Erlang Ecosystem Foundation CNA advisory and the OSV record EEF-CVE-2026-65623.
Workarounds
- Place a reverse proxy or WebSocket-aware gateway in front of bandit to enforce per-connection frame-count and frame-rate limits
- Reduce the max_fragmented_message_size configuration so quadratic work terminates sooner, accepting reduced legitimate message size as a trade-off
- Apply IP-based rate limiting and connection caps at the load balancer to constrain the number of concurrent long-lived WebSocket sessions per source
# Upgrade bandit in an Elixir project
mix deps.update bandit
mix deps.get
mix deps.compile bandit
# Verify the resolved version is >= 1.12.1
mix deps | grep bandit
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

