On October 21, 2026, the PHP development team released emergency security updates for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, collectively known as PHP2Shell. Both carry a CVSS 4.0 score of 9.2 and both allow an unauthenticated attacker to run code on a vulnerable server with nothing more than a crafted HTTP request. Because the flaws are in PHP itself, not in any particular application, every PHP site was affected regardless of how clean its own code was.
Every one of our managed servers was patched by 9:27 PM Eastern that same day. More importantly, we had multiple layers of protection in place throughout the incident, including measures we put in place before PHP’s official fixes were released.
We published a status notice throughout the day as events unfolded. This post is the longer version: what the vulnerabilities actually were, what we did before the patches existed, why there was a gap between the PHP release and our ability to install it, and a clean timeline of the day.
What PHP2Shell actually is
The two CVEs are related but distinct, and both are triggered while PHP is still parsing an incoming request, before any application code runs. That is what makes them so dangerous: no login, no plugin, and no application bug is required.
- CVE-2026-109618 is memory corruption after an out-of-memory failure. If PHP runs out of memory partway through handling a request, it can be left with partially initialized internal data. The cleanup routine then treats that invalid data as valid.
- CVE-2026-109619 is stale request state. Internal data belonging to one request can survive after its memory has been freed, and the next request handled by the same worker process can pick it up before normal initialization resets it.
PHP’s session upload progress feature, which lets a site show a live progress bar during a file upload, was confirmed as one of the paths an attacker could use to reach the second flaw. That feature is on by default and it processes client-supplied data before any script runs, which is why it mattered so much in our early response.
We started before the official release
We became aware of these vulnerabilities before the PHP team’s embargo lifted at 10:00 AM Eastern on October 21. Rather than wait for the fixes, we started looking for anything we could do immediately to reduce the risk.
Through our own investigation, and with help from security researchers who have asked to remain anonymous, we identified session upload progress as an attack path. So before the official fixes were out, we disabled PHP’s session upload progress feature on every PHP version across our servers.
This was a server-level configuration change. It did not require anything from our customers, and it did not affect file uploads. Uploads continued to work normally. The only difference was that applications using PHP’s built-in session upload progress feature would not receive live progress information while a file was transferring.
We knew this was not a complete fix for either vulnerability. It closed one known door while we waited for the real fix, and that was worth doing.
Web application firewall protection
The second layer was the web application firewall that already runs across our fleet through Imunify360. As PHP2Shell details and publicly available exploit tools began circulating, Imunify360 shipped updated firewall rules to detect and block the known attack patterns. These rules are distributed and applied automatically, with no action on our part.
Three rulesets landed on October 21, all times Eastern:
- 5:08 AM, ruleset 8.83: blocked the known exploit request pattern on ModSecurity and Coraza and added detection of exploit attempts. Our servers run LiteSpeed, where that blocking rule could not run because the request data it needed is not available to the firewall. On our fleet, 8.83 shipped a separate rule that logged matching requests but did not block them.
- 9:07 AM, ruleset 8.84: added blocking on LiteSpeed for the publicly available exploit tool and for upload progress requests that did not originate from the site’s own pages. This is when WAF blocking of PHP2Shell went live on our servers, nearly an hour before the embargo lifted.
- 1:17 PM, ruleset 8.85: blocked further variants of the exploit tool and added detection of related malformed upload requests.
The gap between 8.83 and 8.84 is why the earlier change mattered. Because we had already disabled session upload progress before the embargo lifted, the specific attack path used by the circulating exploit was not available on our servers during those hours, before the LiteSpeed blocking rules existed. We were not depending on the firewall vendor alone.
Alongside the rules, Imunify360’s IP reputation system was continuously identifying addresses seen scanning for or attempting to exploit the vulnerability and giving them a CAPTCHA challenge before they could reach a site.
It is worth being clear about what a firewall does and does not do here. Firewall rules stop the attack patterns that are known. They do not fix the underlying bug, and an attacker who finds a different way to trigger it can get past them. That is why we treated the firewall and the upload progress change as a way to hold the line, and installing the actual PHP patches as the only real fix.
Why the patches were not immediately available to us
At 10:00 AM Eastern on October 21, the PHP team released PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. Those are the only branches the PHP project still supports, so those are the only versions they patched.
An official PHP release is not something we can install directly on a cPanel server. Our servers run CloudLinux, and the PHP versions we offer are CloudLinux’s Hardened PHP packages. CloudLinux builds and maintains those packages, integrates them with the operating system and the hosting environment, and distributes them through its own software repositories. When PHP publishes a fix, CloudLinux has to build, test, and release patched packages before anyone running CloudLinux can install them.
That matters even more for older PHP versions. PHP 7.4 and everything before it is End of Life upstream and received no fix from the PHP team at all. CloudLinux’s Hardened PHP backports security fixes into those versions, which is how we are able to keep offering PHP 5.x and 7.x to customers who still need them. For those versions, CloudLinux was not just packaging an existing release. They had to adapt and backport the fixes into PHP branches that have not received official updates in years.
So from 10:00 AM onward we were waiting on our operating system vendor. That is the honest explanation for the gap. CloudLinux announced builds through the day, and at one point announced the PHP 7.4 build before it had actually appeared in the repositories our servers install from, so we opened a ticket with them. When the 7.x packages were finally pushed in the evening, their repositories were under heavy load from every CloudLinux customer pulling the same updates at once, which slowed our installs further. The 8.x packages, oddly, came last, even though those were the versions PHP had patched directly.
None of this was CloudLinux being careless. Backporting a memory-safety fix into PHP 5.2 is real work, and they shipped patches for sixteen PHP versions in a single day. But it does mean that for roughly eleven hours after PHP released its patches, we were dependent on CloudLinux preparing and distributing the packages our servers actually run. During that window the firewall rules and the upload progress change were what stood between the circulating exploit tools and our customers’ sites, and we had everything staged to install the packages the moment each one became available.
Timeline for October 21, 2026
All times are Eastern.
| Time | What happened |
|---|---|
| 12:48 AM | We published our initial security notice. Session upload progress was already disabled across all PHP versions on all of our servers. |
| 5:08 AM | Imunify360 ruleset 8.83 went live. Its blocking rule did not run on LiteSpeed; on our servers it logged matching requests only. |
| 9:07 AM | Imunify360 ruleset 8.84 went live, adding LiteSpeed blocking for the publicly available exploit tool and off-site upload progress requests. WAF blocking active on our servers from this point. |
| 10:00 AM | The PHP team’s embargo lifted. PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35 were released upstream. |
| 10:40 AM | We confirmed the firewall rules were active fleet-wide and that we were waiting on CloudLinux’s Hardened PHP packages. |
| 11:07 AM | CloudLinux began rolling out patched builds. We were monitoring repository availability and ready to install. |
| 1:17 PM | Imunify360 ruleset 8.85 went live, covering further exploit variants and malformed upload requests. |
| 2:15 PM | We posted a detailed update on the firewall protections. CloudLinux had announced the PHP 7.4 build but it was not yet in the repositories, so we opened a ticket with them. |
| 6:27 PM | Still waiting on CloudLinux. They told us the packages should be available within the hour. |
| 7:22 PM | CloudLinux pushed PHP 7.0 through 7.4 to the repositories. Repository load was heavy and installs were slow. No 8.x packages yet. |
| 7:32 PM | PHP 7.0, 7.1, 7.2, 7.3, and 7.4 fully patched across all managed servers. |
| 9:27 PM | PHP 5.2 through 8.5, every version we offer, fully patched across all managed servers. |
A note about version numbers
If you check your PHP version, it may not match the numbers in PHP’s announcement, and that is expected. CloudLinux applies the security fix to the version it already ships rather than bumping the upstream version number. This is called backporting, and it is the same way most operating system vendors handle security updates.
A server reporting PHP 7.4 or PHP 5.6 is not missing the fix. The fix is in the CloudLinux build, and every build we run has it. The version string tells you which PHP branch you are on, not whether it has been patched.
Did anyone get in?
Beyond putting protections in place and applying the patches, we also looked for signs that these vulnerabilities had been successfully exploited against our servers.
Using what is known about the exploits, we reviewed web server access logs, Imunify360 activity logs, web application firewall hits, malware scanner results, and the other logs and security data relevant to this vulnerability. We found no evidence of successful exploitation or compromise in anything we reviewed.
That is reassuring, but no amount of logging can guarantee that every possible attempt would have been detected. If you are concerned about sensitive credentials, rotating API keys, access tokens, passwords, and other secrets is a reasonable precaution. It is also something worth doing periodically whether or not there is a known incident.
Where things stand
All of our managed servers were patched against CVE-2026-109618 and CVE-2026-109619 on October 21, 2026, across every PHP version from 5.2 through 8.5. Once patching was complete we re-enabled session upload progress, so live upload progress bars work again. The Imunify360 firewall rules and IP reputation protections remain in place as an ongoing layer.
No action was required from our customers to put the mitigations or the patches in place. All of that was handled at the server level.
Our approach to this was simple: do whatever we reasonably could right away, keep multiple layers of protection in place, install the real fix the moment our vendor made it available, and keep our customers informed the whole way through. We cannot control when upstream developers or our operating system vendor release their updates. We can control what we do in the meantime, and we think this incident showed that well.