PHP2Shell is the most serious PHP runtime vulnerability in years, and it was found with AI models doing a lot of the digging. The PHP project shipped fixes for two remote code execution bugs, CVE-2026-109618 and CVE-2026-109619, on October 21, 2026, and by that evening Cloudflare was counting exploit attempts in the millions.
If you run PHP behind a web server, stop reading after the next section and go patch. If you have already patched, the rest of this post covers what the bugs are, which mitigations actually help, how the disclosure went sideways, and what it means that GPT-5.6 Sol and Gemini 4 Argon were part of the discovery.
PHP2Shell Fixed Versions: What to Update to Right Now
Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Those four releases went out at 14:00 UTC on October 21, according to the PHP security advisory on php.net. Anything older on a supported branch is vulnerable.
| PHP branch | Status | What to do |
|---|---|---|
| 8.5.x | Fixed in 8.5.12 | Update now |
| 8.4.x | Fixed in 8.4.27 | Update now |
| 8.3.x | Fixed in 8.3.36 | Update now |
| 8.2.x | Fixed in 8.2.35 | Update now, plan to leave 8.2 before Dec 31, 2026 |
| 7.4 to 8.1 | No official release | Source backports from the PHP security team, or your LTS vendor |
| 5.4 to 7.3 | End of life, no fix | Upgrade or take offline |
(Source: php.net security advisory and Tenable php2shell FAQ, Oct 2026)
Two practical notes from the advisory caught my eye. Linux distributions and LTS vendors got the patches in advance, so apt or dnf may already have them. And if you install from the volunteer-run rpms.remirepo.net repository, PHP explicitly told users that repo would not have updates on release day and urged a switch to distribution packages or a source build.
After updating, restart every PHP worker. A patched binary on disk does nothing for an FPM pool that is still running the old one.
What Is PHP2Shell? The Two CVEs Explained
PHP2Shell is two memory-safety bugs in how the PHP runtime cleans up after a request that dies at the wrong moment. Both are rated 9.2 on CVSS v4.0. The CVE IDs leaked a day early with a wrong score of 10.0, which is why you may have seen that number on social media.
CVE-2026-109618, “RCE via OOM corruption.” If a request hits PHP’s memory_limit while internal request data is only partly initialized, the cleanup code later treats that half-built data as valid. On Apache with mod_php, the PHP Foundation says an unauthenticated request can trigger this before any application code runs, and full RCE was shown with default settings.
CVE-2026-109619, “RCE via stale global state.” A fatal error at the wrong point leaves internal state pointing at memory from a previous request. The next request handled by the same worker can use that stale pointer, which is a classic use-after-free. PHP’s advisory lists memory disclosure as a confirmed impact, and the reporter showed RCE against a real application.
What makes this nasty is that neither bug lives in your code. You can have a perfectly audited Laravel app and still be exposed, because the flaw sits in the interpreter underneath it. Cloudflare’s write-up says the same thing in plainer terms: updating your website code or plugins alone does not fix it.
According to Tenable’s FAQ, the affected runtimes are PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. Calif traced the earliest affected code path to PHP 5.4.0 and confirmed pre-authentication RCE against specific versions of WordPress, Drupal, Joomla and Magento.
The short version: if PHP answers HTTP requests on your server, you are in scope.
How Many Sites Does PHP2Shell Affect?
W3Techs data cited by Tenable puts PHP on 69.3% of websites whose server-side language is known. That is where the “70% of the internet” headlines come from.
The exposure estimates vary a lot depending on who is counting and what they count:
- Palo Alto Networks: 22.6 million potentially vulnerable instances, per Fortune
- Shodan search by Henk Poley: more than 1.9 million internet-exposed hosts running PHP, per Tenable
- Silas Cutler’s rough estimate: more than 1.3 million internet-exposed hosts potentially vulnerable, per Tenable
I would not put much weight on any single figure. They use different methods, and a host fingerprinted as “PHP” is not the same as a host that is still unpatched.
The exploitation timeline is easier to pin down. Amazon Threat Intelligence saw an attempt against its MadPot honeypot on October 17, four days before disclosure, and says php2shell is now broadly exploited. Cloudflare told Fortune it saw tens of thousands of exploit attempts within 45 minutes of the announcement, hundreds of thousands within two hours, and millions by the evening of October 21.
Real services went dark too. AP reported limited UK government services offline and Finnish government content still being restored, and The Hacker News lists BambooHR and Dutch government sites including MijnOverheid and DigiD among those taken down as a precaution. The FBI’s cyber division recommended taking sites offline if they could not be updated right away.
PHP2Shell Mitigations That Help (and the Ones That Don’t)
If you genuinely cannot patch today, PHP’s advisory lists stopgaps. The wording matters: these “reduce exposure to specific attack paths but do not make an installation safe.”
For the OOM bug, set memory_limit=-1 somewhere applications cannot override it, cap request sizes, and enforce limits at the proxy. For the stale state bug, turn off session upload progress and, on 8.5, fatal error backtraces. Here is the configuration from the advisory, as a pool or server config that applies before request parsing:
; php.ini or server config (must apply before request parsing)
memory_limit = -1 ; set via php_admin_value so apps can't override
post_max_size = 8M ; 32M if you need file uploads
upload_max_filesize = 8M ; keep below post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0 ; PHP 8.5 only
For an FPM pool, use the admin variants so ini_set() and .user.ini cannot put them back:
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_flag[session.upload_progress.enabled] = off
A few details from the advisory that are easy to miss:
ini_set()and FPM.user.inido not count. The setting has to apply before PHP parses the request.- Hiding errors does nothing. Setting
error_reporting,display_errorsor using@does not help, because the problem is the internal state, not the output. - Do not swap in
RLIMIT_ASorRLIMIT_DATA. PHP warns those can cause the exact allocation failure that triggers the bug. A container or cgroup memory limit that kills only the affected worker is the safer option. memory_limit=-1is not a full fix. An underlying allocation failure can still reach the vulnerable path.
Then there is the WAF route. Cloudflare says it auto-deployed rules for both CVEs to every plan, Free included, at 03:02 UTC on October 21, about nine hours before disclosure. Its own post calls this a stopgap that only covers traffic routed through Cloudflare, and The Hacker News reports attackers were already mutating payloads to slip past the rules.
Treat every mitigation as buying hours, not weeks. The fix is the version bump.
How AI Found PHP2Shell: GPT-5.6 Sol, Gemini 4 Argon and Patch the Planet
PHP2Shell is one of the first internet-scale vulnerabilities where the finders openly credit frontier AI models with the find. OpenAI called it “one of the most impactful security issues in recent memory” and said “AI can uncover security flaws with internet-scale impact.”
The PHP Foundation’s post-mortem gives the cleanest timeline of who found what:
- 2024: a PHP core developer contracted by the Foundation saw the first signs of the OOM bug during an external audit. Greg Brockman told Fortune a limited version “wasn’t considered significant at the time.”
- July 30, 2026: Calif begins an audit of PHP under OpenAI’s Patch the Planet program.
- August 11: Calif reports an unconditional RCE.
- August 24: Wiz reports the same issue independently.
- September 18: OpenAI reports the same root cause plus further attack vectors.
- October 21: fixes ship.
On the models, Fortune reports that Calif used OpenAI’s GPT-5.6 Sol, and that Wiz combined GPT-5.6 Sol, Google’s Gemini 4 Argon and its own Wiz Atlas tooling. The Hacker News credits OpenAI’s Codex Security team with working on the fix alongside PHP and Google’s Gemini team.
Note that Fortune and the PHP Foundation give slightly different discovery dates for Calif and Wiz. I have used the Foundation’s, since it is the maintainer’s own record.
The part I find most interesting is buried lower in the Foundation’s post. Since July 1, PHP has published 15 CVEs, and more than 100 additional reports were invalid, duplicates or not reproducible. Alpha-Omega had already scanned PHP earlier in 2026 with Anthropic’s Claude Mythos. The Foundation now has an “AI Security Engineer in Residence” and uses OpenAI’s Daybreak Red to validate reports.
That is what open source maintenance looks like now. Several well-funded labs pointed their strongest models at the same codebase, three groups found the same bug weeks apart, and a small volunteer security team had to sort real findings from noise. It is the same pattern I wrote about with Anthropic’s free OSS Scanner for open-source projects, which sends model-generated reports to maintainers without human review first.
AI found this bug before attackers did, as far as anyone knows. The next one may not go that way, and attackers have the same models.
The Disclosure Went Sideways
The coordinated release did not hold together, and the PHP Foundation is unusually candid about it.
The CVE IDs began circulating around 15:00 UTC on October 20 with a wrong release time and the wrong 10.0 score. PHP then moved the release up from October 22 to October 21. Around 20:00 UTC that evening, Calif mistakenly posted a video of its proof of concept working against several targets. At 07:41 UTC on October 21, Chainguard published patched container images more than six hours before the embargo lifted.
The Foundation called the slow fix “a structural failure, caused by both the security team’s decision process and its lack of resources,” and noted that “a person makes every call and works on every patch.” It is moving security decisions to majority votes and asking companies, hosts and governments that depend on PHP to fund it.
I think this is the real lesson for anyone building on open source. The runtime under a large share of the web is maintained by a handful of people, and AI-assisted bug hunting just multiplied the volume of serious reports they have to handle.
What Developers Should Do This Week
Here is the checklist I would run, in order:
- Inventory every PHP install. That includes the WordPress marketing site, the old admin panel and the Docker image nobody has rebuilt since spring. Even teams on a JavaScript-first stack like the one in the vibe coding tech stack guide often have a PHP CMS somewhere.
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and restart every worker.
- Rebuild container images. A base image with the old PHP is still vulnerable after the host is patched.
- Hunt from October 17. Amazon recommends starting investigations from that date, since exploitation predates disclosure.
- Do not run random exploit code. Tenable warns that public PoCs claiming to exploit these CVEs are unverified, and PoC repositories are a common malware delivery channel. The AI coding agent supply chain attacks guide covers why letting an agent clone and run one is a bad idea.
- Plan off PHP 8.2. It reaches end of life on December 31, 2026.
If you use coding agents to do the patching, that works, but read the diff. An agent that bumps a version in a Dockerfile and forgets the base image tag is a common way to end up “patched” on paper.
PHP2Shell is fixed upstream. Whether your servers are fixed depends entirely on whether someone restarts them on the new binary this week.
For a very different kind of AI news from the same week, I also wrote up Recursive Flint, the 40B open coding model built to run on a laptop.