Container Security

CVE-2026-42945: A Buffer Overflow in NGINX's Rewrite Module Reaches Into Your Kubernetes Clusters (May 2026)

Disclosed May 17, 2026 with public PoC and in-the-wild activity, CVE-2026-42945 is a buffer overflow in NGINX's ngx_http_rewrite_module. It affects core NGINX and the ingress controllers that wrap it, putting cluster ingress in scope.

Safeguard Research Team
Security Research
12 min read

On May 17, 2026, a buffer overflow in NGINX's ngx_http_rewrite_module was disclosed as CVE-2026-42945. Within days, working proof-of-concept code was published and security vendors reported exploitation activity in the wild. The flaw is in core NGINX — the web server and reverse proxy that an enormous fraction of the internet runs on — which means its blast radius extends well past standalone web servers and into every system that embeds or wraps NGINX. That includes NGINX Plus, and, critically for this lane, the Kubernetes ingress controllers built on top of NGINX.

This is the kind of vulnerability that looks narrow on paper and turns out to be wide in practice. The overflow is reachable through specific rewrite directive configurations involving unnamed PCRE captures and question marks in rewrite/return directives. A standalone NGINX is only exposed if its configuration uses the vulnerable construct. But in containerized and Kubernetes environments, configuration is frequently generated dynamically — from Ingress objects, annotations, and templates — which expands both the chance that a vulnerable construct appears and the population of operators who have no idea their generated config touches the affected code path.

Worth stating plainly up front, because the public reporting is not perfectly consistent on this point: the upstream NGINX advisory rates the issue at medium severity, while several third-party writeups emphasize that practical exploitation can reach remote code execution. We treat the severity rating as the vendor's, and the RCE potential as a credible, reported worst case that you should plan around rather than dismiss. This post lays out the verified facts, the mechanics as far as they are public, how to tell if you are exposed, and what to do this week.

TL;DR

  • CVE-2026-42945 is a buffer overflow in NGINX's ngx_http_rewrite_module, disclosed May 17, 2026.
  • Affected: NGINX versions 0.6.27 through 1.30.0, including corresponding NGINX Plus releases. Fixed: NGINX 1.31.0 and 1.30.1.
  • The overflow is triggered by specific rewrite/return configurations involving unnamed PCRE captures and question marks. The vendor rates it medium; third-party analysis reports practical exploitation reaching RCE.
  • Public PoC exists (the DepthFirstDisclosures/Nginx-Rift repository) and exploitation has been reported in the wild. Treat this as actively exploited.
  • This is distinct from CVE-2025-1974 (an ingress-nginx controller flaw) and from CVE-2026-1580 (an ingress-nginx auth-method config-injection issue from February 2026). But because Kubernetes ingress controllers embed core NGINX, the rewrite overflow can reach cluster ingress.
  • Monday action: identify every NGINX binary you run, including the ones hidden inside ingress controller images, and upgrade to a fixed core NGINX. Where you cannot upgrade immediately, audit and constrain rewrite/return rules and generated config.
  • The hard part is not patching one server. It is finding every place NGINX is embedded across your container images and figuring out which of them actually reach the vulnerable code path.

What happened

The verified facts: CVE-2026-42945 was published on May 17, 2026, describing a buffer overflow in the ngx_http_rewrite_module of NGINX. The vulnerable code path is reachable from configuration — specifically rewrite directive configurations that combine unnamed PCRE captures with question marks. The affected version range is broad, NGINX 0.6.27 through 1.30.0, which covers many years of releases and the NGINX Plus builds derived from them. The fixed releases are NGINX 1.31.0 and 1.30.1.

Shortly after disclosure, a working exploit was published to a public GitHub repository (DepthFirstDisclosures/Nginx-Rift), and reporting indicated active exploitation in the wild. The combination — a long-lived flaw in extremely widely deployed software, a public PoC, and observed exploitation — is what elevates this from "patch at your convenience" to "patch now."

It is important to keep three NGINX-adjacent CVEs separate, because they are being discussed together and conflated in some coverage:

  • CVE-2026-42945 (this post): core NGINX, ngx_http_rewrite_module buffer overflow, May 17, 2026.
  • CVE-2025-1974: a Kubernetes ingress-nginx controller vulnerability, a different component and different mechanism.
  • CVE-2026-1580: an ingress-nginx issue from February 2, 2026, in which the nginx.ingress.kubernetes.io/auth-method annotation allowed nginx configuration injection, leading to code execution in the controller context and disclosure of Secrets accessible to the controller. Fixed in ingress-nginx v1.13.7 and v1.14.3.

