May 2026 dropped three critical Linux vulnerabilities on a near-weekly cadence, and the security discourse has mostly treated them as three separate bad days. They’re not. Together they form a reliable, race-free, forensically quiet kill chain from the public internet to root, and if you’re running nginx in front of anything that matters, you need to stop and read this.
CVE-2026-42945, dubbed NGINX Rift, landed May 13 courtesy of depthfirst. It’s a heap buffer overflow in ngx_http_rewrite_module that’s been sitting in every nginx build since 2008. An unauthenticated attacker sends a single crafted HTTP request and overwrites the heap, getting remote code execution in the worker process – no auth, no prior session, no prerequisites beyond a network path to port 80 or 443. The root cause is a mismatch between two passes over the rewrite directives: the length calculation runs with is_args=0 (raw byte count) while the copy pass runs with is_args=1 (URI-escaped), so the write overruns the allocation. The trigger is a configuration pattern that’s everywhere: a rewrite directive with an unnamed PCRE capture ($1, $2) and a question mark in the replacement string, followed by another rewrite, if, or set in the same block. CVSS 9.2, and it earns it.
CVE-2026-31431, “Copy Fail,” came from Theori on April 29. It’s a logic bug in the authencesn cryptographic template that lets an unprivileged local user write 4 controlled bytes into the page cache of any readable file, then pivot to root. The exploit is 732 bytes of Python (no races, no disk writes, no forensic residue – the page cache corruption means file integrity checks pass because the underlying file on disk was never touched). It works on every distro shipped since 2017. CISA added it to the Known Exploited Vulnerabilities catalog with a May 15 remediation deadline.
Then there’s CVE-2026-43284 and CVE-2026-43500, “Dirty Frag,” disclosed May 7 by Hyunwoo Kim. It’s a two-bug chain that lands in the same place as Copy Fail – page-cache-to-root LPE – but routes around the Copy Fail mitigation entirely. If you blacklisted algif_aead thinking you were covered, Dirty Frag gets there through xfrm-ESP or rxrpc instead. Microsoft’s already seeing in-the-wild activity: SSH foothold, stage an ELF binary, escalate via su. Deterministic. No races. Same bug class, different sink.
Why does the combination matter more than any single bug? Exploit chains are usually academic exercises, published to demonstrate feasibility and then left to rot in a CTF writeup. This isn’t that. CVE-2026-42945 hands you a foothold from the internet. CVE-2026-31431 or CVE-2026-43284 hands you root once you’re on the box. Neither step requires races, user interaction, or authentication. Neither leaves obvious forensic traces on disk. Both have working, published proof-of-concept code as of this writing.
The surface area here is genuinely uncomfortable. NGINX is the most-deployed web server on the planet. WordPress – with scads of massively-deployed plugins recommended NGINX configuration contains the exact vulnerable rewrite pattern (I checked; it’s right there in the docs) – powers something north of 40% of the web. That means whitehouse.gov, NASA, the UK Government, the Australian Government, the State of California, and essentially every major US university is potentially in scope. Every federal agency required by the 21st Century IDEA Act to maintain a public web presence. Every municipality running WordPress on a LEMP stack. Every SaaS app behind an NGINX ingress controller. An attacker doesn’t need a zero-day chain for any of these; they need access to data from a public internet scanner, a grep for vulnerable version strings, and the ability to send one HTTP request.
I shipped a static configuration scanner for the NGINX Rift pattern. Single bash script, no dependencies beyond bash 4+ and grep, runs offline against config files without touching a live nginx process:
git clone https://git.sr.ht/~hrbrmstr/cve-2026-42945-scanner
cd cve-2026-42945-scanner
./scan-nginx-rift.sh /etc/nginx
Run it on every box running nginx. Add --json in CI. Point it at ingress controller configmaps. The output tells you the file, the line number, the vulnerable directive, and which following directive creates the exploitability condition:
[VULN] sites-enabled/wordpress.conf:8 – rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$
followed by "if" at line 12
If you find a hit, you’ve got two options in order of preference:
- Upgrade nginx to 1.30.1 (stable) or 1.31.0 (mainline).
- Replace unnamed captures with named captures in every affected
rewrite:
# Before (vulnerable)
rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
# After (safe)
rewrite ^/(?<term>[^/]+?)-sitemap(?<num>[0-9]+)?.xml$ /index.php?sitemap=$term&sitemap_n=$num last;
For the kernel side, check your distro’s patch status now and don’t trust “we’ll get to it.” If you can’t patch immediately, blacklisting algif_aead blocks Copy Fail but does nothing for Dirty Frag. For Dirty Frag, unload xfrm_algo.ko and rxrpc.ko if your workload doesn’t need them, and make sure AppArmor or SELinux policy is blocking unprivileged user namespaces.
Three critical Linux CVEs in three weeks, all with published exploits, all in code that’s been shipping for years. The gap between disclosure and working exploit is now measured in hours, not months. The scanner above closes one piece of that gap for the nginx side. The rest depends on whether you check your configs today or wait until something in your logs looks wrong – at which point the forensic-residue-free LPE means “looking wrong” may be all you ever see.