Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
💧 Hex
Not in CISA KEV

CVE-2026-54892 — plug

Fix: elixir-plug/plug@9c5d37c

CVE-2026-54892 is a CWE-407 vulnerability in plug. A fix is available for plug — see the affected versions and patch details below.

Plug: quadratic-time decoding of nested query/body parameters enables denial of service

Also known asEEF-CVE-2026-54892GHSA-j43x-5hjq-rgxf
Published
Updated
Affected
5 pkgs
Patched
5 / 5
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-54892.

EPSS Exploitation Probability

via FIRST.org ↗
0.9%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs61th percentile — riskier than 61% of all scored CVEsHighest risk
0.21%0.62%1.04%1.45%0.7%0.7%0.9%0.9%0.9%Jul 26Sep 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

5 pkgs affected
💧plug💧plug💧plug💧plug💧plug

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Hex packages — download data is not available via public APIs for these ecosystems.

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

  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

Affected Packages

5 total 5 fixed
EcosystemPackageVulnerable rangeFix
💧Hexplug≥ 1.15.0&&< 1.15.51.15.5mix deps.update plug
💧Hexplug≥ 1.16.0&&< 1.16.41.16.4mix deps.update plug
💧Hexplug≥ 1.17.0&&< 1.17.21.17.2mix deps.update plug
💧Hexplug≥ 1.18.0&&< 1.18.31.18.3mix deps.update plug
💧Hexplug≥ 1.19.0&&< 1.19.31.19.3mix deps.update plug

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for plug, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update plug to 1.15.5 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-54892 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

Frequently Asked Questions

### 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
O3 Security · Impact-Aware SCA

Is CVE-2026-54892 in your dependencies?

Find it across Hex, including transitive dependencies.

CVE-2026-54892: plug — Fixed in 1.15.5