AI pried a 20-year bug out of core PHP. Now it runs code on your server. Patch today.

AI pried a 20-year bug out of core PHP. Now it runs code on your server. Patch today.

On October 21 the PHP project shipped four releases at once, 8.5.12, 8.4.27, 8.3.36 and 8.2.35, to fix two critical vulnerabilities rated CVSS 9.2 each: CVE-2026-109618 and CVE-2026-109619. Together they are being called php2shell. Either one lets an unauthenticated attacker run code on a server that is doing nothing more than serving PHP. No application bug is involved. A plain "Hello World" page on a vulnerable build is enough.

Both flaws sit in the parts of PHP that almost every request touches: memory management and error handling. CVE-2026-109618 corrupts memory in how PHP cleans up after it runs out of memory partway through a request. CVE-2026-109619 is a use-after-free, where internal state from one request lives on into the next request handled by the same worker. Wiz Research found them with help from AI agents, reported them privately in August, and the fix landed on October 21 in a release coordinated with distributions and vendors. Wiz says every PHP version back to 5.4 is affected, which is roughly the last decade of the language. PHP runs a large share of the web, so the number of exposed servers is huge.

Who is actually exposed

The PHP team rates Apache with mod_php as the highest risk. There a single unauthenticated request can trigger the exploit before any of your code runs, so none of your own defenses, auth middleware, input validation, in-app checks, ever get a turn. Full remote code execution was demonstrated on mod_php with default settings against fresh WordPress, Drupal and Joomla containers.

PHP-FPM is not safe either. RCE through the stale-state bug was validated on FPM, though that path needs a suitable operation in the running application to reach it. php-cgi, FrankenPHP and LiteSpeed are all in scope. If it serves PHP over HTTP, treat it as vulnerable until you have patched and restarted it.

One point for mobile teams, because the exposure is easy to miss: in our native iOS and Android projects the app itself is clean, but it talks to an API, and that API is very often PHP. An unpatched backend puts your users at risk even though nothing on the device is wrong. Check the server behind the app, not just the app.

What we would do first

From our PHP and Docker work, the mistake we see under pressure is patching the wrong thing. Two steps matter more than the rest.

  1. Find every PHP you run, not just the obvious one. It hides in cPanel and Plesk stacks, vendor appliances, old client sites nobody has touched in two years, CI images and base containers. CISA's guidance is to inventory first, because PHP is often buried inside other software and you cannot patch what you have not found.
  2. Patch, then restart, then verify the version the running process reports. A new package on disk does nothing until you replace the running workers. We have watched teams "patch" and stay exploitable for days because PHP-FPM was never actually restarted.

Containers make this trap worse. Running an upgrade inside a live container is not a fix, because your next deploy from the old image brings the vulnerable build straight back. Rebuild on a patched base image, push it, and roll the workers. Then hit the server and confirm the version you expect is the one answering.

If you genuinely cannot patch today

The PHP team is blunt: only updating is a complete fix, and the interim settings just narrow specific attack paths. The ones worth applying are memory_limit=-1 enforced where the app cannot override it, using php_admin_value in your FPM pool or Apache config, then session.upload_progress.enabled=0, and a conservative post_max_size. If you run Cloudflare, the managed WAF rule for these CVEs is already live, and buying time with an edge rule while workers get patched is exactly the kind of thing we set up when configuring Cloudflare for clients during an incident. One catch: that rule keys on the default upload-progress field name, so if you renamed session.upload_progress.name, it will not cover you.

The part that should worry you more than this one bug

Here is what gets me about php2shell. These bugs sat in the codebase for about twenty years. Nobody weaponized them because turning a memory-corruption chain into a reliable exploit across every PHP version, extension set and heap layout was slow, specialist work, the kind that takes months. Wiz used frontier AI models to do that adaptation, and it took a couple of weeks instead.

During our pentesting engagements for gaming studios, the hard part was rarely spotting a suspicious code path. It was proving a real, repeatable exploit before anyone would pay to fix it. That economics has shifted. Attackers get the same speed-up, which means the gap between a patch going public and mass scanning keeps shrinking. Cloudflare reported probing attempts around the time of release, and a proof of concept is already circulating.

So the honest takeaway is uncomfortable: your patch cadence is now your security posture. If you cannot find and update a critical runtime across your whole estate inside a day, that is the real gap, and php2shell will not be the last thing to test it.

If keeping PHP patched, restarted and verified across staging, production and a pile of older client sites sounds familiar, let's talk.

expert-analysisphpsecuritytech-newsvulnerability