CVE-2026-39804 - Bandit's unbounded WebSocket inflate causes BEAM OOM with a single frame

📡 GitHub-Advisory · 2026-05-07

CVE-2026-39804 - Bandit's unbounded WebSocket inflate causes BEAM OOM with a single frame

CVE-2026-39804

GHSA-frh3-6pv6-rc8j HIGH erlang/bandit

CVE: CVE-2026-39804

Summary

When a Bandit-fronted server has explicitly enabled WebSocket permessage-deflate (compress: true), an unauthenticated client can OOM the BEAM with a single ~6 MiB WebSocket frame. Bandit's inflate step has no output-size cap, so a small high-ratio compressed frame (e.g. zeros, ~1024:1 ratio) decompresses unbounded into the connection process before any application code runs. Phoenix and LiveView are not vulnerable by default — they ship with compress: false. Affected apps are those that have deliberately opted in to permessage-deflate.

Details

In lib/bandit/websocket/permessage_deflate.ex:111-115, :zlib.inflate/2 is called without an output-size limit, and IO.iodata_to_binary/1 then materializes the entire decompressed payload as one contiguous binary in the connection process's heap.

websocket_options.max_frame_size only bounds the on-the-wire (compressed) frame, not the decompressed output. With ~1024:1 compression on uniform data, an attacker can stay well under any wire-size cap while still forcing GiB-scale allocations. There is no {:more, ...} resumable path on inflate, so upstream callers cannot interpose a 413/close before the allocation completes.

The bug is gated by two server-side flags being true at the same time:

  • Bandit's global websocket_options.compress (defaults to true per bandit.ex:198-201).
  • The per-upgrade connection_opts.compress passed to WebSockAdapter.upgrade/4 (defaults to false per websock_adapter.ex:42-43; Phoenix's default is also false per phoenix/lib/phoenix/transports/websocket.ex:33).

Both must be true for the handshake at bandit/lib/bandit/websocket/handshake.ex:22 to negotiate permessage-deflate. So the bug is only reachable on apps that explicitly opt in (e.g. socket "/ws", MySocket, websocket: [compress: true] in a Phoenix endpoint, or WebSockAdapter.upgrade(conn, ..., compress: true) in a plain Plug app).

Suggested fix: thread a maximum-output-size through t


📌 来源: GitHub-Advisory | 🆔 CVE-2026-39804 | 📅 2026-05-07

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)