On May 13, 2026, F5 Networks and the NGINX project published an advisory for CVE-2026-42945, a heap buffer overflow in ngx_http_rewrite_module. The flaw has been present since NGINX 0.6.27, a release from 2006, which means it spent eighteen years passing through production environments, security audits, and major version milestones without surfacing.
The attack requires no credentials and no prior access to the target. An unauthenticated attacker sends a crafted HTTP request, and the NGINX worker process overflows its heap. On servers running without ASLR, that overflow provides a path to remote code execution. On hardened systems with ASLR enabled, the worker crashes and restarts. Repeated requests can sustain that crash loop indefinitely.
Where the overflow originates
NGINX’s rewrite engine compiles rewrite directives into a small script that executes in two phases. The first phase calculates how much memory to allocate. The second phase copies data into that buffer. The vulnerability lives in a state inconsistency between these two phases, specifically in how the is_args flag is handled across them.
The length pass runs on a freshly initialized sub-engine where is_args starts at 0. No URI escaping is applied, so the calculated size reflects the raw capture length. The copy pass runs on the main engine, where a ? character in the replacement string has already set is_args to 1. At that point, the copy phase calls ngx_escape_uri, which expands reserved characters into three-byte percent-encoded sequences. Characters counted as one byte during the length pass are written as three bytes during the copy pass. The buffer is too small.
The overflow writes attacker-controlled URI data past the end of the allocated heap region. DepthFirstDisclosures, who responsibly disclosed this flaw, documented a full exploitation chain. Using heap feng shui across multiple requests, they position an ngx_pool_t structure adjacent to the overflow target and corrupt its cleanup pointer. When NGINX destroys that pool, it calls whatever address the pointer now holds. POST request bodies deliver the payload past the null-byte restriction that URIs impose. The cleanup call becomes a call to system().
The trigger conditions are specific but common in real-world configurations: a rewrite directive followed by a second rewrite, if, or set directive, using unnamed PCRE capture groups ($1, $2), with a replacement string that includes a ?. That combination is a routine pattern in configurations that rewrite paths to include query strings.
What is affected
The vulnerability covers every NGINX release from 0.6.27 through the current stable line. Fixed releases are available now.
- NGINX Open Source 0.6.27–1.30.0: fixed in
1.30.1(stable) and1.31.0(mainline) - NGINX Open Source 0.6.27–0.9.7: no fix planned; these releases are past end-of-technical-support
- NGINX Plus R32–R36: fixed in R32 P6 and R36 P4
Why this one is worth understanding
The eighteen-year lifespan is notable, but the reason it lasted that long is more instructive than the number itself. The bug does not live in the regex engine, and does not live in the URI escaping function. Both components work correctly in isolation. The error lives in the handoff between them, where state that the main engine accumulates during directive processing is invisible to the fresh sub-engine used for length calculation. Neither pass looks obviously wrong on its own.
The ngx_http_rewrite_module is not a peripheral feature of NGINX. It is a core routing primitive that most non-trivial configurations rely on. Bugs in central surface areas persist precisely because they look like ordinary configuration until the exact combination of directives appears in a specific request.
What teams should do
Patching is straightforward for teams on supported versions. The more useful question is which deployments are actually running vulnerable configurations.
- Upgrade NGINX Open Source to
1.30.1or1.31.0. Upgrade NGINX Plus to R32 P6 or R36 P4. - Audit your rewrite configurations. Search for unnamed PCRE captures (
$1,$2) paired with replacement strings that include a?, followed by a secondrewrite,if, orsetdirective. That is the exact trigger pattern. - Apply the configuration workaround if patching is not immediately possible. Replace unnamed captures with named captures using
(?P<name>...)syntax and reference them as$namein the replacement string. Named captures do not use the positional variable mechanism that causes the state inconsistency. - Check ASLR status on NGINX servers. Without ASLR, the overflow is more directly exploitable for code execution. With ASLR, the primary risk is a crash loop on worker processes.
- Plan migration for any instance on 0.6.27–0.9.7. No patch is planned for those releases. Moving to a supported version is the only remediation path.
CVE-2026-42945 is a useful prompt to revisit how rewrite configurations are reviewed across your fleet. The trigger conditions are auditable with a grep across NGINX config files. Teams that have that inventory are minutes away from knowing their exposure. Teams that rely on manual inspection across distributed deployments face a broader triage problem that this CVE only partly illuminates. The next flaw with a narrow trigger and an eighteen-year history may arrive without a configuration-level workaround to buy time while patching catches up.