On 21 October 2026 two flaws in the core of PHP were disclosed. PHP is the language behind WordPress, Laravel and a large chunk of the web. The identifiers are CVE-2026-109618 and CVE-2026-109619 (a CVE is the reference code used to catalogue a vulnerability), and the internet quickly named them php2shell.
They score 9.2 on the CVSS 4.0 scale. Both allow remote code execution with no login required. Put simply, whoever exploits them can run the machine as if it were their own.
What happened that day
Official fixes shipped the same day: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Real-world exploits were already circulating within hours, so waiting until morning was out of the question.
Cloudflare extended its WAF rules to free plans as well. A WAF is a web application firewall: it inspects requests before they reach the site. Cloudflare was candid about the limits, warning that attackers tweak their payloads to slip past the rules. The filter helps, but it is not enough on its own.
Our problem: no update yet
Our servers run CloudLinux with cPanel, which ships PHP in its own packages. On the evening of the 21st the patched versions of those packages had not been released.
We had five versions of PHP-FPM running, the service that executes PHP for each site: 7.4, 8.2, 8.3, 8.4 and 8.5. So we worked on two fronts.
1. Close the confirmed attack path
The confirmed attack path goes through session.upload_progress, a PHP feature that tracks the progress of file uploads. We switched it off on every installed version, using a dedicated config file and a PHP-FPM restart:
for d in /opt/cpanel/ea-php*/root/etc/php.d; do
echo "session.upload_progress.enabled = 0" > $d/zz-php2shell.ini
done
/scripts/restartsrv_apache_php_fpm
The loop walks through every PHP version on the server, so none gets left behind. To be clear, this mitigation closes the confirmed attack path, not every possible one. It was a stopgap until the real fix arrived.
2. The filter in front
Our servers only accept web traffic that comes through Cloudflare. Anyone trying to hit a site by going straight to the server finds the door shut, which meant the new WAF rules applied to every single request.
A fix with the same version number
CloudLinux released the patched packages at 22:55 Italian time, with a detail that could easily mislead: the PHP version number did not change.
8.5.11 stayed 8.5.11, but the package became 8.5.11-2.el9.cloudlinux.1. Likewise 8.4.26 became 8.4.26-2…cloudlinux.1, and 7.4.33 moved to 7.4.33-18…cloudlinux.13.
If you only looked at the version number you saw 8.5.11 before and after, with no way of telling whether you were covered. You had to read the package revision.
The morning after
We updated the packages and checked the revisions on each server with one command:
rpm -qa 'ea-php*-php-cli' | sort
The rule was simple. Every line must end in .cloudlinux.1, and the 7.4 line in .cloudlinux.13. Anything else means that PHP still needs updating.
We left the mitigation file where it was. With the fix installed it works as a belt-and-braces measure, and it gets in the way of no site.
What we take away
- On a server with several PHP versions, the fix has to reach all of them, including the 7.4 that some sites still rely on.
- When the fix is late, a targeted mitigation plus a filter in front buys the hours you need.
- To know whether you are protected, look at the installed package rather than the announcement.


