nginx rewrite module heap corruption from escaped captures
Escaped capture data can turn a rewrite rule into a heap write when the length pass and the copy pass stop agreeing. In the affected path, ngx_http_script_copy_capture_code() can size a buffer for one version of the data and then write a longer escaped version into it. The result is heap corruption, worker crashes, and in the worst case a path towards remote code execution.
How escaped capture data turns a rewrite into a heap write
The trigger is a crafted URI that reaches the rewrite module with capture groups containing escapable characters. The rewrite engine first calculates how much space the copied capture needs, then copies the data into the allocated buffer. If the state used for that calculation is stale, the estimate is wrong and the write can overrun the heap buffer.
That is the ugly part of nginx rewrite module heap corruption: the failure happens inside normal rewrite processing, not in some exotic corner of the request pipeline. A rule that looks harmless on paper can become dangerous when it mixes captured input with escaping behaviour that changes between the sizing pass and the copy pass.
Heap corruption is the practical outcome. A crash is the common one. A controlled heap spray is the more uncomfortable one.
The length pass and copy pass stop agreeing in ngx_http_script_copy_capture_code()
ngx_http_script_copy_capture_code() sits at the centre of the bug. The function handles capture copying for rewrite scripts, and the bad state means the length calculation no longer matches the data written later. If the copied capture expands after escaping, the buffer size is no longer enough.
That mismatch is enough on its own. Once the copy pass writes beyond the allocated area, adjacent heap memory gets corrupted. With the right request pattern, repeated allocations and frees can make the heap layout easier to abuse. That is where exploitation attempts start to look like heap spray activity rather than a simple crash.
Rewrite directives that mix ? with set or if open the door
The risky pattern is rewrite directives that include ? in the replacement string and then feed captured values into set or if. That combination gives the rewrite module more moving parts while it is still carrying capture state. If the capture data includes escapable characters, the stale state can surface at the worst point.
This is not every rewrite rule with captures. It is the ones that combine query string handling with conditional logic and captured data in the same path. Those are the ones worth treating as suspect until the build is confirmed and the edge layer is blocking obvious exploitation attempts.
Hardening nginx before CVE-2026-42945 bites
nginx 1.30.1 is the clean boundary here. Older builds should be treated as exposed if they carry the affected rewrite module code path. Verify the binary in use, not the package name in a repo entry, because drift between what was installed and what is actually running is a classic way to lie to yourself.
Upgrade to nginx 1.30.1 or later and confirm the build in use
Upgrade to nginx 1.30.1 or later. Then check the running worker process, not just the config management output. A version string in a changelog means little if the old binary is still on disk and still serving traffic.
If a reverse proxy or container image is involved, confirm the image tag and the deployed artefact. Rebuilds and restarts fail in the most boring way possible, which is usually the way these things slip through.
Block exploit patterns at the edge and watch for worker crashes
Edge filtering buys time, not immunity. Cloudflare pushed emergency WAF rules for exploitation attempts against CVE-2026-42945, which tells you what the traffic looks like when someone starts testing this in anger. A WAF block does not fix the heap bug, but it can cut off obvious probes before they reach nginx.
Watch for worker process crashes, restart loops, and any surge in requests that target rewrite-heavy routes with odd capture content. If the service starts dying under a narrow set of URIs, do not assume it is random bad luck. That pattern is often the first visible sign that the rewrite module is being poked where it hurts.