CVE-2026-42945 is the core-NGINX issue. The reason it matters for container security is that ingress controllers ship and run core NGINX inside their images. A core-NGINX overflow is therefore not only a "web server team" problem; it is a "who runs ingress in our clusters" problem.

Technical analysis

The public details describe a buffer overflow in the rewrite module triggered by particular directive configurations. The trigger involves unnamed PCRE captures (the $1, $2-style positional capture groups produced by a regular expression in a rewrite or location match) combined with question marks in the rewrite/return target. The following is an illustrative sketch of the shape of a configuration that exercises the affected code path. It is intentionally non-functional and is shown only to explain what to look for in your own configs — this is not functional exploit code.

# ILLUSTRATIVE ONLY — not a working exploit, shown to identify the at-risk pattern.
# The risk is in rewrite/return constructs combining unnamed PCRE captures ($1...)
# with question marks in the target. Audit configs that look structurally like this.

location ~ ^/legacy/(.*)$ {
    # unnamed positional capture ($1) feeding a rewrite target containing '?'
    rewrite ^/legacy/(.*)$ /app?path=$1 last;
}

Why the container/Kubernetes angle amplifies this:

  1. Generated configuration. In a standalone deployment, an operator hand-writes nginx.conf and knows whether it uses the at-risk construct. In Kubernetes with ingress-nginx, the controller generates the NGINX config from Ingress resources, annotations, and templates. Rewrite-target annotations and path rewrites are exactly the feature set that produces rewrite directives with positional captures. Operators may have no visibility into the final generated nginx.conf.
  2. Embedded, not installed. The NGINX in an ingress controller is baked into the controller's container image, not installed via your OS package manager. Your host patch process does not touch it. You patch it by updating the controller image to a version whose base NGINX is fixed — which is a different workflow and a different team than apt upgrade nginx.
  3. Exposure and privilege. Ingress controllers terminate north-south traffic and, in default ingress-nginx installs, the controller is granted cluster-wide read access to Secrets. Code execution in the NGINX/controller context is therefore high-value: it sits at the cluster's front door and near sensitive material. This is the same blast-radius property that made CVE-2026-1580 dangerous, and it applies to any RCE that lands in the controller process.

To be precise about uncertainty: the exact memory-corruption primitive, the reliability of RCE versus crash/DoS, and which specific generated configurations are definitively exploitable are not fully public at the level of a weaponized template, and we are not going to speculate. The defensible planning assumption is: actively exploited, RCE-credible, reachable from generated config, and present anywhere NGINX is embedded.

What detection looks like

Detection has two halves: finding where you are exposed (inventory) and spotting exploitation attempts (telemetry).

Inventory — find every NGINX, including embedded ones:

# Illustrative discovery commands — adapt to your environment.

# 1) Standalone/host NGINX versions
nginx -v 2>&1 || /usr/sbin/nginx -v 2>&1

# 2) NGINX inside running containers (per node / per pod)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'
# then, for ingress controller pods:
kubectl exec -n <ns> <ingress-pod> -- /nginx-ingress-controller --version
kubectl exec -n <ns> <ingress-pod> -- nginx -v 2>&1

# 3) Audit the GENERATED config for at-risk rewrite/return constructs
kubectl exec -n <ns> <ingress-pod> -- cat /etc/nginx/nginx.conf | grep -nE 'rewrite|return' 

A software bill of materials for your container images is the scalable version of this: rather than execing into every pod, query your SBOMs for the NGINX component and version across every image in your registry. That turns "do we run an affected NGINX anywhere" from a manual sweep into a single query.

Telemetry — spot exploitation:

  • NGINX worker process crashes, segfaults, or unexpected restarts (worker process ... exited on signal 11) in ingress controller or web server logs. A buffer overflow that fails to achieve clean RCE typically crashes the worker first.
  • Anomalous child processes spawned by the NGINX/ingress controller process (a shell, an outbound network tool) — strong signal of successful code execution in that context.
  • Unexpected reads of Kubernetes Secrets by the ingress controller's service account in the audit log, especially Secrets the controller has never accessed before.
  • Spikes in requests against paths that map to rewrite-heavy Ingress rules, particularly with crafted query strings containing question marks and unusual encodings.
