Single WebSocket frame can OOM the BEAM via Bandit deflate
TL;DR - In bandit > 0.5.8 and < 1.11.0, the permessage-deflate WebSocket path calls :zlib.inflate/2 with no output-size limit. One small high-ratio compressed frame inflates to GiB-scale allocations in the connection process heap, exhausting BEAM memory before any application code runs. Only reachable when compress: true is explicitly negotiated, but when it is, the attacker is unauthenticated and your app cannot interpose guards.
What happened
bandit is an Elixir HTTP/WebSocket server used as a Plug adapter, including in Phoenix stacks.
The vulnerability lives in lib/bandit/websocket/permessage_deflate.ex. When permessage-deflate is negotiated, Bandit calls :zlib.inflate/2 with no cap on decompressed output size, then immediately materialises the entire payload as a contiguous binary via IO.iodata_to_binary/1 - on the connection process heap. The websocket_options.max_frame_size setting only limits the compressed, on-the-wire frame size. It says nothing about what that frame decompresses to.
The practical result: an unauthenticated client sends a ~6 MiB compressed frame, it inflates to GiB-scale, and the BEAM node OOMs. The decompression happens pre-handler, so there is no application-level hook you can rely on to stop it after the fact.
Two conditions must both be true for the path to be reachable: the Bandit global websocket_options.compress must be set, and the per-upgrade call to WebSockAdapter.upgrade/4 must pass compress: true. Phoenix defaults to compress: false, so Phoenix apps are only affected if a developer explicitly opted in.
Who is impacted
- Deployments using
banditwith WebSockets wherepermessage-deflateis explicitly enabled. - Threat model: any internet-reachable WebSocket endpoint where both compress flags are true. The attacker needs no credentials.
| Item | Detail |
|---|---|
| Package | bandit |
| Affected versions | > 0.5.8 and < 1.11.0 |
| Patched version | 1.11.0 |
| Severity | CVSS v4 8.2 (High) |
| Weakness | CWE-770 - Allocation of Resources Without Limits or Throttling |
What to do now
- Upgrade to
bandit1.11.0as soon as possible."Patched versions: 1.11.0"
- Audit your compress configuration before you patch:
- Grep for
WebSockAdapter.upgrade(call sites that passcompress: true. - In Phoenix, check endpoint and socket configuration for
websocket: [compress: true].
- Grep for
- If you cannot upgrade immediately, remove
compress: truefrom all internet-facing WebSocket upgrade paths. No compression negotiation means the vulnerable code path is not reached. - Treat unexplained memory spikes or OOM events on Bandit nodes as potential exploit signals, particularly when they correlate with inbound WebSocket traffic.
Content is AI-assisted and reviewed by our team, but issues may be missed and best practices evolve rapidly, send corrections to [email protected]. Always consult official documentation and validate key implementation decisions before making design or security choices.
