CVE-2026-42945
Overview
NGINX is the most widely deployed reverse proxy and load balancer on the public internet. The ngx_http_rewrite_module implements the rewrite, if, and set directives that operators use to manipulate request URIs, dispatch traffic between upstreams, and rewrite headers. The module’s script engine has been a stable part of NGINX since version 0.6.27 shipped in 2008.
A critical heap-based buffer overflow (CVE-2026-42945), branded “NGINX Rift” by its discoverer depthfirst, has been identified in ngx_http_script_regex_end_code in src/http/ngx_http_script.c. A two-pass contract violation between the script engine’s length and copy passes lets a crafted HTTP request write past a heap allocation in the NGINX worker process. A single unauthenticated request is enough to crash the worker; on systems with Address Space Layout Randomization (ASLR) disabled, the same primitive yields remote code execution.
Per OWASP: a buffer overflow occurs when a process writes data beyond the bounds of an allocated memory region, corrupting adjacent state in a way that can be steered into arbitrary code execution.
This issue affects every NGINX OSS release from 0.6.27 through 1.30.0, NGINX Plus R32 through R36, and every downstream that compiles the same ngx_http_script.c, including the upstream Ingress NGINX Controller v1.15.1. The upstream NGINX project shipped patches in 1.30.1 (stable) and 1.31.0 (mainline) on May 13, 2026. The Kubernetes ingress-nginx project retired in March 2026 and will not ship a v1.15.2 to absorb the fix. HeroDevs has resolved CVE-2026-42945 in NES for Ingress NGINX 1.15.4 by backporting the upstream patch onto the controller’s pinned NGINX 1.27.1 baseline. Active in-the-wild exploitation has been confirmed by VulnCheck.
Why this matters for Ingress NGINX deployments
CVE-2026-42945 is operationally different from every CVE HeroDevs has resolved in NES for Ingress NGINX so far. The earlier post-retirement findings (CVE-2026-32282, CVE-2026-35204, CVE-2026-35205, CVE-2026-40890, and CVE-2024-44337) lived in dependencies — the Go toolchain, Helm, gomarkdown — and were closed by bumping a module version and rebuilding. CVE-2026-42945 lives in the NGINX C source itself, compiled directly into the controller binary; remediation requires patching the C code, not bumping a dependency.
The exposure is also at the worst possible surface. An ingress controller terminates external TLS, sits in front of every Service in the cluster, and has direct network reachability from the public internet. A compromised worker exposes TLS private keys for the lifetime of the process, every proxied request and response body, and lateral access to the kube-apiserver (subject to RBAC) and adjacent pods on the same node. The vulnerable code path is on the hot path for nearly every Ingress NGINX deployment because rewrite-target, canary routing, and X-Forwarded-* handling all generate the trigger pattern.
For teams running upstream Ingress NGINX v1.15.1, scanners begin reporting CVE-2026-42945 as an open Critical the moment NVD propagates the advisory, and no upstream release will close it. NES for Ingress NGINX 1.15.4 rebases the controller’s compiled NGINX with the patched script engine, closing the finding without a configuration change or a Gateway API migration.
Details
Module Info
- Product: NGINX (ngx_http_rewrite_module); compiled-in component of Ingress NGINX Controller
- Affected components: ngx_http_script_regex_end_code, ngx_http_script_start_args_code, ngx_http_script_copy_capture_code, ngx_http_script_copy_capture_len_code in src/http/ngx_http_script.c
- Affected versions: NGINX OSS 0.6.27 through 1.30.0; NGINX Plus R32 through R36; Ingress NGINX Controller builds that link those versions (including upstream v1.15.1)
- Upstream source repository: https://github.com/nginx/nginx
- Published artifacts (NES):
- Container image: registry.nes.herodevs.com/nes/ingress-nginx:v1.15.1-nes-1.15.4
- Helm chart: HeroDevs/ingress-nginx --version 0.0.6 (see helm-charts documentation)
- Release notes: docs.herodevs.com/ingress-nginx/release-notes
- Distribution channels: registry.nes.herodevs.com, HeroDevs Helm chart repository
- Fixed in:
- nginx 1.30.1 (stable) and 1.31.0 (mainline), commit 2046b45a, May 13, 2026 (upstream)
- NGINX Plus R32 P6, R35 P2, R36 P4 (upstream commercial)
- NES for Ingress NGINX 1.15.4 (May 18, 2026), which backports the upstream patch onto the controller’s pinned NGINX 1.27.1 baseline
Vulnerability Info
This Critical-severity vulnerability lives in the two-pass script engine that drives NGINX’s rewrite, if, and set directives.
The engine runs each rewrite in two passes: a length pass that computes how many bytes the rendered output will occupy and allocates that much memory from the request pool, and a copy pass that writes the rendered bytes. Both passes must compute the same length; the allocation is sized from the first and consumed by the second.
CVE-2026-42945 breaks that contract. When a rewrite replacement contains a question mark (the URI/query separator), ngx_http_script_start_args_code sets e->is_args = 1 on the main script engine and never clears it. A subsequent rewrite, if, or set directive that references an unnamed PCRE capture ($1 through $9) triggers ngx_http_script_complex_value_code, which allocates a fresh sub-engine to run the length pass. On that sub-engine, is_args is zero, so ngx_http_script_copy_capture_len_code measures the capture as raw bytes. The destination buffer is allocated for that raw length. The copy pass then runs on the main engine, where is_args is still 1, and ngx_http_script_copy_capture_code invokes ngx_escape_uri with the NGX_ESCAPE_ARGS flag. Every +, %, or & byte in the attacker-controlled capture expands from one byte to three, and the resulting write runs past the heap allocation. Named PCRE captures ((?<name>...)) bypass the vulnerable escaping path; the bug is specific to unnamed captures.
The corruption lands inside the NGINX request pool, adjacent to ngx_pool_cleanup_t structures. The bytes written past the allocation are derived directly from the attacker’s URI, which is what converts the primitive from a denial of service into remote code execution: depthfirst’s published proof of concept rewrites a cleanup handler function pointer, and when the request pool is destroyed at the end of the request, NGINX walks the cleanup list and the rewritten pointer calls system() with attacker-controlled arguments. With ASLR enabled, the same primitive produces a deterministic worker crash; depthfirst documents a cross-request heap-shaping technique that progressively defeats ASLR.
Threat model for Ingress NGINX clusters: exploitation requires a vulnerable build plus an Ingress configuration that combines a rewrite whose replacement contains a question mark, an unnamed PCRE capture, and a later rewrite, if, or set that references the same capture. The pattern is generated by routine Ingress features — nginx.ingress.kubernetes.io/rewrite-target, canary routing, X-Forwarded-* handling — so most production Ingress NGINX deployments are reachable. nginx -t does not flag the trigger pattern; the configuration is syntactically valid.
When successfully exploited, this vulnerability can lead to:
- Remote code execution in the NGINX worker process on builds with ASLR disabled (still common in hardened-container and minimal-image scenarios)
- TLS private key disclosure for the lifetime of the worker process
- Proxied request and response tampering, including session cookie and bearer token capture in flight
- Persistent denial of service through repeated triggering that crashes workers faster than NGINX restarts them
- Cluster-internal lateral movement to the kube-apiserver (subject to RBAC) and adjacent pods on the same node
Steps To Reproduce
- Stand up a controller running upstream Ingress NGINX v1.15.1 (or any NGINX OSS build between 0.6.27 and 1.30.0).
- Apply an Ingress that exercises the trigger pattern, for example a rewrite-target annotation that rewrites to a path containing a question mark and a second rule that references the same capture in a set directive.
- Send a crafted HTTP request whose path matches the rewrite rule’s unnamed capture with bytes that ngx_escape_uri will expand (+, %, &).
- Observe the worker process crash and restart in the controller logs; with ASLR disabled and the depthfirst exploit chain, observe code execution under the worker’s user.
Proof Of Concept
A public proof of concept is available at https://github.com/DepthFirstDisclosures/Nginx-Rift; the discoverer’s writeup is at https://depthfirst.com/nginx-rift. Active in-the-wild exploitation has been confirmed by VulnCheck.
Mitigation
OSS Users
Users of upstream NGINX and Ingress NGINX should apply one of the following mitigations:
- For NGINX OSS, upgrade to 1.30.1 (stable) or 1.31.0 (mainline) and restart workers.
- For NGINX Plus, apply R32 P6, R35 P2, or R36 P4 per F5 advisory K000161019.
- As a configuration stopgap on builds that cannot be patched immediately, audit Ingress and NGINX configurations for rewrite rules whose replacement contains a question mark combined with unnamed PCRE captures referenced by a later rewrite, if, or set; switch unnamed captures to named captures ((?<name>...)), which bypass the vulnerable escaping path.
- For Ingress NGINX specifically, no upstream release will rebase against the patched NGINX because the project retired in March 2026. Sign up for post-EOL security support; HeroDevs customers get immediate access to a patched Ingress NGINX build.
NES Customers
HeroDevs Never Ending Support for Ingress NGINX has resolved CVE-2026-42945 in NES for Ingress NGINX 1.15.4 by backporting the upstream patch (commit 2046b45a) onto the controller’s pinned NGINX 1.27.1 baseline. The release ships as a drop-in replacement for upstream ingress-nginx v1.15.1:
- Pull the patched container image: registry.nes.herodevs.com/nes/ingress-nginx:v1.15.1-nes-1.15.4
- Or upgrade via the public Helm chart: HeroDevs/ingress-nginx --version 0.0.6 (helm-charts documentation)
- The same NGINX base image rebuild picks up Alpine 3.23.4 with newer curl/libcurl (8.19.0-r0), additionally clearing five medium-severity curl CVEs (CVE-2025-14524, CVE-2025-14819, CVE-2026-1965, CVE-2026-3784, CVE-2026-3805).
- VEX statements ship with the release so scanners that consume OpenVEX or CycloneDX VEX surface the patched status instead of leaving CVE-2026-42945 as an open finding.
Compliance impact
CVE-2026-42945 is a Critical, unauthenticated, network-reachable RCE at the cluster edge with confirmed in-the-wild exploitation. Several frameworks make the gap acute:
- The EU Cyber Resilience Act’s Article 14 reporting obligations begin September 11, 2026; “the upstream project no longer ships fixes” is not a valid answer when a Critical is being actively exploited.
- DORA’s ICT third-party risk requirements have been in force since January 2025.
- PCI DSS 4.0 expects continuous evidence that components receive security patches.
- FedRAMP authorizations carry continuous monitoring obligations.
- CISA KEV catalog inclusion is likely given the confirmed in-the-wild exploitation; KEV entries trigger federal patching deadlines under BOD 22-01.
The NES release ships a documented patch trail plus VEX statements that scanners consume programmatically.
Taking Action
CVE-2026-42945 sat undiscovered in NGINX’s most widely deployed module for 18 years and is now being exploited in the wild. For most NGINX deployments the upstream patches close it. For Kubernetes teams on Ingress NGINX 1.15.1, the upstream patches do not exist, and the question is how long the deployment can carry an actively exploited Critical at the cluster edge. NES for Ingress NGINX 1.15.4 is the patched build for clusters that cannot complete a Gateway API migration before regulatory and exploitation pressure converge. Pull the 1.15.4 image and Helm chart per docs.herodevs.com/ingress-nginx/release-notes.