PHP Patches Two AI-Found RCE Flaws Back to 5.4 as NSA Says Patch or Go Offline
TL;DR
On October 21 the PHP project released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical bugs that let an unauthenticated request run code on a PHP web server. Together they are called PHP2Shell (CVE-2026-109618 and CVE-2026-109619), and both are rated 9.2. Researchers at Wiz and in OpenAI's Patch the Planet program found them with GPT-5.6 Sol and Gemini 4 Argon. Every release back to PHP 5.4 is hit by at least one of the two. The embargo leaked a day early, NSA told organizations that can't update to take their systems offline, and a long list of European government sites did exactly that. If you run PHP anywhere, upgrade today. The config workarounds below are partial.
What broke
Both bugs live in PHP itself, beneath any framework or CMS. Wiz says even a "Hello World" app on an affected version can be exposed. The PHP advisory names every SAPI that serves web requests: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The PHP team rates mod_php as the highest risk because the demonstrated exploit fires there before any application code runs.
CVE-2026-109618: RCE via OOM corruption
When PHP runs out of memory it uses longjmp() to abandon the request. Some request memory is reachable before it is fully initialized, so a failed allocation at that moment leaves invalid state behind. The shutdown routine then reads that state as if it were valid. The advisory lists several multipart tricks that hit the memory limit while staying under post_max_size: bodies with no usable declared length, parts with an unlimited number of headers, and empty file controls that skip the max_file_uploads count while nested field names multiply the array work.
Picture a fire drill that clears the kitchen halfway through an order, after which the cleanup crew trusts the half-written ticket and cooks whatever it says. In this case the attacker wrote the ticket.
CVE-2026-109619: RCE via stale global state
A PHP worker keeps global error, session, object and extension state that can point into memory owned by one request. If a fatal error or OOM interrupts an operation before its reset, or a late warning repopulates the error state after shutdown cleared it, the request heap gets freed while the worker still holds the pointer. The next request on that worker can touch the stale value before normal initialization overwrites it. That is a use-after-free across two HTTP requests. Session upload progress and deprecated or invalid INI values applied per request are among the confirmed paths.
Wiz demonstrated pre-auth RCE against the stock wordpress:latest, drupal:latest and joomla:latest container images. It also showed memory disclosure that works regardless of the application, which can leak passwords, tokens, API keys and certificates without any code execution. Wiz says it reported four bugs and expects more variants to exist.
Who found it, and with what
The GitHub advisories credit four reporters: lcfr-hax, sagitzadik-wiz, tomash-areion and amyb-oai. The PHP2Shell site lists Wiz Research (Sagi Tzadik, Shir Tamari, Nir Ohfeld, Tomer Schwartz), Amy Burnett of OpenAI Codex Security, and Ryan A. of Calif. Cloudflare also names Quarkslab among the disclosing parties.
Wiz says it worked with its own Wiz Atlas platform plus Gemini 4 Argon and GPT-5.6 Sol throughout, and credits Gemini 4 Argon with help on discovery, exploit development, attack detection and patch validation. Its boldest claim is that one researcher did in a week what used to take a world-class team months. OpenAI president Greg Brockman wrote that OpenAI had spent two months "leading a coalition to mitigate one of the most severe bugs in open source software found in recent memory," found through Patch the Planet. Decrypt reports that Calif found a version with GPT-5.6 Sol in August and that OpenAI's own team found a fuller version in September.
Wiz says the vulnerable code sat in PHP for more than a decade, and Decrypt reports that a limited version surfaced in 2024 without anyone treating it as significant. Then two separate teams found the full thing with frontier models in the same summer. If that doesn't change your threat model, nothing on this site will.
The embargo didn't hold
The write-up from inside the PHP security team says an anonymous Hacker News post on October 20 described the bugs before it was removed. Screenshots had already spread on X and Mastodon, and a leaked screenshot of the PHP2Shell tool was credited to Calif. watchTowr then confirmed the bugs publicly and posted both CVE numbers, saying the embargo was meant to last until Thursday at 11am ET. PHP moved the release up a day.
Cloudflare had WAF rules live for Free and paid plans from 03:02 UTC on October 21, about nine hours before disclosure. It says it has seen attack traffic against its customers, including payloads mutated to slip past the rules. It published no counts.
NSA: patch, or unplug
At 13:45 UTC on October 21, NSA Cyber posted: "Effective Immediately, all organizations using PHP for their systems are advised to be prepared for an update addressing two critical vulnerabilities... If an immediate update is not feasible, it is recommend that organizations take the system offline until it can be fully mitigated." Plenty of organizations did. A Reuters factbox lists Germany's federal IT provider ITZBund, French prefecture sites, Belgium's foreign ministry, the Port of Rotterdam and Overheid.nl in the Netherlands, Finnish government web services, a Czech government site and several Wikimedia systems. Most framed it as precautionary.
Some platforms were patched before the news broke. Automattic says WordPress.com, WordPress VIP, WP Cloud, Pressable and Tumblr are already covered. The AWS bulletin says its own services are unaffected, but customers running PHP on Elastic Beanstalk, Amazon Linux and Lightsail need to update, and Lightsail instances have to be rebuilt from new blueprints.
What you should do today
- Upgrade. Both advisories and AWS say a patched release is the only complete fix. Distros and LTS vendors got the patches early, so check your package manager first. For 7.4, 8.0 and 8.1, PHP has published source backport branches, but it doesn't ship releases for those versions. PHP 8.2 itself reaches end of life on December 31, 2026.
- Restart every worker. Long-lived FPM, mod_php and FrankenPHP workers keep running old code until they restart, and 109619 depends on what a worker carries from one request to the next.
- Stopgap for 109618. Enforce
memory_limit=-1administratively (for examplephp_admin_valuein the FPM pool or Apache config) so applications can't put a finite limit back. Keeppost_max_sizelow (8M with no uploads, 32M with them). If the app takes no multipart data, block it at the frontend. Use a container or cgroup limit for availability, and do not useRLIMIT_ASorRLIMIT_DATA, which force the verymmap()failure you are trying to avoid. - Stopgap for 109619. Set
session.upload_progress.enabled=0inphp.ini, the FPM pool or server config (notini_set()or.user.ini), then restart. On 8.5, also setfatal_error_backtraces=0. Remove deprecated or invalid per-request settings, including.htaccessphp_valuelines on mod_php. Turning offdisplay_errorsor using@does not help. - Edge rules. Cloudflare has deployed managed WAF rules for PHP2Shell on Free and paid plans (check they are in block mode). On AWS WAF, enable
SizeRestrictions_BODY(8 KB body cap) and add the custom "PHP2Shell" rule AWS describes. - Watch logs. Wiz suggests looking for multipart requests followed by memory-limit errors, runs of HTTP 500s, oversized or malformed
PHPSESSIDcookies and unexplained worker churn. Its caveat applies: seeing none of these proves nothing.
OpenAI also released php2shell-checker (Apache-2.0), a Node CLI with Codex skills that reads the PHP version from X-Powered-By, Server or php -v. It is a version comparison and nothing more. A distro backport can fix the bug without changing the version string, and an UNKNOWN result, which the README says explicitly, does not mean you are patched.
Why this one matters beyond PHP
PHP runs on almost 70% of websites, according to the W3Techs figure Cloudflare cites. Wiz warns that AI "significantly lowers the barrier to scaling attacks across different deployments" and makes bugs that once looked impractical worth exploiting. Here frontier models found a ten-year-old memory bug, helped build working exploits against WordPress, Drupal and Joomla, and validated the fix. Defenders still needed two months and a coalition of PHP maintainers, cloud providers and US agencies to ship the patch. The leak gave attackers about a day's head start on the patch.
If your patch cycle is measured in weeks, assume the models working for the other side can read a diff faster than you can schedule a maintenance window.
Key Takeaways
- PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, two unauthenticated RCE bugs rated 9.2 that affect releases back to 5.4.
- Full RCE is validated against Apache mod_php before any app code runs. Wiz showed pre-auth RCE on stock WordPress, Drupal and Joomla images, plus app-agnostic memory disclosure.
- Wiz (with Gemini 4 Argon and GPT-5.6 Sol) and OpenAI's Patch the Planet effort found the bugs. Wiz says the vulnerable code sat in PHP for more than a decade.
- The embargo leaked on October 20. NSA told organizations that can't patch to go offline, and government and infrastructure sites across Europe did.
- Upgrade and restart every worker.
memory_limit=-1,session.upload_progress.enabled=0and WAF rules only reduce exposure until you do.
Sources: PHP security advisory (Oct 21, 2026), GHSA-w8hw-w9fx-j79w (CVE-2026-109618), GHSA-6wmf-4rv5-p3rp (CVE-2026-109619), Wiz Research, PHP2Shell, AWS bulletin 2026-143, Cloudflare, NSA Cyber, Greg Brockman, daubois.dev (PHP security team), Reuters factbox, Automattic, Decrypt, php2shell-checker