← Back to Research

A redirect that overreads: CVE-2026-9256 in the NGINX rewrite module

The shape that matters. CVE-2026-9256 (CVSS 8.1) lives in one of the most-used NGINX features: rewrite. A regex with overlapping PCRE captures plus a replacement string that references multiple of them, in a redirect or args context, mishandles the capture data on an unauthenticated request. The edge proxy you trust to be boring has a sharp edge in its busiest config block.

NGINX sits in front of an enormous fraction of the internet, and its rewrite directive is in nearly every non-trivial configuration: canonicalizing URLs, redirecting old paths, rewriting to backends. That ubiquity is exactly why CVE-2026-9256 is worth a careful read: the bug is not in some obscure module, it is in the regex-rewrite machinery operators touch every day.

What the advisory describes

The vulnerability is in the ngx_http_rewrite_module. It manifests when a rewrite directive uses a regex pattern with distinct, overlapping Perl-Compatible Regular Expression (PCRE) captures (the advisory's example is a pattern like ^/((.*))$, where an outer group encloses an inner group) and a replacement string that references multiple of those captures, such as $1$2, in a redirect or arguments context. Under that combination, an unauthenticated request can trigger the flaw in how the captured substrings are handled.

The two conditions worth internalizing are precise: overlapping captures (nested groups that cover the same text), and a replacement that uses more than one of them in a redirect (return 301 ...$1$2) or query-argument context. A configuration that captures once and substitutes once is not in the described shape. The danger is the nested-group-plus-multi-reference pattern, which is common enough (people write ((.*)) by accident, or to group an alternation) that plenty of real configs match it.

The lesson: your config is attack surface too

It is tempting to think of CVEs as living in application code, with the proxy as a trusted, static layer. This bug is a corrective. The configuration you wrote (the specific regex in your rewrite rules) is part of the reachable attack surface, and a vendor bug in how that config is processed can be triggered by an ordinary unauthenticated request. Edge software earns its “boring and reliable” reputation precisely because bugs in it are rare and loud; when one lands in the most-used directive, it deserves prompt attention rather than the patch-it-next-quarter treatment a frontend dependency might get.

There is a second-order reason this class is easy to under-prioritize: the trigger condition is specific enough that many operators will glance at the advisory, decide “we probably do not do that,” and move on without checking. But “overlapping captures referenced more than once” is not an exotic pattern: it is what you get when someone wraps an alternation in an extra group, or copies a rewrite rule from a forum answer, or builds a redirect that stitches together two captured path segments. The only way to know whether your configuration matches the dangerous shape is to actually grep your rewrite rules, not to reason about whether you “usually” write them that way. Assumption is how a fixable exposure becomes a standing one. Treat the advisory as a prompt to inventory, not a prompt to guess.

It is also a reminder that regular expressions in security-relevant positions (rewrite rules, WAF patterns, validation filters) deserve the same review discipline as code, because they are code. A regex that looks correct can carry subtle behavior around captures, anchoring, and backtracking that only matters under adversarial input. The rewrite block is one of the few places where a single line of configuration is directly exposed to every unauthenticated visitor on the internet.

The defensible check

You confirm exposure two ways (by version and by config shape) neither of which involves attacking a live edge:

# CVE-2026-9256: version + config-pattern check (no exploitation).
nginx -v 2>&1                       # compare build against the fixed release in the advisory
# Surface rewrite rules that match the dangerous shape: nested captures + multi-ref replacement.
grep -rnE 'rewrite\s+[^;]*\(\([^)]*\)\)[^;]*\$[0-9]\$[0-9]' /etc/nginx/
grep -rnE 'return\s+30[0-9][^;]*\$[0-9]\$[0-9]' /etc/nginx/
# FINDING = a pre-fix NGINX build AND a rewrite/return using overlapping captures
# with a multi-capture replacement in a redirect/args context. A patched build,
# or configs without the nested-capture-plus-multi-ref pattern, is a PASS.

The fix

How Celvex Sentry tests for this

Our continuous-monitoring suite fingerprints edge-proxy builds and, where configuration is in scope for an engagement, flags rewrite rules matching the vulnerable overlapping-capture shape. The finding requires a pre-fix build together with a config that can actually trigger the flaw. A patched proxy or a rule that does not match the pattern is a PASS, not noise. When both hold, we mint a Proof Capsule with the version evidence, the matching rule, and the upgrade-and-simplify remediation attached.

Sources

Get your exposure check: full report in 4-24 hours

Real assessment on production-grade infrastructure. We prove what is exploitable and attach the fix. Paying customers get priority capacity.

Queue My Assessment