A newly disclosed flaw in NGINX has gone unnoticed for roughly 18 years, sitting in code that ships on a huge share of the world's web servers. Tracked as CVE-2026-42945 and nicknamed "NGINX Rift," the bug is a heap buffer overflow in the request-rewriting engine that an unauthenticated attacker can leverage for remote code execution. It carries a CVSS v4 score of 9.2 and affects both NGINX Plus and NGINX Open Source. A working proof-of-concept already exists, so administrators should treat patching as urgent.
What's affected
The vulnerability lives in the ngx_http_rewrite_module and was found by a researcher operating under the handle "depthfirst." According to the disclosure, the defect has existed since NGINX 0.6.27 — a release that first shipped in 2008 — which is what gives the flaw its 18-year lifespan.
- Vulnerable: every release from NGINX 0.6.27 up to and including 1.30.0
- Fixed: NGINX 1.31.0 and 1.30.1
CVE-2026-42945 was one of four memory-corruption issues reported in the same effort. The others — CVE-2026-42946, CVE-2026-40701, and CVE-2026-42934 — were, per the PoC author, surfaced automatically by depthfirst's analysis system after onboarding the NGINX source tree.
What triggers the bug
The overflow is reachable when a rewrite directive is followed by another rewrite, an if, or a set directive that uses an unnamed PCRE capture group — references like $1 or $2 — and the replacement string contains a question mark (?).
How the flaw works
NGINX builds rewritten strings with a two-pass script engine: the first pass calculates how large a buffer it needs, and the second pass copies the data into that buffer. The mismatch that causes the overflow comes down to where the is_args flag is set.
When a rewrite replacement contains a ?, the engine sets is_args on the main engine. The length-calculation pass, however, runs against a freshly zeroed sub-engine. The result is two passes that disagree about the data size:
- Length pass: sees
is_args = 0, so it returns the raw capture length. - Copy pass: sees
is_args = 1, so it callsngx_escape_uriwithNGX_ESCAPE_ARGS, which expands every escapable byte into three bytes.
Because the buffer was sized for the unescaped length, the copy pass writes attacker-controlled URI data past the end of an undersized heap allocation.
From overflow to code execution
The public PoC turns this into unauthenticated RCE by pairing the overflow with an ASLR-bypass chain that uses a common same-host local file inclusion / arbitrary-file-read primitive. Exploitation relies on cross-request heap feng shui: the attacker grooms the heap to place a target object next to the overflow, then corrupts the cleanup pointer of an adjacent ngx_pool_t. Since URI bytes cannot contain null bytes, the fake structure is sprayed through POST request bodies instead of the URI. The corrupted pointer is redirected to a counterfeit ngx_pool_cleanup_s, which calls system() when the pool is destroyed.
Trying it out
The reference repository ships a Docker environment to stand up a vulnerable instance:
docker compose -f env/docker-compose.yml up
The proof-of-concept and a technical write-up are available in the jelasin/CVE-2026-42945 GitHub repository.
Detection and mitigation
The fix is to upgrade to a patched build — NGINX 1.31.0 or 1.30.1. If you can't patch immediately, audit your configuration for rewrite directives that use unnamed capture groups and convert them to named captures.
For example, a directive written as:
rewrite ^/(.*)$ /$1 break;
should be rewritten to use named capture groups instead of the unnamed $1 reference. Review every affected rewrite directive, not just one, since any unnamed capture feeding a subsequent rewrite, if, or set with a ? in the replacement can reach the vulnerable path.
Given that NGINX serves a large fraction of the internet and that the flaw stayed hidden for nearly two decades, defenders should assume capable attackers may already know about it and prioritize remediation accordingly.