CVE-2026-42945: rewrite directive failure mode

CVE-2026-42945: rewrite directive failure mode

The nginx rewrite module can end up writing past the end of a heap buffer when is_args goes stale during rewrite processing. Crafted URIs with escapable characters are enough to push the length pass and copy pass out of sync, which is the sort of bug that turns a routing rule into a crash. In the worst case, heap corruption opens the door to remote code execution.

Where the rewrite path goes wrong in practice

The failure shows up in rewrite rules that mix a replacement string containing ? with set or if, then reference capture groups. That combination is awkward because the module has to calculate output size, then rebuild the URI with escapes applied, and both steps need to agree on the final length.

Once is_args keeps the wrong state, the sizing pass can assume one layout while the copy pass emits another. The result is an undersized heap allocation followed by a write that carries on past the buffer boundary. Worker process crashes are the obvious outcome. Heap spray changes the shape of the mess, not the fact of it.

Why stale is_args turns into heap corruption

The bug sits in the gap between “how much space do I need?” and “how much did I actually write?”. In normal rewrite handling, those two answers should match. Here they do not, because the state that tracks whether a ? needs to be treated as the argument separator is left stale.

Escaping makes the mismatch worse. A URI that looks short in its raw form can grow once characters are escaped during the rewrite. If the length pass does not account for that growth, the heap allocation comes back too small. The copy pass then writes the escaped form into that space and corrupts adjacent memory.

The length pass and copy pass stop agreeing

This is the core failure mode. The module counts one version of the data, then copies another. That is bad enough in a stack buffer; on the heap it tends to be nastier, because nearby metadata or application data can be trampled as the write runs on.

The practical trigger is not exotic. A rewrite chain with captures, a conditional, and a query marker in the replacement string gives enough moving parts for the state to drift. Once the module thinks is_args has already been dealt with, the later copy step can inherit the wrong size assumptions.

ngx_http_script_copy_capture_code() writes past the buffer

ngx_http_script_copy_capture_code() is where the mismatch becomes memory corruption. It copies captured content into the destination buffer after the size check has already been made. If that check was based on stale state, the function writes escaped data into a buffer that was never large enough for it.

That is a plain heap buffer overflow, not a subtle logic quirk. The buffer ends up too small, the copy keeps going, and the overwrite lands wherever the allocator placed the next chunk. At that point, the best outcome is a dead worker.

What to change on live systems before the next scan

If vulnerable rewrite directives are still present, the site stays exposed even with traffic filtering in place. The immediate job is to remove the rule shape that triggers the bug, then move the build to a fixed release.

Remove risky rewrite directives that mix ?, set, if, and capture groups

Search for rewrite rules that place ? in the replacement string and then chain into set or if while using capture groups. Those are the patterns that deserve attention first. They are not all broken on their own, but they are the ones that line up with the stale is_args path.

A blunt control is better than a clever one here. If a rule can be simplified without capture reuse or chained conditionals, do that. If it cannot be simplified, isolate it and test it with crafted input that includes escapable characters. Broken rewrite logic is usually very obedient right up until it is not.

Upgrade to nginx 1.30.1 and verify the fix in place

Upgrade to nginx 1.30.1 or later. That is the clean fix for CVE-2026-42945, and it removes the stale-state bug rather than asking the configuration to behave itself forever.

After the upgrade, verify the running version on every host and check the deployed config for leftover rewrite patterns that still match the failure mode. Old config paired with a new binary is a classic way to keep the trouble alive. The worker process does not care that the change looked sensible in review.

Related posts

Agentic AI still needs domain judgement

Agentic AI can write the thing, but it still cannot tell you whether the thing is right. That is where domain expertise matters, because a clean config or neat bit of glue logic can still be wrong in...

Weekly Tech Digest | 06 Jul 2026

Stay updated with the latest in tech! This digest covers AI ethics, auto industry shifts, and the impact of politics on technology, exploring today's pressing issues.

wolfCOSE zero-allocation parsing in embedded C

wolfCOSE looks sensible only if you care about what your firmware actually has to carry. I like that, because on small targets the wrong crypto feature can cost more than the message itself, and there...