elixir-plug/plug · Security
Plug: quadratic-time decoding of nested query/body parameters enables denial of service
- GHSA ID
- GHSA-j43x-5hjq-rgxf
- CVE ID
- CVE-2026-54892
- Severity
- high
- Published
- Updated
- CVSS v4
- 8.7 · 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
Description
Summary
Plug's nested-parameter decoder (Plug.Conn.Query) parses URL-encoded keys in time quadratic in their bracket-nesting depth. Any unauthenticated remote attacker that can reach a Plug-based HTTP endpoint can pin a BEAM scheduler for minutes with a single small request.
Details
For a key like a[a][a]...=1, Plug.Conn.Query.split_keys/6 (in lib/plug/conn/query.ex) builds an accumulator of :binary.part prefixes (a, a[a], a[a][a], …) that grow ~3 bytes per level. Plug.Conn.Query.insert_keys/3 then does one Map.put per level keyed on that growing prefix, hashing the full byte range each time, and Plug.Conn.Query.finalize_pointer/2 repeats the prefix-keyed walk to materialize the structure. Total cost is O(N²) in nesting depth.
The same code path handles query strings, application/x-www-form-urlencoded bodies, and multipart field names via Plug.Conn.Query.decode/4 and decode_each/2. The default Plug.Parsers.URLENCODED cap is 1 MB (~333,000 nesting levels), but Plug.Parsers accepts urlencoded payloads up to its overall body limit (20 MB by default), so an attacker can scale the per-request work well beyond the urlencoded-specific cap. The decoder shows ~4× scaling per 2× input (16k levels ≈ 195 ms on a single scheduler).
PoC
- POST
a[a][a]...[a]=1asapplication/x-www-form-urlencodedto any endpoint of a Plug-based app. Even at the 1 MB urlencoded-parser default the payload carries ~333,000 nesting levels; with the broaderPlug.Parsersbody limit (20 MB default) a single request can carry millions. - Launch one such request per scheduler concurrently. Each pins a scheduler for minutes; legitimate traffic stalls once all schedulers are busy.
Impact
A single low-bandwidth sender can render any internet-reachable Plug-based service (most Phoenix and standalone Elixir/Erlang web stacks) unresponsive. No credentials, specific endpoint, or prior knowledge of the application is required.
References
CWEs
- CWE-407 · Inefficient Algorithmic Complexity
References
- https://github.com/elixir-plug/plug/security/advisories/GHSA-j43x-5hjq-rgxf ↗
- https://nvd.nist.gov/vuln/detail/CVE-2026-54892 ↗
- https://github.com/elixir-plug/plug/commit/9c5d37c440eaae92869eed7c014c47266744fadb ↗
- https://github.com/elixir-plug/plug/commit/a61124aa625d819a218fb07f90afbac8aa85eb0e ↗
- https://github.com/elixir-plug/plug/commit/c317d08fdcf96e17931f7419275b2b8c4bf3e951 ↗
- https://github.com/elixir-plug/plug/commit/d4e5568392a4b29e545b91e12e87d6098f976145 ↗
- https://github.com/elixir-plug/plug/commit/d737eb236f17e31a36290e39f9ef3cd86a1343bd ↗
- https://cna.erlef.org/cves/CVE-2026-54892.html ↗
- https://github.com/elixir-plug/plug/blob/v1.19.3/CHANGELOG.md#v1193-2026-06-23 ↗
- https://osv.dev/vulnerability/EEF-CVE-2026-54892 ↗
- https://github.com/advisories/GHSA-j43x-5hjq-rgxf ↗