CVE-2026-54892: Plug: quadratic-time decoding of nested query/body parameters enables denial of service
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.splitkeys/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.insertkeys/3 then does one Map.put per level keyed on that growing prefix, hashing the full byte range each time, and Plug.Conn.Query.finalizepointer/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 decodeeach/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
1. POST a[a][a]...[a]=1 as application/x-www-form-urlencoded to any endpoint of a Plug-based app. Even at the 1 MB urlencoded-parser default the payload carries ~333,000 nesting levels; with the broader Plug.Parsers body limit (20 MB default) a single request can carry millions. 2. 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
Introduction commit: https://github.com/elixir-plug/plug/commit/712b875d3442c765d8d37e546ffd5ad9f8afcc55 Patch commit: https://github.com/elixir-plug/plug/commit/b4aa8a0665ce2726a6d5af44467fb4f59595b107
Other sources
Inefficient algorithmic complexity in Plug's nested-parameter decoder allows an unauthenticated remote attacker to cause denial of service. Plug.Conn.Query.decode/4 (and Plug.Conn.Query.decodeeach/2) parse query strings and application/x-www-form-urlencoded request bodies. When a key contains many bracketed segments such as a[a][a][a]=1, the decoder walks the brackets and, for each of the N levels, performs a map operation keyed on an ever-growing binary prefix of the key, hashing the full byte range at each step. The total decode cost is therefore quadratic in the number of nesting levels.
With the default Plug.Parsers.URLENCODED body limit of 1,000,000 bytes, a single request can carry roughly 333,000 nesting levels and saturate a BEAM scheduler for minutes. A small number of concurrent requests can saturate all schedulers and render a Plug-based server unresponsive. No authentication or knowledge of application routes is required.
This vulnerability is associated with program files lib/plug/conn/query.ex and program routines Plug.Conn.Query.decode/4, Plug.Conn.Query.decodeeach/2, Plug.Conn.Query.splitkeys/6, Plug.Conn.Query.insertkeys/3, and Plug.Conn.Query.finalizepointer/2.
This issue affects plug from 1.15.0 before 1.15.5, 1.16.4, 1.17.2, 1.18.3, and 1.19.3.
— NVD
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
erlang/plugto a version that resolves this vulnerability.Fixed in 1.19.3 - Upgrade
Upgrade
erlang/plugto a version that resolves this vulnerability.Fixed in 1.18.3 - Upgrade
Upgrade
erlang/plugto a version that resolves this vulnerability.Fixed in 1.17.2 - Upgrade
Upgrade
erlang/plugto a version that resolves this vulnerability.Fixed in 1.16.4 - Upgrade
Upgrade
erlang/plugto a version that resolves this vulnerability.Fixed in 1.15.5 - Upgrade
Upgrade
Plugto a version that resolves this vulnerability.Fixed in 1.15.5 - Upgrade
Upgrade
Plugto a version that resolves this vulnerability.Fixed in 1.16.4 - Upgrade
Upgrade
Plugto a version that resolves this vulnerability.Fixed in 1.17.2 - Upgrade
Upgrade
Plugto a version that resolves this vulnerability.Fixed in 1.18.3 - Upgrade
Upgrade
Plugto a version that resolves this vulnerability.Fixed in 1.19.3
Event History
Frequently Asked Questions
What is the severity of CVE-2026-54892?
CVE-2026-54892 has a risk rating of 66, indicating a significant potential for denial of service.
How do I fix CVE-2026-54892?
To mitigate CVE-2026-54892, ensure you are using the latest version of the Plug library that includes the fix for this vulnerability.
What is the impact of CVE-2026-54892?
CVE-2026-54892 allows an unauthenticated remote attacker to exploit the inefficient decoding algorithm, resulting in potential denial of service.
Who is affected by CVE-2026-54892?
CVE-2026-54892 affects applications using the Plug library that process nested query and body parameters.
What conditions are required to exploit CVE-2026-54892?
An attacker needs to send crafted query strings or application/x-www-form-urlencoded request bodies containing numerous keys to exploit CVE-2026-54892.