# Illustrative audit-log query intent (pseudo-query)
source=k8s_audit
| where user.username == "system:serviceaccount:ingress-nginx:ingress-nginx"
| where verb in ("get","list") and objectRef.resource == "secrets"
| where objectRef.namespace NOT in (expected_namespaces_for_ingress)

What to do Monday morning

Ordered by urgency:

  1. Inventory every NGINX, embedded included. Use SBOMs across your registry plus runtime discovery in clusters. You are looking for NGINX 0.6.27 through 1.30.0 anywhere — in standalone servers, NGINX Plus, and inside ingress controller and other images.
  2. Upgrade core NGINX to a fixed release (1.31.0 or 1.30.1). For standalone servers, update the package and reload. For ingress controllers and other images, pull a controller/image build whose base NGINX is 1.30.1+/1.31.0+ and roll it out. Do not assume your ingress controller is unaffected just because its controller version looks current — check the embedded NGINX version.
  3. Triage by reachability first. You almost certainly cannot patch every NGINX instance simultaneously. Prioritize internet-facing ingress and any server whose generated or hand-written config actually contains rewrite/return constructs with positional captures and question marks. An affected version that never evaluates the vulnerable construct is lower urgency than one that does.
  4. Audit and constrain rewrite rules as an interim mitigation. Where you cannot upgrade immediately, review Ingress objects and templates for rewrite-target usage. Remove or simplify the at-risk constructs, and consider a validating admission controller that rejects Ingress resources whose annotations would generate the vulnerable pattern.
  5. Tighten ingress controller privilege. Reduce the controller's Secret access from cluster-wide to namespaced where your topology allows, so that code execution in the controller does not hand over every Secret in the cluster. This is good hygiene regardless of this specific CVE.
  6. Watch for exploitation now. Turn on the crash and child-process alerts above immediately, because PoC is public and activity is reported in the wild. Worker crashes are an early, cheap signal.
  7. Verify after patching. Re-run your inventory query post-rollout and confirm no affected NGINX version remains, including in any images that were recently rebuilt or pulled.

Why this keeps happening

NGINX is everywhere, and "everywhere" includes a long tail of places engineers do not think of as "running NGINX." It is embedded in ingress controllers, API gateways, sidecars, appliance images, and vendor containers. When a flaw lands in core NGINX, the patch problem is not "update one package," it is "find every copy across an organization's entire image estate and figure out which copies are reachable." That inventory problem is the structural reason these CVEs have long, messy tails: the affected component is a dependency of dependencies.

The container ecosystem compounds it. A vulnerable NGINX baked into a base image propagates to every image built on top of it, and those images sit in registries and run in clusters long after the upstream fix ships. Without a continuously maintained SBOM and a way to ask "which of my running workloads contain affected NGINX, and which of those actually exercise the vulnerable path," teams default to either patching nothing (no visibility) or patching everything in a panic (no prioritization).

The structural fix

The two things that shorten dwell time here are knowing where the component is and knowing which instances are actually reachable. Safeguard's SBOM generation across container images lets you answer "do we run an affected NGINX anywhere, including embedded in ingress controllers" with a query instead of a fleet-wide exec sweep, and reachability analysis helps cut the resulting list down to the instances whose configuration actually evaluates the vulnerable rewrite code path — so you patch the genuinely exposed front-door first instead of drowning in every image that merely contains the binary. For the clusters themselves, an admission controller can reject Ingress resources that would generate the at-risk construct as an interim guardrail while rollouts proceed, and auto-fix can open the version-bump PRs against affected images. None of this prevents the overflow, but it compresses the time between disclosure and a verified-clean estate, which is the metric that matters when a PoC is already public.

What we know we don't know

  • Severity framing. The upstream vendor rates this medium; third-party analysis emphasizes RCE potential. The reliability of RCE versus crash/DoS in real configurations is not fully public.
  • Exact exploitable configurations. The public material describes the class of at-risk construct (unnamed PCRE captures plus question marks) but not an authoritative, complete list of definitively exploitable generated configs.
  • Scope of in-the-wild activity. Exploitation has been reported, but a precise picture of targets, volume, and outcomes was not public at the time of writing.

References

Internal reading:

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.