php2shell: two PHP RCEs and who patches first
PHP's emergency patch fixes two unauthenticated RCE flaws, php2shell (CVE-2026-109618/109619). Who's affected, which version to move to, how to hold the line.
At 14:00 UTC on October 21, PHP released four versions at once — 8.5.12, 8.4.27, 8.3.36 and 8.2.35 — fixing two vulnerabilities collectively called php2shell: CVE-2026-109618 and CVE-2026-109619. Both are unauthenticated remote code execution (RCE), rated CVSS v4.0 9.2. The official advisory ends with a single conclusion: “There are no complete mitigations, updating is the only safe choice.”
There are three reasons this deserves a deep write-up. First, the affected scope is “all PHP installations serving web requests,” and PHP runs well over half the sites on the web. Second, four days before disclosure, someone was already trying to exploit it in the wild, so this isn’t theoretical. Third, most coverage stops at “patch now,” but the real difficulty is “what to do when you can’t patch immediately” and “does my setup actually count as high-risk.”
I pulled together the two official GitHub security advisories, php.net’s release notes, the PHP Foundation’s post-mortem, Calif’s technical write-up, plus analysis from Tenable, Rapid7, CISA and Amazon into one briefing for developers and ops. This article gives no attack steps or proof of concept — only the risk, the fix and the defense. At the end I also checked one of my own Laragon dev machines. I opened and verified these pages on October 22.
First, the conclusion: what to do now
Figure 1: The security advisory on the php.net front page (source: php.net)
If you only have five minutes, do this in order:
- Inventory. Find every machine running PHP, including software that bundles PHP without you noticing. CISA specifically warns that PHP is often a component of other software.
- Internet-facing first. Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, prioritizing anything reachable from the internet.
- Still on 8.1 or older? Take it offline. CISA’s advice is that if you can’t upgrade immediately, or still run an unsupported version, take the system offline until it’s fixed.
- Don’t clock off after upgrading. Watch for web worker processes doing something odd like launching shells or downloading tools — the exact signs the advisory names for monitoring.
That’s it. The rest of this piece explains the “why,” and handles the cases you can’t fix in five minutes.
What is php2shell, exactly?
The name comes from the researchers. Calif, the security firm that found the flaws, named the whole exploit chain php2shell — literally “from PHP to a shell.” It’s actually two separate vulnerabilities that share a very low-level root cause, which is why they were disclosed and patched together.
In its technical write-up, Calif traces the root back to 2004, when PHP’s handling of its memory limit planted the seed; related issues were reported in 2020 and 2024, but weren’t shown to be exploitable at the time. This round, Calif used AI-assisted auditing to push it to reliable remote code execution. They’re clear in the write-up that no special models unavailable to the general public were used, and that AI doesn’t “unearth all bugs with simple prompts” — it was an aid in the research process.
Here’s the root cause of each in one sentence, without the exploitable detail:
- CVE-2026-109618 (OOM corruption): when PHP uses
longjmp()to handle an out-of-memory error, it can abort while request data is only partly initialized, and the cleanup that follows may treat that invalid data as valid. - CVE-2026-109619 (stale global state): some PHP global state (error, session, object and extension state) should be reset when a request ends, but a fatal error can leave the reset unfinished, so a later request can hit leftover state pointing to freed memory.
Both share the same CVSS vector: AV:N/AC:H/AT:P/PR:N/UI:N. In plain terms: reachable over the network, needs no privileges and no user interaction, but attack complexity is high and there are preconditions. That “high complexity” matters, and it’s both bad news and good news, as we’ll see.
One aside: a CVSS of 10.0 circulated during the leak. It’s wrong. The PHP Foundation has clarified the correct score is 9.2.
Which deployment should be most worried?
Figure 2: The GitHub security advisory for CVE-2026-109618 (source: GitHub Advisory)
The official affected list is: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed. But these aren’t the same level of risk.
Figure 3: The official risk assessment per deployment (data: php.net advisory, GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp)
Apache mod_php is the one PHP explicitly calls highest risk. The reason is spelled out in the advisory: mod_php unconditionally runs the request cleanup procedure even when request startup fails, which lets the attack succeed before your application code has even started. In other words, how securely you wrote your app doesn’t matter, because it never gets a turn. PHP says the first bug was validated against mod_php with “default PHP input and memory limits,” including multi-worker prefork deployments.
PHP-FPM is more nuanced. For the first bug, FPM terminates the worker when startup fails, blocking that particular path; but source analysis suggests it may still be susceptible after a successful startup, though no complete FPM exploit was demonstrated. For the second bug, FPM does have a validated path. So FPM isn’t immune, the bar is just higher.
FrankenPHP and LiteSpeed get their own assessments, but the conclusion is the same: upgrade. One thing to stress: CLI isn’t on this list. This vulnerability is about serving web requests.
There’s a reality here that many people overlook. Take Laragon, which I use: on Windows, developing with this kind of integrated stack often means mod_php by default — the setup PHP rates highest risk (I didn’t check XAMPP’s or WAMP’s defaults one by one). A dev machine usually isn’t exposed, which lowers the risk a lot, but if you’ve ever temporarily opened it to the public internet for a demo, that’s a different story.
Which version should you move to?
Figure 4: The fix for each version (data: php.net, Tenable)
All four supported branches have a matching fix version — just go up. The ones to watch are the unsupported branches:
- 8.2 got a fix this time, but it reaches end of life on December 31, 2026, with no security updates after that. If you’re on 8.2, this upgrade is just buying time, and you should plan to move up.
- 7.4 to 8.1 have no official binary. PHP only provides source-level patch branches (named like
PHP-7.4-CVE-2026-109618-109619), so you’d compile it yourself or wait for your Linux distribution / LTS vendor’s package. Many distributions actually received the patch in advance, so check your vendor. - 5.4 to 7.3 get no fix at all; upgrade is the only option. Calif says the earliest affected path dates to PHP 5.4.0, meaning this seed was planted more than a decade ago.
Windows users can grab a compiled build straight from the php.net download page. When I checked, the 8.5.12 Windows build (VS17, x64, both TS and NTS) was stamped as built at 13:48 UTC on October 21, the same day as the release.
Is anyone exploiting it yet?
Figure 5: The opening of Calif’s php2shell write-up (source: calif.io)
This is the part of the event that most warrants caution.
Amazon’s threat intelligence team says its MadPot honeypot system logged a php2shell exploitation attempt on October 17, a full four days before the October 21 disclosure. The source was an IP tied to a commercial anonymization network. Amazon says “it remains unclear how the actor acquired exploit information prior to disclosure.” That means details were moving in some circle before the official announcement.
Disclosure day itself was busier. The full timeline:
Figure 6: The timeline from report to patch (data: Calif, PHP Foundation, AWS Security Blog)
PHP had originally scheduled the release for October 22. But on the afternoon of October 20, the two CVE IDs leaked on forums and social media, so PHP moved the release up a day to the 21st. The PHP Foundation later admitted that Calif mistakenly published a video showing a working attack, which accelerated the appearance of various proofs of concept; mitigation advice given to critical-infrastructure providers may have leaked as well. Separately, Chainguard unilaterally broke the embargo more than six hours before the coordinated release, publishing images containing the fix.
So how heavily is it actually being hit? Keep each source’s claim separate:
- Amazon says php2shell “is now being broadly exploited in the wild” and advises investigating from October 17 onward. But the same post says it’s unclear whether those attempts would succeed on real systems.
- CISA (October 21) says that as of publication it “has not observed exploitation.” That doesn’t conflict with Amazon; CISA’s statement just has a time lag.
- Rapid7 expects a viable public exploit soon, given PHP’s enormous deployment.
- PHP itself says it inspected the PoCs that appeared after the leak and “did not identify any functional exploits at the time of release.”
Put together, my read is: a mature, stable public weapon may not be in place yet, but capable attackers are clearly already moving, and the clock is measured in hours, not days. Amazon put it most bluntly: “measure patch and mitigation timelines in hours. A 7-day or 30-day SLA assumes a delay that no longer exists.”
Can’t upgrade right away? Mitigations and their limits
Some systems can’t just be upgraded on the spot — a dependent extension, an app that needs re-testing, a production environment you can’t touch. The official advice offers some mitigation settings, but every one comes with “this is not a complete mitigation.” Keep that premise front of mind.
Figure 7: The official mitigation settings and their limits (data: php.net advisory, Rapid7, AWS)
Key things to watch:
- Settings must be enforced from the admin side. For example,
memory_limit=-1needs to be locked with something likephp_admin_valueso the application can’t change it back withini_set(). Anything set at the application layer or via.user.iniis “too late” — it isn’t in effect at request-parse time. Restart every worker after changing it. - Container and cgroup memory limits are incomplete. Rapid7 specifically says not to use
RLIMIT_ASorRLIMIT_DATA, which can themselves trigger the vulnerable path. - Hiding error messages does nothing. Turning off
display_errorsor suppressing errors with@won’t stop stale state from being read. Not seeing logs isn’t proof of safety. - A WAF is only a stopgap. Cloudflare pushed WAF rules the same day, but says itself they’re “STOPGAP only,” and they cover only traffic that passes through it. If your app doesn’t use multipart forms at all, blocking those requests before they reach PHP is a more practical line of defense.
Amazon also gave detection guidance: review web server logs for POST requests carrying the PHP_SESSION_UPLOAD_PROGRESS string in form uploads, and check web servers for unexpected process execution or file modification. It published a few observed IPs, but stressed they’re shared anonymization infrastructure that shouldn’t simply be blocked — investigate any sighting rather than block.
One line sums up this section: mitigations are for holding on until you can upgrade, not a substitute. In PHP’s own words, these measures “do not make an installation safe.”
I checked one of my own dev machines
Honestly, no amount of reading advisories beats running one command yourself. I checked a Laragon Windows dev machine, and the result is fairly representative.
Figure 8: The check results on the site author’s dev machine, October 22, 2026 (data: the author’s own php -v and php -i)
What php -v and php -i showed me:
- This machine’s Apache is loaded via mod_php (the config reads
LoadModule php_module ... php8apache2_4.dll) — exactly the setup PHP rates highest risk. - It runs PHP 8.5.5, in the affected range, needing 8.5.12.
session.upload_progress.enabledandfatal_error_backtracesare both On, both default settings used by confirmed paths for the second bug.- The machine also has 7.4.19, 8.1.10, 8.2.9 installed, and 7.4 and 8.1 have no official fix at all.
There’s a trap here that Windows users hit easily. I’d already downloaded 8.5.12, but grabbed the NTS (Non Thread Safe) build, whereas Apache’s mod_php needs the TS (Thread Safe) build — that’s the one containing the php8apache2_4.dll module. The NTS build doesn’t have that file and can’t be dropped in for Apache; it’s for FPM/CGI. So when you upgrade, know your SAPI and grab the right TS/NTS. Get this wrong and Apache simply won’t start.
My machine is purely local and not exposed, so the real risk is low. But it’s a complete demonstration of what ordinary people run into: mod_php as the high-risk default, a pile of unmaintained old versions installed, and even “do I want TS or NTS” needing a moment’s thought. If this were an internet-facing server, every line of it would need to be taken seriously.
Another thing worth thinking about: AI is changing the tempo of vulnerabilities
There’s one more thread to this event that I think matters more over the long run than the flaw itself.
The three parties who found php2shell were Calif, OpenAI and Wiz. Calif and Wiz both said publicly that they used AI models; OpenAI’s report is credited to its Codex Security team. And the PHP Foundation made a very candid point in its post-mortem: the rise of AI-assisted research has made the volume of reports the PHP security team receives balloon. They’ve shipped 15 CVEs since July 1 while working through more than 100 reports that turned out to be invalid, duplicates, or not reproducible. AI helps validate, but “a person makes every call and works on every patch.”
Zoom out: the side finding bugs is starting to use AI to go faster, while the maintainers fixing bugs and triaging reports are still the same handful of people. The PHP Foundation’s post says plainly that there are “too few” engineers who know the codebase, and asks sponsors and governments for funding. This isn’t unique to PHP; it’s the shared condition of open-source infrastructure.
So php2shell’s significance isn’t just “another RCE to patch.” It’s a preview: as both sides’ tools get stronger, the defender’s bottleneck shifts from “can we find the bug” to “do we have enough people to absorb it.” This site has written about one person plus hundreds of AI agents breaching 440 PaperCut servers and about Anthropic cutting the network on its internal evals — different faces of the same trend. Amazon’s “measure in hours” advice is, underneath, the same point.
My take
Should you be worried about this flaw? If you have any internet-facing PHP service, yes, and deal with it now. Unauthenticated, reachable remotely, and officially declared to have no complete mitigation — those three together mean leaving it is the same as leaving the door open. mod_php users have one extra layer of urgency.
But there’s no need to panic. The “high attack complexity, preconditions present” in the CVSS vector is real, which is why no one had a stable public weapon at disclosure. That gives you a window measured in hours, but a real one. Spend it well: upgrade internet-facing systems first, hold the rest together with mitigations plus a WAF, and schedule the upgrades.
What would raise my alert level? A verified, stable public exploit, or multiple parties beyond Amazon confirming large-scale successful exploitation in the wild — then the bar drops from “capable attackers” to “anyone,” and even internal systems need re-evaluating. Conversely, if the next two weeks show these paths have a low success rate in real environments, the “measure in hours” can ease a little — but you still upgrade, because 8.2 faces another end-of-life soon anyway.
One last repeat of the most important and most-skipped step: upgrading is the only complete fix. Mitigations only keep you alive until that moment.



