Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-54892

CVE-2026-54892: Plug Nested-Parameter DoS Vulnerability

CVE-2026-54892 is a denial of service flaw in Plug's nested-parameter decoder that allows attackers to exhaust server resources through malicious query strings. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-54892 Overview

CVE-2026-54892 is an algorithmic complexity vulnerability in Plug, the specification and connection adapter library for building web applications in Elixir. The flaw resides in Plug.Conn.Query.decode/4, which parses query strings and application/x-www-form-urlencoded request bodies. Deeply nested bracket keys such as a[a][a][a]=1 trigger quadratic decode behavior, allowing an unauthenticated remote attacker to saturate BEAM schedulers and render the server unresponsive. The vulnerability is tracked under [CWE-407: Inefficient Algorithmic Complexity].

Critical Impact

A single HTTP request near the default 1,000,000-byte body limit can carry roughly 333,000 nesting levels and saturate a scheduler for minutes. A small number of concurrent requests can take a Plug-based server fully offline without authentication or route knowledge.

Affected Products

  • Plug versions 1.15.0 through 1.15.4
  • Plug versions 1.16.0 through 1.16.3, 1.17.0 through 1.17.1, 1.18.0 through 1.18.2
  • Plug versions 1.19.0 through 1.19.2

Discovery Timeline

  • 2026-06-23 - CVE CVE-2026-54892 published to NVD
  • 2026-06-23 - Last updated in NVD database

Technical Details for CVE-2026-54892

Vulnerability Analysis

The vulnerability sits in lib/plug/conn/query.ex, specifically in Plug.Conn.Query.decode/4 and Plug.Conn.Query.decode_each/2. These routines parse URL-encoded request bodies and query strings into nested maps. When a key contains many bracketed segments, the decoder walks each bracket and performs a map operation keyed on an ever-growing binary prefix of the original key.

Because the implementation hashes the full byte range of the prefix at every step, the cost grows quadratically with the number of nesting levels (N). The supporting helpers Plug.Conn.Query.split_keys/6, Plug.Conn.Query.insert_keys/3, and Plug.Conn.Query.finalize_pointer/2 are all part of the affected code path. The patched releases introduce a hard limit through the new module attribute @max_nesting 32, capping bracket depth before quadratic cost becomes exploitable.

Root Cause

The root cause is missing bounds enforcement on user-controlled nesting depth combined with repeated full-key hashing at each parse step. Plug accepted arbitrarily deep bracket structures and did not bound the work performed per request. The default Plug.Parsers.URLENCODED body limit of 1,000,000 bytes is more than sufficient to fit hundreds of thousands of bracket levels.

Attack Vector

An unauthenticated attacker sends a single HTTP POST with Content-Type: application/x-www-form-urlencoded (or a GET with a crafted query string) containing a key composed of approximately 333,000 nested brackets. The decoder consumes a BEAM scheduler for minutes while attempting to parse the request. Issuing the request in parallel against all online schedulers exhausts the runtime and stops the application from handling legitimate traffic.

text
  @typedoc since: "1.16.0"
  @opaque decoder() :: map()

+ @max_nesting 32
+
  @doc """
  Decodes the given `query`.

Source: GitHub Commit 9c5d37c

The patch introduces the @max_nesting 32 module attribute in lib/plug/conn/query.ex. Once depth exceeds this bound, decoding aborts before the quadratic cost path can be reached.

Detection Methods for CVE-2026-54892

Indicators of Compromise

  • Inbound HTTP requests whose URL or request body contains an unusually long sequence of [ and ] characters in a single parameter name.
  • Sudden, sustained spikes in BEAM scheduler utilization or :scheduler_wall_time without corresponding increases in request volume.
  • Elixir or Phoenix application processes blocked inside Plug.Conn.Query.decode_each/2 visible in :observer or :recon dumps.
  • Reverse proxy or load balancer logs showing requests with Content-Length near 1,000,000 bytes targeting form-decoded endpoints.

Detection Strategies

  • Inspect HTTP traffic at the web application firewall or reverse proxy layer for parameter names exceeding a sane bracket count (for example, more than 32 [ characters).
  • Alert on Plug-based application unresponsiveness paired with low external CPU pressure but high scheduler busy percentage.
  • Add structured logging for requests that exceed normal parse time thresholds in Plug.Parsers.

Monitoring Recommendations

  • Export BEAM telemetry (scheduler utilization, run queue length, reductions per process) to your observability stack and alert on anomalies.
  • Track HTTP 5xx and request timeout rates per endpoint to catch slow saturation against form-handling routes.
  • Ingest reverse proxy access logs into a SIEM and build queries for repeated requests with extreme parameter-name length.

How to Mitigate CVE-2026-54892

Immediate Actions Required

  • Upgrade Plug to a fixed release: 1.15.5, 1.16.4, 1.17.2, 1.18.3, or 1.19.3.
  • Restart all Elixir or Phoenix nodes after upgrading so the patched Plug.Conn.Query module is loaded.
  • Until patched, place a reverse proxy or WAF rule in front of the application that rejects parameters with more than 32 bracket characters.

Patch Information

The Erlang Ecosystem Foundation published the advisory in GitHub Security Advisory GHSA-j43x-5hjq-rgxf and tracks it as EEF-CVE-2026-54892 on OSV. The fix is delivered across multiple branches by the merge commits 9c5d37c, a61124aa, c317d08f, d4e55683, and d737eb23. Each commit adds the @max_nesting 32 bound to lib/plug/conn/query.ex. See the CNA advisory for vendor details.

Workarounds

  • Lower the Plug.Parsers.URLENCODED body limit below the default 1,000,000 bytes for endpoints that do not require large form payloads.
  • Reject or strip request parameters containing excessive bracket nesting at the ingress layer (Nginx, HAProxy, Cloudflare, or AWS WAF).
  • Apply per-IP and per-route rate limits to URL-encoded POST endpoints to constrain concurrent decode work.
bash
# Pin a fixed Plug version in mix.exs and refresh dependencies
# mix.exs
# {:plug, "~> 1.19.3"}

mix deps.update plug
mix deps.get
mix compile

# Example Nginx rule to drop requests with extreme bracket nesting
# /etc/nginx/conf.d/plug-cve-2026-54892.conf
if ($request_uri ~* "(\[){33,}") {
    return 400;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.