Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-42786 — bandit

🟠 CVSS 8.0 — High ✅ No Known Exploit CWE-770 NVD
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Bandit Buffers Unbounded WebSocket Continuation Frames, Allowing Unauthenticated Memory Exhaustion

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 small number of concurrent connections OOM-kills the host.

Affected by default. No opt-in flag, no configuration option to mitigate. Any Phoenix application is on the vulnerable path: Phoenix Channels and LiveView both run over WebSock on Bandit, so a stock Phoenix app exposes this surface as soon as it accepts socket connections — including the LiveView socket that almost every Phoenix 1.7+ app mounts at /live. Plug apps that mount any custom WebSock handler are equally affected. Applications that expose no WebSocket endpoints are not.

The exploit also survives almost every common deployment topology: L4 load balancers, HTTP-mode reverse proxies, and TLS-terminating edge proxies (Cloudflare, Fly.io, Fastly, etc.) all tunnel post-upgrade WebSocket frames opaquely without inspecting size. There is no application-level workaround either — the accumulation happens *before* WebSock.handle_in/2 is called, so by the time the application could check, Bandit has already buffered the iolist. The fix belongs in Bandit.

Script and Logs

```elixir

# Bandit WebSocket fragmented-message accumulation PoC.

#

# lib/bandit/websocket/connection.ex:80-95 appends every incoming

# Continuation{fin: false} frame's payload to connection.fragment_frame.data

# as iodata, with no cumulative cap. max_frame_size only bounds *each*

# frame; a peer that streams an unbounded number of max-sized continuations

# without ever setting fin=1 grows the iolist linearly in BEAM memory until

# the OS kills the process. The eventual IO.iodata_to_binary/1 in the

# fin=true branch also momentarily doubles peak memory.

#

# This script starts Bandit 1.10 on 127.0.0.1:4321, opens a WebSocket,

# sends one text frame with fin=0 followed by a continuous stream of

# continuation frames (also fin=0), and samples BEAM memory while doing so.

# A correct server would close the connection with 1009 once a configured

# max-message-size is exceeded; the buggy server keeps growing.

#

# Run: elixir scripts/bandit/ws_fragment_memory_exhaustion.exs

Mix.install([

{:bandit, "~> 1.10"},

{:plug, "~> 1.19"},

{:websock_adapter, "~> 0.5"}

])

defmodule EchoSocket do

@behaviour WebSock

def init(_opts), do: {:ok, %{}}

def handle_in(_message, state), do: {:ok, state}

def handle_info(_message, state), do: {:ok, state}

def terminate(_reason, state), do: {:ok, state}

end

defmodule DemoApp do

@behaviour Plug

def init(opts), do: opts

def call(conn, _opts) do

conn

|> WebSockAdapter.upgrade(EchoSocket, %{}, [])

|> Plug.Conn.halt()

end

end

defmodule FragmentFlood do

@port 4321

@fragment_payload_bytes 1 * 1024 * 1024

@fragment_count 4096

@sample_every_ms 250

def run do

{:ok, _} = Bandit.start_link(plug: DemoApp, ip: {127, 0, 0, 1}, port: @port)

sock = ws_handshake!()

sampler_pid = spawn_link(&sample_memory_loop/0)

payload_chunk = :binary.

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality none, integrity none, availability high.

CVSS metrics in full

The score comes from this vector: 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 — reachable from anywhere that can route to the service.
  • Attack complexity: Low — the attack works reliably, with no preparation.
  • Attack requirements: None — no deployment-specific condition has to hold.
  • Privileges required: None — an unauthenticated stranger can try it.
  • User interaction: None — nobody has to be tricked into anything.
  • Confidentiality impact: None.
  • Integrity impact: None.
  • Availability impact: High — total loss, or loss the attacker controls.

Weakness class

CVE-2026-42786 is classified as CWE-770: Allocation of Resources Without Limits. Resources are allocated on request with no cap, so a client can exhaust them.

Affected software

CVE-2026-42786 is recorded against 2 packages.

  • bandit
  • unknown

Timeline and source

Published on 7 May 2026 and last revised on 30 July 2026. No public exploit is currently recorded for this entry. A vendor advisory or fix has been published. Record sourced from NVD.

References

github.com (Web)
nvd.nist.gov (Advisory)
github.com (Web)
cna.erlef.org (Web)
github.com (Package)
osv.dev (Web)

Other advisories for this package

bandit has other advisories on record. If you are patching this one, these are worth checking on the same host:

Same weakness in other software

These advisories are the same class of weakness (CWE-770: Allocation of Resources Without Limits) in other software:

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector 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
CWE CWE-770
Public Exploit ✅ No
Source NVD
Published 2026-05-07
Updated 2026-08-20
Modified 2026-07-30

Affected Packages

Software From version Fixed in
bandit
unknown

Similar Threats

Site Security Check

Is bandit part of your stack?

CVE-2026-42786 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026