On May 13, 2026, the depthfirst research team published a full breakdown of a vulnerability they had reported to F5 almost three weeks earlier. The verdict was severe: a single crafted HTTP request, sent without any authentication, against an NGINX instance that uses rewrite and set directives, was enough to crash worker processes deterministically and, in environments with weakened ASLR, achieve remote code execution as the NGINX worker user. The vulnerability was assigned CVE-2026-42945, nicknamed NGINX Rift, with a CVSS score of 9.2. The bug has been sitting in the codebase since 2008.
This article is a two-layered breakdown. The first part is written for non-technical readers who need to decide quickly whether they have anything to do and what exactly. The second part dissects the exploitation chain the way depthfirst reconstructed it, plus a discussion of what this class of bug means for any infrastructure that depends on web servers, reverse proxies, or ingress controllers. At the end, we look at how the Pragma Core platform addresses exactly the kind of problems that made this breach possible.
Part I. Executive breakdown
What happened
Researchers at depthfirst uncovered a heap buffer overflow in NGINX's ngx_http_rewrite_module, the component that processes URL rewriting rules and one of the most widely used modules in production NGINX deployments. The flaw is triggered when a rewrite directive contains a question mark in its replacement string and is followed in the same scope by another directive that references an unnamed regex capture group such as $1 or $2.
NGINX's internal script engine runs rewrites in two passes. The first pass walks the configuration and calculates how many bytes the final string will occupy, then allocates a buffer of exactly that size from the per-request memory pool. The second pass walks the same configuration again and writes the actual bytes into the buffer. For the design to be safe, both passes have to observe identical engine state. They don't. A flag called is_args is set during the first pass on the main engine, then the second pass runs on a freshly zeroed sub-engine where the flag is back to zero. The length calculation pretends there is no argument context. The copy phase remembers there is one, and calls a URI escaping routine that expands every special character from 1 byte to 3 bytes.
The result: the copy writes well past the end of the allocated heap buffer, in a way that is fully controlled by the attacker through a properly crafted URI. From there, the depthfirst team turned the overflow into a working RCE primitive on a system with ASLR disabled, with no credentials, no session, and no prior access required.
Who is affected
| Component | Status |
|---|---|
| NGINX Open Source 0.6.27 to 1.30.0 | Vulnerable. Upgrade to 1.30.1 or 1.31.0. |
| NGINX Plus R32 to R36 | Vulnerable. Upgrade to R32 P6 or R36 P4. |
| NGINX Instance Manager 2.16.0 to 2.21.1 | Vulnerable. |
| F5 WAF for NGINX 5.9.0 to 5.12.1 | Vulnerable. |
| NGINX App Protect WAF 4.9.0 to 4.16.0 and 5.1.0 to 5.8.0 | Vulnerable. |
| F5 DoS for NGINX 4.8.0 | Vulnerable. |
| NGINX App Protect DoS 4.3.0 to 4.7.0 | Vulnerable. |
| NGINX Gateway Fabric 1.3.0 to 1.6.2 and 2.0.0 to 2.5.1 | Vulnerable. |
| NGINX Ingress Controller 3.5.0 to 3.7.2, 4.0.0 to 4.0.1, and 5.0.0 to 5.4.1 | Vulnerable. |
The number that should worry anyone running NGINX at the edge: roughly a third of all websites globally are served by NGINX. A working public proof of concept already lives on GitHub, and the bug requires nothing more than a single HTTP request to a vulnerable endpoint. If you run an API gateway, a reverse proxy, or a Kubernetes ingress controller built on top of NGINX, you very likely have at least one path in your configuration that uses unnamed PCRE captures and a question mark in a rewrite rule. That path is the trigger.
Why this matters beyond your NGINX boxes
The bug itself is elegant and surprisingly easy to follow once you see the diagram of the two passes. What matters more is the pattern. Many high performance servers and runtimes optimize string handling by separating a length calculation phase from a copy phase. The pattern saves allocations and improves cache behavior. It also creates a brittle invariant: the two phases must observe the exact same engine state, including every implicit flag set by every code path between them. When that invariant is violated, you get exactly this kind of bug.
NGINX is not the only system that uses two-pass scripting. The same shape of bug has appeared in template engines, regex backends, and protocol parsers across the industry over the past decade. The lesson is broader than NGINX. Whenever an internal engine state is modified by one code path and consumed by another, the boundary between them is a security boundary, even if nobody documented it as such.
Recommended actions
- Upgrade immediately. For NGINX Open Source, move to 1.30.1 or 1.31.0. For NGINX Plus, move to R32 P6 or R36 P4. Restart NGINX after the upgrade so worker processes reload the patched binary. There is no partial fix.
- Apply the interim mitigation if patching is delayed. Replace every unnamed PCRE capture (
$1,$2, and so on) in your rewrite,if, andsetdirectives with named captures. This breaks the exact configuration shape that triggers the bug. Use it only as a stopgap. - Inventory every NGINX instance you have. That includes the obvious ones, but also NGINX embedded inside vendor appliances, container base images, Kubernetes ingress controllers, and managed API gateways. The bug affects every product line built on top of the same codebase. Many teams discover they have ten times more NGINX deployments than their CMDB suggests.
- Look at HTTP logs. Specifically, look for unusually long URIs that contain large numbers of percent-encoded characters and plus signs hitting rewrite-heavy endpoints. There are no vendor-published indicators of compromise at the moment, but those request shapes are the natural footprint of the overflow trigger.
- Re-evaluate ASLR posture on edge servers. Worker crashes are guaranteed even with ASLR. Code execution requires ASLR bypass or absence. Make sure every NGINX-fronted box has ASLR enabled at full strength and that any container image you run respects the host's ASLR settings.
Part II. Technical breakdown
The role of rewrite and set in real configurations
Two directives are at the heart of this bug. Both are extremely common in modern NGINX configurations, to the point that they show up in almost every API gateway and reverse proxy setup we have ever audited.
The rewrite directive changes the request URI based on a regular expression. When a request matches the specified pattern, NGINX replaces the URI with a new string. For example, rewrite ^/api/(.*)$ /v2/api/$1 takes the matched part in the parentheses (a capture group) and appends it to the new path through the $1 variable. If the replacement string contains a question mark, NGINX treats the rest of the string as a query string and appends the original request arguments to it. That question mark is the flag that flips the engine into "we are now in argument context" mode.
The set directive is used to assign a value to a custom variable. This is incredibly useful in practice for temporarily storing parts of the original request, dynamically routing endpoints, or maintaining state throughout the request lifecycle before subsequent rewrites alter the URI. It can also reference capture groups from the most recently executed regular expression. For instance, a configuration might use set $original_path $1 to save the value of the first capture group into a variable named original_path. Backend applications and access logs then have access to the original requested endpoint even after the URI has been rewritten.
Both directives are processed by the same internal component: the NGINX script engine.
The architecture of the NGINX script engine
When NGINX parses the configuration file, the script engine compiles rewrite, set, if, and a handful of related directives into a sequence of small opcodes. Each opcode is a pointer to a C function. At runtime, the engine executes them in order against a per-request engine state structure named ngx_http_script_engine_t.
For each rewrite that produces a string, the engine runs the opcodes twice:
- Length pass: every opcode is paired with a corresponding
_len_codefunction that returns the number of bytes its operation will produce. The engine accumulates these numbers and allocates a single buffer of exactly that size from the per-request memory pool. - Copy pass: the engine then walks the opcodes a second time and runs the actual
_codefunctions, which write their output into the pre-allocated buffer.
This design is elegant. It allocates the right amount of memory once, then writes the data once, with no intermediate copies or reallocations. The cost: both passes must produce the same number of bytes for the same opcode. If they disagree, the copy phase either leaves trailing zeros in the buffer (mostly harmless) or writes past the end (very much not harmless).
The invariant that ties the two passes together is that they observe identical engine state. The bug is a violation of that invariant.
The vulnerability: an unpropagated is_args flag
The vulnerability resides in src/http/ngx_http_script.c. The flaw is triggered when a rewrite directive contains a question mark in its replacement string. The opcode emitted by the question mark calls ngx_http_script_start_args_code, which permanently sets the e->is_args = 1 flag on the script engine:
void
ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script args");
e->is_args = 1;
e->args = e->pos;
e->ip += sizeof(uintptr_t);
}
This flag is never reset between script code evaluations. It sticks for the lifetime of the request on the main engine e.
When a subsequent set directive references a regex capture group, it triggers ngx_http_script_complex_value_code. This is where the two pass design breaks. During the length calculation pass, this function uses a fresh, completely zeroed sub engine called le:
void
ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
{
size_t len;
ngx_http_script_engine_t le;
ngx_http_script_len_code_pt lcode;
ngx_http_script_complex_value_code_t *code;
code = (ngx_http_script_complex_value_code_t *) e->ip;
e->ip += sizeof(ngx_http_script_complex_value_code_t);
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script complex value");
ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); // fully zeroed sub engine
le.ip = code->lengths->elts;
Because it is initialized with zeros, le.is_args is zero. The length calculation function, ngx_http_script_copy_capture_len_code, then checks this condition to decide if escaping is required:
size_t
ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
{
...
if ((e->is_args || e->quote)
&& (e->request->quoted_uri || e->request->plus_in_uri))
{
p = r->captures_data;
return cap[n + 1] - cap[n]
+ 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
NGX_ESCAPE_ARGS);
} else {
return cap[n + 1] - cap[n];
}
...
Because le.is_args is zero, the condition evaluates to false. The function falls through to the else branch and returns the raw, unescaped capture length.
During the copy pass, however, the copy function ngx_http_script_copy_capture_code runs against the main engine e, where e->is_args is still set to 1 from the earlier opcode. The exact same condition now evaluates to true, and the code enters a completely different branch:
void
ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
{
...
if ((e->is_args || e->quote)
&& (e->request->quoted_uri || e->request->plus_in_uri))
{
...
// OVERFLOW HAPPENS HERE
// The destination buffer `pos` was allocated with `raw_size`,
// but `ngx_escape_uri` expands the characters and writes
// the much larger `raw_size + 2 * N` bytes directly into it.
e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
cap[n + 1] - cap[n],
NGX_ESCAPE_ARGS);
} else {
e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
}
ngx_escape_uri with NGX_ESCAPE_ARGS expands every escapable character (plus signs, ampersands, percent signs, equals signs, and several others) from one byte into three bytes (%XX). The destination buffer was sized for the raw, unescaped length. The copy writes raw_size + 2 * N bytes, where N is the number of escapable characters in the capture group. The extra 2 * N bytes are written straight past the end of the buffer, into whatever happens to live next in the per-request memory pool.
The minimum vulnerable configuration looks like this:
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
The question mark in /internal?migrated=true sets is_args on the main engine. The set $original_endpoint $1 runs ngx_http_script_complex_value_code, which evaluates the capture group with a length pass on a zeroed sub-engine and a copy pass on the main engine. The size of the overflow is controlled by the attacker through the number of escapable characters injected into the URI.
Exploitation: turning the overflow into RCE
The overflow is highly controllable, but the path from "I can write bytes past the buffer" to "I am running arbitrary code as the NGINX worker user" has real constraints.
The first useful property comes from NGINX's process model. NGINX uses a multi process architecture where worker processes are forked from a single master process. Because of this design, the memory space is duplicated exactly for every child worker. The heap layout remains entirely deterministic across different workers. If an exploit fails and crashes a worker, the master process simply spawns a new one with the exact same memory layout. An attacker can safely try many times until they succeed, without worrying about the worker crashing and changing the memory layout in the next attempt. Theoretically, this design could even be leveraged to leak ASLR by progressively overwriting pointers byte by byte. The depthfirst write-up discusses exploitation under the assumption that ASLR has already been bypassed (or is off).
The second constraint is the alphabet. The bytes used to overwrite adjacent memory are passed through the URI parser and the escaping function. The attacker cannot simply inject arbitrary bytes. The payload is strictly limited to URI safe characters. So, without null bytes, how do you craft a pointer?
Overwriting ngx_pool
To turn the overflow into code execution, depthfirst targeted the NGINX memory pool structure. NGINX uses per-connection and per-request memory pools to manage allocations. The memory pool is defined by ngx_pool_t, which contains essential metadata for managing the allocator state:
struct ngx_pool_s {
ngx_pool_data_t d;
size_t max;
ngx_pool_t *current;
ngx_chain_t *chain;
ngx_pool_large_t *large;
ngx_pool_cleanup_t *cleanup;
ngx_log_t *log;
};
The target field is cleanup at offset 64. It points to a linked list of ngx_pool_cleanup_t structures, each of which holds a function pointer and an argument to be executed when the pool is destroyed:
typedef void (*ngx_pool_cleanup_pt)(void *data);
struct ngx_pool_cleanup_s {
ngx_pool_cleanup_pt handler;
void *data;
ngx_pool_cleanup_t *next;
};
If you can make cleanup point to a structure you control, where handler is system and data is a string of your choice, the moment NGINX destroys the pool, your command runs.
The challenge is that the overflow is contiguous. To reach cleanup, the attacker must first overwrite every preceding field in the pool structure: d, max, current, chain, large. Filling these with URI safe padding bytes completely corrupts the internal state of the pool allocator. If the victim connection then tries to allocate more memory, read from the network, or process further data, NGINX dereferences one of the corrupted pointers and crashes prematurely. Game over, no RCE.
The trick is timing. The victim pool has to be destroyed immediately after the overflow, before any of the corrupted allocator fields are touched. depthfirst engineered this with a cross-request heap feng shui sequence:
- Open an initial connection and send partial headers. NGINX allocates a request pool for this connection.
- Open a second victim connection. NGINX allocates a victim pool exactly adjacent to the first pool.
- Complete the initial headers, triggering the rewrite overflow directly out of the first pool and into the adjacent victim pool header.
- Immediately close the victim connection from the client side. NGINX calls
ngx_destroy_poolto destroy the victim pool.
When the pool is destroyed, NGINX iterates the cleanup linked list but does not touch any of the corrupted fields in the pool structure. After this, the attacker holds the primitive of dereferencing an arbitrary ngx_pool_cleanup_s.
Spraying fake ngx_pool_cleanup_s
The remaining problem: the attacker can only write URI safe characters into the victim pool header, so the cleanup pointer the attacker can place there must itself be made of URI safe bytes. The structure it points to, however, can contain anything, as long as it lives somewhere accessible in the worker's memory.
depthfirst solved this by spraying the heap with POST request bodies. Unlike HTTP headers or request URIs, which are strictly parsed, POST bodies are treated as raw data streams and can contain arbitrary binary payloads, including null bytes. The spray payload contained a fake cleanup structure pointing to libc's system function, followed by a user-supplied command string.
for (c = pool->cleanup; c; c = c->next) {
if (c->handler) {
c->handler(c->data);
}
}
Because the heap layout is highly predictable across workers, the fake structures sprayed via POST land at fixed offsets. The exploit brute forces the address where these fake structures land and explicitly filters them to find an address that consists entirely of URI safe bytes. That guarantees the address used to overwrite the cleanup pointer survives the escaping function intact. Worth noting: the attacker does not need to overflow with null bytes; overwriting only the lower bytes of the cleanup pointer is enough to redirect it to the sprayed fake structure.
Finally, the attacker closes the victim socket from the client side. NGINX worker calls ngx_destroy_pool, iterates pool->cleanup, hits the fake handler, and runs system(command). RCE achieved, as the NGINX worker user, on a single TCP session.
Affected versions and patches
The vulnerable codebase spans nearly every NGINX product line. The depthfirst advisory and the F5 security bulletin list:
- NGINX Open Source 0.6.27 through 1.30.0
- NGINX Plus R32 through R36
- NGINX Instance Manager 2.16.0 through 2.21.1
- F5 WAF for NGINX 5.9.0 through 5.12.1
- NGINX App Protect WAF 4.9.0 through 4.16.0 and 5.1.0 through 5.8.0
- F5 DoS for NGINX 4.8.0
- NGINX App Protect DoS 4.3.0 through 4.7.0
- NGINX Gateway Fabric 1.3.0 through 1.6.2 and 2.0.0 through 2.5.1
- NGINX Ingress Controller 3.5.0 through 3.7.2, 4.0.0 through 4.0.1, and 5.0.0 through 5.4.1
Fixed versions:
- NGINX Open Source: 1.30.1 and 1.31.0
- NGINX Plus: R32 P6 and R36 P4
Major distributions started shipping backported packages within 24 hours of the public disclosure. AlmaLinux, for example, published patched packages across every supported nginx module stream on May 14, including end-of-life streams that would normally not receive an upstream fix. Debian, Ubuntu, and Red Hat followed shortly after. If you depend on a distribution package, run your package manager and confirm the installed version is at or above the fixed release for your channel.
Timeline
| Date | Event |
|---|---|
| 2026-04-18 | depthfirst's autonomous system analyzes NGINX source. 5 memory corruption issues reported internally. |
| 2026-04-21 | All 5 issues reported to NGINX via GitHub security advisory. |
| 2026-04-24 | NGINX confirms 4 of the 5 issues. |
| 2026-04-28 | depthfirst informs NGINX of a working PoC demonstrating RCE. |
| 2026-05-05 | RCE PoC and demo video shared with NGINX. |
| 2026-05-13 | F5 publishes the security advisory. NGINX 1.30.1 and 1.31.0 released. depthfirst publishes the full write-up. |
| 2026-05-14 | Distribution packages start landing in production repositories. Public GitHub PoC referenced widely. |
A note on the discovery methodology
depthfirst states that the entire discovery process was driven by their internal autonomous system specialized in low-level software analysis. Onboarding NGINX required a single click. The system scanned the codebase for roughly six hours and produced 5 candidate findings, 4 of which were confirmed by NGINX as real vulnerabilities. CVE-2026-42945 alone is an 18-year-old bug in one of the most heavily reviewed C codebases on the public internet, found by a system the team describes as "autonomous".
This is the second major CVE in the past month where the discovery was AI-augmented and explicitly credited as such (CVE-2026-3854 in GitHub's git push pipeline being the other). The message to the application security community is now consistent across multiple data points: large legacy codebases, especially those that combine multiple files, multiple opcode tables, and stateful engines, are squarely in scope for AI-driven analysis. The 18-year window between introduction and discovery is no longer the comfort it used to be.
What we should learn from CVE-2026-42945
A few patterns show up repeatedly in this kind of bug, and they're worth investigating proactively in any codebase:
- Two-pass scripting with shared state across passes is a security boundary in disguise. If one pass writes a flag that the other pass reads, that flag is part of the security model. Make it explicit. Either propagate it to the sub-engine deliberately, or refuse to share state at all. The current
is_argshandling in NGINX is neither. - Unsafe string expansion at copy time without re-checking allocation size. Any code path where a copy routine can expand its input (URI escaping, HTML entity encoding, JSON escaping, base64 padding, hex encoding) must verify, at the point of writing, that the destination buffer is large enough. Trusting a length calculation done elsewhere, by a different engine instance, is exactly how this bug got past 18 years of review.
- Deterministic process models multiply the value of a single primitive. Fork-and-respawn architectures are operationally convenient, but they hand the attacker an infinite retry loop with a stable heap layout. Every byte of useful primitive, when combined with this property, is worth more than it would be in a single-shot process. Designs like worker re-randomization on crash exist for exactly this reason and are underused.
- URI-safe alphabets are not a real boundary. The exploit demonstrates that a payload restricted to URI-safe characters can still write into cleanup function pointers, by combining lower-byte overwrites of pointers with heap sprays in adjacent, less restricted parsers (POST bodies, in this case). If you ever justify a security control with "but the attacker can only inject these characters", check that no other parser in the same address space accepts everything.
- Long-lived configuration patterns become attack surface. API gateway patterns built around
rewriteand unnamed captures with question marks are not unusual; they are the textbook example most teams learned from. The bug is in the engine, but the trigger is the most common configuration shape in the wild. When you write a runbook for a primitive that ends up everywhere, you're implicitly defining a future attack surface.
How Pragma Core addresses this class of problem
Pragma Core is an application security platform built specifically for the class of issues that made CVE-2026-42945 possible. We're talking about vulnerabilities that classical scanners don't surface, because they're not about a single badly written function. They're about how state flows through an engine across multiple passes, multiple files, and multiple invocation contexts, each of which makes reasonable assumptions about the others.
Here are the concrete connections between what the platform does and the bug class this CVE represents:
Autonomous AI agents for attack chain investigation
The autonomous agents in Pragma Core don't stop at "we found a potential overflow". Their reasoning over attack chains tries to answer questions like: "If this engine state is written by one function and read by another, do both callers see consistent values across all code paths? Where is the engine reset, and where is it cloned without resetting?". That's exactly the kind of reasoning that surfaces an is_args style propagation bug, where the issue is not in any single line of code but in the relationship between three.
Interactive call graphs with vulnerability overlay
depthfirst's analysis required manually reasoning across ngx_http_script_start_args_code, ngx_http_script_complex_value_code, ngx_http_script_copy_capture_len_code, and ngx_http_script_copy_capture_code. Pragma Core generates call graphs automatically for any connected repository, visualizing how classes, functions, and calls connect across the codebase. Overlaying identified vulnerabilities on top of these graphs lets teams see at a glance where engine state is mutated and where it is consumed, and which paths between the two skip the propagation entirely.
Continuous tracking of third-party packages
Many organizations run NGINX, NGINX modules, and downstream products built on NGINX as transitive dependencies inside container images and vendor appliances. They don't know they have them. Pragma Core tracks every third-party package across all connected repositories, surfacing vulnerable versions with CVSS scores and fixed upgrade paths. For a CVE like this one, the practical effect is that an organization with a sprawl of internal services running ingress controllers and reverse proxies gets a single, prioritized list of every vulnerable instance the moment the CVE lands in the catalog, with no manual monitoring required.
Full SBOM per repository
Pragma Core generates a complete inventory of libraries, versions, licenses, and package URLs for every repository, exportable as CycloneDX JSON. In the context of NGINX Rift, that inventory is essential to quickly answer "where is NGINX, what version, and inside which other product?". Teams that already have that inventory patched within hours of disclosure. Teams that didn't are still finding instances days later.
Human-guided AppSec investigations
The expert-led research module in Pragma Core is built precisely for the type of investigation depthfirst did here: take a real, complex, low-level engine and reason about whether shared state is correctly propagated between code paths. An AppSec operator drives that analysis, supported by autonomous agents, automated scans, and the platform context already available in the workspace. The focus is on what your team feels is fragile: sensitive features, complex code paths, business-critical components. Not a separate black-box engagement, but a natural extension of your existing subscription, leveraging your existing repository coverage and findings.
Native repository integration
The platform connects to GitHub, GitLab, and Azure DevOps in minutes. For an organization running NGINX, NGINX modules, or any of the F5 products built on top of the same codebase, integration is direct: continuous scanning starts immediately, and the findings generated are contextualized with repository, branch, and commit.
Closing thoughts
CVE-2026-42945 is not, fundamentally, a bug about rewrite, and it's not a bug about NGINX. It's a bug about what happens when one engine pass mutates a flag, another pass clones the engine without propagating it, and a third pass reads a different value than the one that drove the allocation. The same patterns are present in many script engines, many template runtimes, and many protocol parsers across the modern stack. The difference between an organization that reads this article as a curiosity and one that uses it as a trigger for an audit usually comes down to how mature the application security function is and how much visibility teams have into their own code.
For organizations that want to move from "we scan and report" to "we systematically investigate what's fragile", Pragma Core was built to make that step. You can reach us directly at pragma-core.com for a demo or to talk about how the platform could fit into your security pipeline.
Sources
- depthfirst Research, NGINX Rift: Achieving NGINX Remote Code Execution via an 18-Year-Old Vulnerability, May 13, 2026.
- F5 Security Advisory, K000160932: NGINX ngx_http_rewrite_module vulnerability CVE-2026-42945, May 13, 2026.
- Picus Security, NGINX Rift: CVE-2026-42945 Critical Heap Buffer Overflow Vulnerability Explained, May 14, 2026.
- AlmaLinux Project, NGINX Rift (CVE-2026-42945) Patches Released, May 13, 2026.
- Orca Security, NGINX Rewrite Module Flaw (CVE-2026-42945), May 14, 2026.
- SOC Prime, CVE-2026-42945: Critical NGINX Rewrite Flaw, May 14, 2026.
- SecurityOnline, Critical 18-Year-Old NGINX RCE (CVE-2026-42945) and GitHub PoC Disclosed, May 14, 2026.
- NVD, CVE-2026-42945 Detail.