October 23, 2026
The PHP Vulnerability Was Exploited 4 Days Before Anyone Announced It
I have a WordPress project running on PHP 8.3.6, and on Wednesday the version I need to be on became 8.3.36. That is the whole of myโฆ

By Andrus
9 min read
I have a WordPress project running on PHP 8.3.6, and on Wednesday the version I need to be on became 8.3.36. That is the whole of my personal stake in this story, and it was enough to make me read every timeline I could find about the two flaws now called PHP2Shell, because the advisory told me to patch and Amazon's threat intelligence team told me something less comfortable: start looking at your logs from October 17, four days before anyone outside a small coordination group knew the bugs existed
The two flaws are CVE-2026โ109618 and CVE-2026โ109619. Both are unauthenticated remote code execution (RCE) bugs in the PHP runtime itself, not in WordPress or any plugin, which means the usual comfort of "I keep my plugins updated" buys nothing here. The first is a memory corruption that happens when PHP runs out of memory partway through setting up a request and the cleanup code then trusts half-built data. The second is a use-after-free, where state left over from one request points at memory that has already been released, and the next request handled by the same worker can act on it. PHP's own security team rates both at 9.2 on version 4 of the Common Vulnerability Scoring System (CVSS). Every way of serving PHP to the web is in scope: PHP-FPM, Apache's mod_php, php-cgi, FrankenPHP and LiteSpeed, with mod_php the worst case because a demonstrated exploit fires before any application code runs.
None of that is unusual for a critical bug. The order of events is.
One honeypot hit on October 17
Amazon runs a global network of decoy servers called MadPot, and on October 17 one of them recorded an attempt to exploit PHP2Shell. One attempt, from an IP address belonging to a commercial anonymization network, against a vulnerability that would not be publicly disclosed until 14:00 UTC on October 21. Amazon's write-up is careful about what it does not know. It does not say which of the two CVEs the request targeted, it does not publish the payload, and it says plainly that it remains unclear how the actor acquired exploit information before disclosure.
What Amazon does say is the instruction I have taken seriously: investigate from at least October 17, not from the disclosure date. That single date shifts the question a system owner has to answer. Patching on the 21st or 22nd tells you that you are protected going forward. It tells you nothing about whether somebody who knew about the bug four days earlier had already been through your server, and the only way to answer that is to read logs that most of us never look at unless something is visibly broken.
I want to be precise about how strong this evidence is, because the title of this piece leans on it. A single honeypot request is not a breach. Amazon says it is unclear whether even the later attempts would have succeeded against real systems, and the PHP Foundation's security team says it had not identified a functional public exploit by release time. What the October 17 hit establishes is narrower and, to me, more unsettling: at least one party outside the embargo was already sending traffic shaped like this bug before the embargo ended. Whether they had a working exploit or a good guess, nobody has shown.
Three leaks in a single day
If October 17 was a quiet signal, October 20 and 21 were the embargo coming apart in public, in roughly three stages.
Around 15:00 UTC on October 20, the two CVE identifiers started circulating on forums and social media along with a wrong release time and a CVSS score of 10.0. That score was never PHP's, and it is still the number you will see repeated in some early coverage. No technical details came with it, but the leak was specific enough that PHP pulled its schedule forward, posting an advance notice that evening and moving the release from October 22 to October 21, still at 14:00 UTC.
Around 20:00 UTC the same evening, Calif, one of the research firms that reported the flaws, mistakenly published a video of its proof of concept working against real targets. It took the video down, but copies spread, and according to the PHP Foundation's account those copies helped public exploit code appear the next day.
Then at 07:41 UTC on October 21, more than six hours before the coordinated release, Chainguard published container images containing the fix. The PHP Foundation says this broke the embargo and handed attackers a patch they could study in binary form while everyone else waited. Chainguard's chief executive, Dan Lorenc, said on Hacker News that he made the call to release early when exploits hit in the wild, that his company had found the vulnerability independently using its own testing harness and a frontier AI model, and later apologized for the added stress on maintainers.
Meanwhile the traffic was already moving. Amazon saw the earliest proof-of-concept exploit around 02:00 UTC on the 21st, twelve hours before release, with more attempts from different anonymized infrastructure over the next six hours and payload variations that suggested more than one actor. Cloudflare's chief executive Matthew Prince said his network saw thousands of exploitation attempts in the ten hours before disclosure, tens of thousands within 45 minutes after it, hundreds of thousands within two hours, and eventually millions. Attackers modified payloads to get past Cloudflare's web application firewall (WAF) rules, apparently learning from which requests were blocked. watchTowr reported no exploitation at 11:26 UTC and active exploitation attempts against both CVEs at 14:19, nineteen minutes after the patch shipped.
I have read a lot of disclosure timelines and this is the first one where I could not find a single hour, from the evening of the 20th onward, in which the defenders were ahead.
A bug PHP had seen in 2024
What bothers me more than the leak is that one of these flaws was not new to the people responsible for fixing it.
During PHP's first external security audit in 2024, a core developer working on a separate finding noticed signs of the out-of-memory issue that became CVE-2026โ109618. Somebody theorized an exploit, nobody found a concrete attack path, and other problems took priority. When the security team later tried to fix it, it drafted several competing repairs and each one had a cost: one broke backward compatibility, one introduced a denial-of-service risk, and one would have forced changes on thousands of third-party extensions. A small team that worked by consensus and was afraid of shipping the wrong choice let the work stall and restart for months.
The PHP Foundation's own description of this, in its October 21 post, is that the delay was "a structural failure," caused by both the security team's decision process and its lack of resources. I respect that sentence more than I expected to, because most projects would have written something about complexity and moved on. The Foundation says it has since set up an ecosystem security team, hired two more engineers, and is moving security decisions from consensus to majority vote, and it is asking the companies, hosting providers and governments that run on PHP to fund security work.
That last request is the one that should land. PHP runs on 69.3% of websites whose server-side language W3Techs can identify, and the team deciding how to fix a memory bug in its request lifecycle was small enough that disagreement over three imperfect patches could freeze it for most of a year. I do not think any amount of process redesign makes that ratio safe, and I am not sure who is going to pay to change it.
What 8.3.6 means on my WordPress server
Back to my own problem, which is more mundane and probably closer to yours.
The fixed releases are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. My server reports 8.3.6, which on the face of it is thirty patch releases behind the fix. But 8.3.6 is also exactly the version string Ubuntu 24.04 ships for its php8.3 package, and Ubuntu backports security fixes into that package without changing the upstream number; its September security notice, for instance, fixed three PHP issues in a build labelled 8.3.6โ0ubuntu0.24.04.11. So the version number on its own does not answer whether a machine is patched. If your PHP came from a distribution, the thing to check is the full package version and your distribution's security notice for these two CVEs. If it came from a container image or a source build, 8.3.6 means what it looks like it means, and it is old.
Older branches are worse off. PHP 8.1, 8.0 and 7.4 get no official release, only minimal source backports for people prepared to build from source, and anything from 7.3 back gets nothing. Calif says the earliest affected code path it found goes back to PHP 5.4, and W3Techs currently counts 26.9% of PHP sites on PHP 7 and 7.7% on PHP 5. Roughly a third of the PHP web, then, sits on a branch for which the PHP project will not ship a fixed release at all, and getting out of that means a major-version migration, not a patch.
For WordPress specifically, Calif confirmed pre-authentication RCE against specific versions of WordPress, Drupal, Joomla and Magento, so this is not a theoretical concern about some exotic configuration. If patching has to wait a few hours, PHP lists interim settings that reduce exposure without making the system safe: set memory_limit=-1 in a way the application cannot override (for the out-of-memory bug), set session.upload_progress.enabled=0 (for the use-after-free), also set fatal_error_backtraces=0 on PHP 8.5, and restart every PHP worker afterwards. Turning off the memory limit to close a memory bug feels backwards, and PHP's answer is to cap memory at the container or cgroup level instead, which it also says is not a complete mitigation. The session setting matters more than it looks; the security firm Hadrian said most of the attacks it observed abused PHP's session upload-progress path.
Then the logs. Amazon's hunting guidance is to look for POST requests carrying the string PHP_SESSION_UPLOAD_PROGRESS in form uploads, and it published six IP addresses it saw, starting with 103.216.220.92 on October 17, while warning that these are shared anonymization services worth investigating rather than blocking. For a single WordPress site that means grepping the web server's access logs back to the 17th, which is a ten-minute job on a box I own and a support ticket on a managed host where I do not keep the logs at all. I suspect a lot of small sites are in the second situation and will never know.
Embargoes are losing to rediscovery
The usual reading of a messy disclosure is that someone broke the rules, and there is a version of this story where Chainguard is the villain and Calif's video is the accident that made it worse. I do not find that reading very useful.
Look at who found these bugs. The reporters were Wiz Research, Calif and OpenAI's Codex Security team, and Calif and Wiz have both said they used AI models in the research. Chainguard says it found the same vulnerability independently with a frontier model. One researcher reportedly turned the flaws into working exploits in about a week, work that would otherwise have taken a team months. Calif's own caveat is that current models do not reliably start from obscure, twenty-year-old primitives on their own, so knowing the target's history still mattered. Even so, that is at least four organizations converging on the same decade-old bug in the same window, and the person behind the October 17 request may simply have been a fifth.
Amazon's write-up has the sentence for it: "An embargo protects defenders only until someone else finds the same bug." Coordinated disclosure assumes the finder holds a scarce secret and the vendor gets time to prepare while nobody else knows. When the tools that find bugs are available to anyone who pays for an API key, the secret is not scarce, and the embargo window starts to look less like protection and more like a period in which the attacker knows and the system owner does not.
I do not have a better system to propose. Shorter embargoes punish small volunteer teams like PHP's, which already needed months to agree on one fix. Longer ones widen the window that October 17 just showed us. What I am changing is smaller: when a critical bug in something I run is announced, I now treat the disclosure date as the end of the exposure period I have to investigate, not the start of it. For PHP2Shell, that means my WordPress logs from October 17 onward, and an upgrade to a build that actually contains the fix rather than one whose version number looks close enough.
Sources
- Amazon threat intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot, AWS Security Blog
- Hackers pile on PHP2Shell as AWS reveals attacks began before disclosure, The Register
- PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws as Exploit Attempts Emerge, The Hacker News
- PHP knew about one of the flaws in 2024 but could not agree a fix, The Next Web
- PHP Foundation Says Chainguard Broke Security Embargo Ahead of Emergency Patches, Socket
- php2shell (CVE-2026โ109618, CVE-2026โ109619): Frequently Asked Questions About Critical PHP Remote Code Execution, Tenable
- PHP2Shell FAQ: CVE-2026โ109618 & CVE-2026โ109619 Fixes, watchTowr
- USN-8743โ1: PHP vulnerabilities, LWN.net
- Usage statistics of PHP for websites, W3Techs