
PHP patched two RCE vulnerabilities rated 9.2 under CVSS v4.0 this week. And the emergency release shipped a day early because the disclosure embargo fell apart. That combination matters to you even if you never read advisories: your patch window this week was compressed by a supply-chain leak you had zero say in.
Here’s the whole picture in one paragraph. On October 21 at 14:00 UTC, the PHP project released 8.5.12, 8.4.27, 8.3.36, and 8.2.35, fixing CVE-2026-109618 and CVE-2026-109619. Both flaws sit in PHP’s core request-parsing layer and, under the right conditions, allow an unauthenticated attacker to execute code on the server. Researchers at watchTowr told BleepingComputer the flaws are believed to affect PHP versions 5, 6, 7. And 8. Every release before those four fixed versions is vulnerable. And the Foundation’s position is that there are no real mitigations, only an update makes you safe.
My take after reading the advisory and the disclosure postmortem: the blame argument everyone is having misses the operator lesson. Coordinated disclosure held for weeks, then broke through a party most of us have somewhere in our supply chain without thinking about it. Your patch window is not set by the vendor’s announcement. It’s set by whoever builds and ships binaries first.
The Bugs Live Below Your Application Code
Both vulnerabilities sit in PHP’s native request-parsing code, the C layer that runs before any of your application code executes. That single detail should reset your mental model of exposure. Input validation in your controller, a patched framework, a WAF rule tuned to your app’s routes: none of it engages before the vulnerable code has already run.
CVE-2026-109618 has a mechanism the Foundation spelled out plainly.
If a request reached PHP’s memory_limit at exactly the wrong moment, PHP could leave partially initialized internal data behind and later treat it as valid, corrupting memory.
Out-of-memory conditions are cheap for an outside party to provoke, since you just send requests designed to consume memory.
The bug is not that a request fails.
Bug: that the failure leaves the runtime in a state it later trusts.
No login, no API key, no session, nothing your code checks. “Under the right conditions” is the Foundation’s own phrase.
And those conditions live in the runtime rather than in your application. Researchers tagged the pair php2shell, which tells you how they frame the end state.
The Embargo Broke Six Hours Before the Patch
Run the timeline and it moves fast. The embargo was set for October 22 at 14:00 UTC. After embargoed details leaked, the project moved the release forward to October 21 at 14:00 UTC and sent advance notice on October 20. The Foundation says the coordinated process worked well until two days before the original target.
Then, on October 21 at 07:41 UTC, Chainguard published built images containing the fix, more than six hours before even the moved release time. The Foundation’s account is blunt: Chainguard “unilaterally broke the embargo,” and the move “disregarded weeks of work by many parties toward a coordinated disclosure.” The patches went public at 14:00 UTC as rescheduled.
The consequence the Foundation flagged is the one operators should sit with: “Any attacker could now study the fix in binary form while every other PHP user was still waiting for the release.” I’m less interested in assigning blame than in what those six hours prove.
A fix that exists as a binary is a fix that can be reverse-engineered.
And the quiet window coordinated disclosure exists to protect inverted. Patched artifacts were public before the announcement did.
If your incident response assumes “we patch within days of the advisory,” note that the study clock started earlier than the advisory itself.
There’s a structural problem here too, and it won’t go away with better manners. The more parties inside an embargo, the weaker the embargo. And image vendors have to build and ship the fix to serve their own users. Publishing before the coordinated hour and leaking are hard to distinguish from the outside. You inherit that tension every time you pull a base image. And I pull base images for nearly everything I ship.
No Real Mitigation Exists, Only the Update
The Foundation stresses there are no real mitigations; only an update makes you safe. The fixed versions are 8.5.12, 8.4.27, 8.3.36, and 8.2.35, and everything before them is vulnerable. Apache mod_php is described as the easiest deployment to weaponize, which puts a lot of shared hosting and older LAMP stacks in the worst quadrant: most exposed, least able to fix it themselves.
Small operators should not skip the uncomfortable part.
The fixed list stops at the 8.2 branch, while watchTowr’s assessment covers versions 5 through 8 as believed affected.
This release set contains nothing below 8.2.35. If your app is pinned to an old PHP given that one dependency demands it, tonight’s advisory does not reach you. That is not a patch ticket. A migration project with a 9.2 sitting on top of it.
What To Do Before You Close the Tab
Work the checklist in this order:
– Inventory first, every server, container, and host account. I don’t read technical analysis before I know what I’m actually running, as the version list decides everything downstream.
– Take the patch for your branch: 8.2.35, 8.3.36, 8.4.27, or 8.5.12. Every current branch got a fixed release, so there is no security reason to jump branches mid-incident and plenty of compatibility reasons not to.
– Patch the mod_php hosts first. It is the deployment called out as easiest to weaponize.
– Rebuild anything built on a pulled PHP image. This event reached the public through published images, so a stale cache in your deploy pipeline is an unpatched box wearing a fresh timestamp.
– Anything older than 8.2: write down that it exists, with a date next to it. There is no fixed release for it in this set, and pretending otherwise is how the debt compounds.
The Real Lesson From php2shell
Two failures stacked this week. A 9.2 in the C layer of one of the web’s most widely deployed runtimes. And a disclosure process that survived weeks of coordination only to break hours from the finish line, through a vendor inside the circle of trust. You control neither of those. You control how fast you can answer “what PHP am I running, everywhere,” and how fast you can roll a branch patch once the answer disappoints you.
Go run that inventory now.
If you find a box on a dead branch, that’s your next weekend planned.
And if you want the operator’s cut of events like this in the week they happen, follow along, since I write these so you can act tonight instead of catching up tomorrow.
