Notes on coding agents and the pages they leave behind, on moving between notes apps, and on the plain mechanics of keeping what you think. Written and published from a Sumibako vault.
PHP2Shell: the PHP bug that took government sites offline, and what to check on yours
PHP2Shell from the sources: two unauthenticated RCEs in PHP itself, a leak, an embargo broken twice, attacks four days early, and five checks for your site.
Prashant Shaw
Founder, Sumibako
11 min read
I do not run PHP. Sumibako is Next.js on one side and Convex on the other, and the last PHP I wrote was a guestbook with a visitor counter. The counter was wrong. So when the PHP2Shell advisories came out on 21 October I had the rare pleasure of reading a critical vulnerability that was not mine. The pleasure lasted about a paragraph. Then I remembered that PHP runs 70.8% of websites whose server-side language is known, that my bank's login page and half the blogs I read are among them, and that the Finnish government took pages offline. Not mine is not the same as not my problem.
This is what PHP2Shell is, in the words of the people who found it and fixed it, how the week went wrong before the patch was even out, and what to check if a PHP site is yours.
🐘 What broke, in PHP's own words
Two bugs, both in PHP itself rather than in any application, both reachable by an unauthenticated request. PHP's release announcement describes the first, CVE-2026-109618: "out-of-memory handling can interrupt PHP while internal request data is only partially initialized. Request cleanup may then treat the invalid data as valid." And the second, CVE-2026-109619: "request-owned internal state can survive after its backing memory has been freed. A later request handled by the same worker may use that stale state before normal initialization resets it."
The way in is a file upload. Both bugs live in how PHP reads multipart form data, which AWS's mitigation guide calls "the request format browsers use for file uploads" and which PHP parses "before your application code runs". That last clause is the whole story. Your framework's validation, your plugin's sanitising, your carefully written controller: none of it has executed yet when the damage is done. The second bug sits in the upload progress feature, which has been on by default since PHP 5.4 and which, as Akamai's
puts it, "PHP intercepts it before the target script even begins executing."
Sophos's advisory has the severity in one line: "Both can allow unauthenticated remote code execution with the privileges of the web server account, and are rated CVSS v4.0 9.2 (Critical)." PHP says who is exposed: "all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed." It rates the risk "highest for mod_php". The fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and the sentence that matters for everyone still on 8.1 or older: "PHP 8.1 and older no longer receive updates from the PHP project."
⚠️WARNING
PHP is unusually blunt about workarounds: "There are no complete mitigations, updating is the only safe choice." watchTowr goes further about the ini tweaks circulating online: "Mitigations that involve changes to .ini files should be understood to be ineffective and not suitable to prevent exploitation."
🗓️ Two years, two months and twenty-six minutes
The discoverer's write-up is by Ryan Austin of Calif, who was auditing PHP inside OpenAI's Patch the Planet programme from 30 July. He found the code execution paths on 1 August and reported the first bug on 11 August. He also found breadcrumbs going back years: a memory-limit bug from 2004, a bug report from 2020 about long multipart variables that was shrugged off, and the 2024 OSTIF and Quarkslab audit that rediscovered the out-of-memory problem without proving it exploitable. The oldest reachable path, he writes, "dates to PHP 5.4.0".
The PHP Foundation's own account is the most honest vendor post I have read this year. On the 2024 sighting: "We won't pretend otherwise: the delay was a structural failure, caused by both the security team's decision process and its lack of resources." On where the bugs live: "Both issues sit in parts of PHP that nearly every request touches: memory management and error handling."
Then the last two days, which went about as badly as a coordinated disclosure can. Around 15:00 UTC on 20 October the CVE identifiers leaked online. The Foundation: "They came with a wrong release time and a wrong CVSS score of 10.0 (the actual score is 9.2). No technical details leaked." PHP pre-announced at 19:30 UTC and moved the release forward a day, to 14:00 UTC on the 21st. That evening Calif accidentally published a proof-of-concept video. And at 07:41 UTC on the 21st, in the Foundation's words, "more than six hours before the coordinated release, Chainguard unilaterally broke the embargo and published built images containing the fix." The GitHub advisories went public at 13:34 UTC, twenty-six minutes early. The release followed at 14:00.
Two years from the first sighting to the fix. Two months from the report. Twenty-six minutes from the advisory to the release, and a patch diff in the wild six hours before that.
When (UTC)
What happened
2024
A PHP core developer sees the first signs of the memory problem while fixing an audit finding
30 Jul 2026
Calif starts auditing PHP inside OpenAI's Patch the Planet programme
1 Aug
Ryan Austin finds the code execution paths
11 Aug
First bug reported to PHP; the second follows on 21 Aug
17 Oct
Amazon's honeypots record the first exploit attempt
20 Oct, about 15:00
The CVE numbers leak with a wrong 10.0 score; PHP moves the release a day earlier
21 Oct, 02:00 to 08:00
Several proof-of-concept exploits hit Amazon's honeypots
21 Oct 03:02
Cloudflare's blocking rules on for every plan
21 Oct 07:41
Chainguard publishes fixed images, six hours before the release
21 Oct 13:34
The GitHub advisories go public, 26 minutes early
21 Oct 14:00
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 released
23 Oct
PHP's informational advisory for a third flaw, CVE-2026-115560, not yet fixed
🕵️ Someone tried it four days early
The embargo had already failed in a quieter way. Amazon's threat intelligence team reported that its honeypot network saw "a PHP2Shell exploitation attempt dating to Oct. 17, 2026, in MadPot telemetry, four days before public disclosure". The attempt "originated from an IP address associated with a commercial anonymization network." Amazon is careful: "Technical analysis is ongoing, and it's unclear if any of these attempts would have succeeded in real-world systems." Multiple proof-of-concept exploits followed between 02:00 and 08:00 UTC on the 21st, before the release.
CJ Moses, Amazon's security chief, drew the lesson in two sentences I expect to see quoted for years: "An embargo protects defenders only until someone else finds the same bug." And: "AI-assisted analysis makes it cheaper to turn a patch diff or advisory into a working exploit."
Whether anyone has actually been broken into depends on whom you ask, and the honest answer on 24 October is that the sources disagree. watchTowr's rapid reaction states that "watchTowr has observed exploitation of both CVE-2026-109618 and CVE-2026-109619 in the wild." CISA's alert, the same day: "While CISA has not observed successful exploitation of these vulnerabilities in the wild as of the time of publication, they pose a risk to organizations if left unpatched." Unit 42's brief, two days later, describes a real one: "In one case, the attackers targeted a government entity in Europe and within two hours of the initial exploitation they had successfully accessed password hashes and multi-factor authentication secrets." And The Hacker News reports on the 23rd that "researchers say a reliable exploit is proving harder to build than expected." All four can be true at once: scanning everywhere, success somewhere, reliability nowhere yet.
🌍 How big is big
Every vendor published a number and every number is a different unit. Unit 42: "Palo Alto Networks Cortex Xpanse has identified the presence of over 22.6 million exposed instances potentially vulnerable". VirusTotal "fingerprints roughly 5.1 million IP addresses running PHP". VulnCheck counted 2.6 million hosts and Modat 4.38 million services, 79% of them on branches PHP no longer supports. None of these is a count of servers that are actually exploitable. All of them are large.
Four counts, four units. The one thing they agree on is the order of magnitude.
The reaction was large too. The NSA said what agencies rarely say out loud: "If an immediate update is not feasible, it is recommended that organizations take the system offline until it can be fully mitigated." CISA said the same for anyone on 8.1 or older. And people did. The BBC: "Multiple cyber-security agencies have urged organisations unable to apply fixes in time to consider taking their sites down, leading bodies such as the Finnish government, Edinburgh council and the BBC to take pages offline." Sophos took its own customer portal down. A site that went dark this week was being careful, not necessarily hacked.
Cloudflare turned on blocking rules for everyone, including free plans, at 03:02 UTC on the 21st, with a caveat worth reading if you have customised PHP: "Customers who have changed session.upload_progress.name are not covered by the WAF rule." Its plain-English summary is the one to send to a client who thinks a plugin update will do: "These flaws are in the PHP runtime, so updating website code or a plugin(s) alone does not fix these vulnerabilities."
🤖 Did AI find it? Three answers
The headlines said AI discovered PHP2Shell. The people involved say three different things, and the difference matters.
Discovery: Ryan Austin says no. "No special harness, or access to models that weren't generally available to everyone were used in the initial bug discovery." His other line is the humbler one: "We were not expecting to find anything critical - everyone and every lab had already done extensive AI assisted audits of this target." Exploitation: Wiz, which found further attack paths, says yes. Via the BBC: "Frontier models were critical to making this process practical, enabling us to develop and adapt working exploits across multiple applications in hours," Fixing: the Foundation says AI helps "validate reports and group reports sharing the same root cause, but a person makes every call and works on every patch."
So: a human found it with ordinary tools and twenty years of context, machines made the exploits fast, and humans still wrote the fix. That is roughly the shape of every story this week, and it is why Amazon's line about patch diffs turning into exploits is the one to worry about.
🧰 What to check if the PHP site is yours
1️⃣ Find the version that serves requests, not the one on the command line. watchTowr's FAQ makes the point: "The command-line php binary can be a different version from the one PHP-FPM or Apache runs." Put a phpinfo page behind authentication, or ask your host. If a host manages PHP for you, the only question is which version serves your site and when it was updated.
2️⃣ If it is 8.2 or newer, update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and restart every long-running worker. Distribution packages often backport the fix without changing the version string, so read the package changelog for the CVE numbers rather than trusting the number.
3️⃣ If it is 8.1 or older, you are on a branch PHP does not patch. There are source-level backports for 7.4, 8.0 and 8.1; otherwise the agencies' advice applies, and it is the word offline.
4️⃣ Set session.upload_progress.enabled=0 and keep it that way. On 23 October PHP published an informational advisory for a third issue, CVE-2026-115560, not fixed by this week's releases: "We suggest you set session.upload_progress.enabled=0 until the next regular bugfix release, to fully protect from an unlikely RCE vector." PHP adds that "The issue can only occur under an unusual combination of configuration and application code." It has not said which versions, what score, or when.
5️⃣ Look back. Sophos's advisory puts the window plainly: "The PHP Project received the first reports of these issues on August 11, 2026, and exploitation attempts have been observed since at least October 17, 2026." Look for new PHP files in the web root, for shells spawned by the PHP process, and for memory-limit fatal errors in the logs around the 17th and after.
📎 If you do not run PHP
Nothing on your own computer is affected and there is nothing for you to install. The risk is second-hand: a site you use, patched late, could have had its database read. Treat password-reset and breach emails from PHP-based services seriously over the next few weeks, and be a little slower than usual to dismiss them as phishing. Everything else this week, from Railway's lost secrets to the certificate authority whose key was the number 4, is in the state of the internet this month, and the habits that get a site through weeks like this are in a checklist for the next one.
I will go back to not running PHP now. It has never felt like less of an achievement.
Eight eMudhra keys were integers under 256, one of them 4. Why browsers blocked them in hours, why your Docker image did not, and what to check by 27 October.
10 min read
; php.ini or the FPM pool, never ini_set(), then restart every worker
session.upload_progress.enabled = 0
shellscript
php -v # the command-line binary, which may not be the one serving requestsphp-fpm -v # the FPM binary, where FPM is what serves you# Or a page with <?php phpinfo(); ?> behind authentication, read once and deleted.