Update of 27 October: CISA lists PHP2Shell among exploited flaws
On 26 October 2026, CISA, the US cybersecurity agency, added both flaws (CVE-2026-109618 and CVE-2026-109619) to its Known Exploited Vulnerabilities (KEV) catalog. An entry appears there only once real-world exploitation is established: until now, that finding rested on watchTowr's network traps; it now comes from a public authority.
CISA set the due date at 29 October 2026, three days after the addition. That date binds only US federal agencies, but it gives the order of magnitude of the urgency a public body attaches to these flaws: a few days, not the next monthly maintenance window.
What the KEV catalog entry says
- Date added: 26 October 2026, for CVE-2026-109618 (“PHP Memory Corruption Vulnerability”) as well as for CVE-2026-109619 (“PHP Stale Internal Request-State Vulnerability”).
- Due date: 29 October 2026 for both.
- Required action: apply the vendor's mitigations in line with directive BOD 26-04 (Prioritizing Security Updates Based on Risk), or stop using the product if no mitigation is available.
- Forensic triage: the entry points to CISA's “Forensics Triage Requirements”. Patching is not enough: you also need to look for a compromise that happened before the fix.
- Ransomware: use in a ransomware campaign is listed as “unknown” so far.
What this changes for you
Nothing in the procedure: the fixed versions and the commands remain those of this article. What changes is the priority. Before 26 October you could still weigh “right now” against “at the next maintenance window”; that is no longer defensible. Internet-facing servers come first. And the question is no longer only “am I protected?” but “was I hit between 21 October and the moment I patched?”: the checklist further down has been extended accordingly.
PHP2Shell at a glance
PHP2Shell is not a flaw in WordPress, Laravel or a plugin: the PHP engine itself is at fault. Every PHP application that answers web requests is therefore affected, whatever its code looks like. The security advisory names PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.
Both flaws share the same underlying mechanism. When PHP abruptly aborts a request (exhausted memory, fatal error), it can leave behind an internal state that is only half initialised or that has already been freed. A subsequent request, handled by the same PHP process, then reuses that state: this is what opens the door to remote code execution.
Key takeaways
- CVE-2026-109618 — memory corruption when
memory_limitis exceeded: request data that was only partially initialised is later treated as valid during the cleanup phase. - CVE-2026-109619 — stale global state: state that belongs to one request survives after its memory has been freed and can be read by the next request on the same process.
- Score: 9.2 out of 10 under CVSS 4.0 for each one, with no authentication and no user interaction required.
- Patched versions: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. The project no longer publishes releases for 8.1 and the older branches.
- Exploitation: watchTowr reports exploitation attempts caught in its network honeypots as early as 21 October 2026.
- Scope: according to the NVD, CVE-2026-109619 affects every version since PHP 5.4.0, and CVE-2026-109618 every version since PHP 7.3.0.
Why these two flaws are so dangerous
Most web flaws require a specific form, a user account or a vulnerable plugin. PHP2Shell needs none of that: the most common trigger is the processing of a multipart/form-data upload with session upload progress tracking (session.upload_progress), a mechanism that PHP enables by default and that runs before the first byte of your application. A web application firewall living inside your code, a WordPress security plugin or a Laravel middleware therefore all come into play too late.
The second factor is the execution model itself. PHP-FPM and Apache reuse the same process for hundreds of successive requests: this is precisely what allows a booby-trapped request to contaminate the next one. According to Imperva, the published techniques range from crashing processes to reading arbitrary files through the OPcache cache, including leaking around 67 KB of process memory inside an oversized PHPSESSID cookie. That memory can contain database passwords or API keys.
Which version to install for your branch
Scroll the table
| PHP branch | Patched version | What to do |
|---|---|---|
| 8.5 | 8.5.12 | Update, then restart PHP |
| 8.4 | 8.4.27 | Update, then restart PHP |
| 8.3 | 8.3.36 | Update, then restart PHP |
| 8.2 | 8.2.35 | Update, then plan the migration to 8.3 or 8.4 |
| 8.1, 8.0, 7.4 | No official release | Your distribution's patched package, a source backport, or else migration |
| 7.3 and earlier, 5.x | No published fix | Migrate to a maintained branch |
Check whether your servers are exposed
Watch out for a classic trap: the version shown by php -v on the command line is not necessarily the one that serves your websites. A server can have several versions of PHP-FPM installed side by side, and each site can point to a different one. You therefore need to check the version that is actually served over the web, one site at a time.
Take an inventory of the PHP versions being served
List the installed versions
On Debian or Ubuntu:
dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\n' 'php*' | awk '$1=="ii"' | grep -E 'php[0-9.]+-(fpm|cli|common)|libapache2-mod-php'On RHEL, AlmaLinux or Rocky Linux:
rpm -qa 'php*' 'ea-php*' 'alt-php*' | sortFind the PHP processes that are running
systemctl list-units --type=service --state=running | grep -E 'php|apache2|httpd|lsws'Every active
phpX.Y-fpmservice is a version you need to check and to patch.Read the version served by a site
Drop a temporary file at the root of the site, query it, then delete it immediately afterwards:
echo '<?php echo PHP_VERSION, " ", PHP_SAPI;' > /var/www/monsite/v-check.php curl -s https://monsite.example/v-check.php rm /var/www/monsite/v-check.phpA result such as
8.3.36 fpm-fcgiindicates a patched version being served by PHP-FPM.Check your Docker containers
docker ps --format '{{.Names}}' | while read c; do echo "$c: $(docker exec "$c" php -r 'echo PHP_VERSION;' 2>/dev/null)"; doneA container without PHP shows nothing at all after its name.
Apply the fix
Linux distributions and extended support vendors received the fixes ahead of the public release. The patched package from your distribution therefore does not necessarily carry the number 8.3.36: Ubuntu 24.04, for example, patches its own version 8.3.6 in the package 8.3.6-0ubuntu0.24.04.13. Rely on your distribution's security advisory rather than on the PHP version number alone. In every case, a restart is essential: as long as the old processes keep running, it is the old code that answers your requests.
Update PHP for your environment
Debian and Ubuntu
sudo apt update sudo apt install --only-upgrade $(dpkg-query -W -f='${db:Status-Abbrev} ${Package}\n' 'php*' | awk '$1=="ii"{print $2}') sudo systemctl restart 'php*-fpm' sudo systemctl restart apache2 # if you use mod_phpIf your versions come from a third-party repository (for example the
ondrej/phpPPA), check that the version installed after the update really is one of the patched versions.RHEL, AlmaLinux, Rocky Linux
sudo dnf upgrade 'php*' sudo systemctl restart php-fpm sudo systemctl restart httpdAlmaLinux published its patched packages on 21 October 2026. The community Remi repository, for its part, published versions 8.2.35, 8.3.36, 8.4.27 and 8.5.12 on 22 October 2026: if you depend on it, check the installed version afterwards.
cPanel server (EasyApache 4 or CloudLinux)
sudo dnf upgrade 'ea-php*' 'alt-php*' /scripts/restartsrv_apache_php_fpm /scripts/restartsrv_httpdOn an older server, replace
dnfwithyum. Then check each version in WHM › MultiPHP Manager: any account set to 7.3 or older, with no fix from cPanel, must be switched over to a maintained version; 7.4, 8.0 and 8.1 are fixed by backport but end-of-life (see below).Docker containers
docker compose pull docker compose up -d --force-recreate docker compose exec app php -r 'echo PHP_VERSION;'If your
Dockerfilestarts from aphp:8.3-fpmimage, rebuild the image withdocker compose build --pull: without--pull, Docker reuses the old base image that it has in its cache.Check the result
Run the check from the previous step again on every site. The fix is only in place if the version served over the web is patched, not merely the version installed on disk.
cPanel and EasyApache 4: an unchanged version number does not mean “not fixed”
The EasyApache 4 (EA4) changelog of 21 October 2026, version 25.91, covers seven PHP branches. For the maintained branches the number goes up: ea-php82 moves from 8.2.34 to 8.2.35, ea-php83 from 8.3.35 to 8.3.36, ea-php84 from 8.4.26 to 8.4.27 and ea-php85 from 8.5.11 to 8.5.12. For ea-php74, ea-php80 and ea-php81, which cPanel has nonetheless declared end-of-life, the fix is backported: the PHP version number stays put and only the package revision changes.
That is the trap: php -v then shows an “old” version even though the code is fixed, and an old version whose changelog does not cite the two CVEs remains vulnerable. Only reading the package changelog settles it. A version 25.92, released the same day, also rebuilt the meta-packages so that their changelog mentions the backport too.
EasyApache 4 25.91: what cPanel published, package by package
Scroll the table
| Package | What changed | How to check |
|---|---|---|
| ea-php85 | 8.5.11 to 8.5.12 | Package version |
| ea-php84 | 8.4.26 to 8.4.27 | Package version |
| ea-php83 | 8.3.35 to 8.3.36 | Package version |
| ea-php82 | 8.2.34 to 8.2.35 | Package version |
| ea-php81, ea-php80, ea-php74 | Fix backported, PHP number unchanged | RPM changelog: look for both CVEs |
| ea-php73 and older | No entry in the 25.91 changelog | Migrate, or see CloudLinux below |
Check that a backported package really is fixed
Read the EasyApache package changelog
rpm -qa 'ea-php*-php-cli' rpm -q --changelog ea-php81-php-cli | grep -E 'CVE-2026-(109618|109619)'The first command lists the installed branches; replay the second for each one. A line citing the CVEs confirms the fix. No line at all: the package is not fixed, whatever its version number.
Do the same for alt-php packages
On a CloudLinux server, the versions chosen in Select PHP Version are
alt-phppackages:rpm -q --changelog alt-php85-common | grep -E 'CVE-2026-(109618|109619)'Go through the accounts one by one
In WHM › MultiPHP Manager, every domain must point to a branch whose package passed this check. The 7.4, 8.0 and 8.1 branches fixed by backport remain end-of-life: they are a holding position, not a destination.
CloudLinux: the same fix, one to two days later depending on the product
CloudLinux publishes its own packages, and they do not arrive at the same time as cPanel's. According to its bulletin, the ea-php packages (5.2 to 8.5) reached stable on 21 October, the alt-php ones on 22 October for CloudLinux 7, 8 and 9, the system's native PHP late on 22 October (UTC), and the packages numbered like PHP.net on 23 October.
These too are backports: ea-php84 there stays, for instance, at 8.4.26 with a CloudLinux-specific revision (8.4.26-2) while being fixed. Two points of caution: on 21 October, alt-php packages announced as released were in fact in the TuxCare ELS repository and not in CloudLinux's own; and the advice to disable the php-els repository, given on 22 October, was corrected on the evening of the 23rd: leave it enabled. Finally, Imunify360 published its WAF rules on 21 October (ruleset 8.83), and version 8.88 has been stable since the 23rd: they block known vectors and do not replace the update.
cPanel/WHM's internal PHP and Roundcube: another PHP to update
MultiPHP and EasyApache govern the PHP of your sites. The cPanel and WHM interfaces and the Roundcube webmail run instead on an internal PHP shipped with cPanel itself, which choosing a version in MultiPHP Manager does not touch. On 21 October 2026, cPanel published a security update for this internal PHP, stating that it “affects PHP in cPanel interfaces, including Roundcube webmail”.
It delivers PHP 8.4.27 in cPanel & WHM 138.0.18, 136.0.50 and 134.0.66, and backported fixes for PHP 8.1.34 in version 110.0.153. These interfaces are open to your customers' logins, so often reachable from the internet: they are prime targets. Read your version with /usr/local/cpanel/cpanel -V (or in the WHM banner) and compare it with these numbers. If your release series is not listed, do not assume it is fixed: check cPanel's release notes and move to a series that is.
After patching, still turn off upload progress tracking
On 23 October 2026, PHP published a supplementary informational advisory: it recommends keeping session.upload_progress.enabled=0 until the next regular bugfix release, to guard against a code-execution vector it considers unlikely. It targets applications that set session.serialize_handler to php_binary or php_serialize, then switch it back to php at runtime with ini_set() before session_start(). PHP announces a full advisory for CVE-2026-115560 with the next release. The setting only concerns the file upload progress bar.
If you cannot update right away
The official PHP advisory suggests settings that reduce exposure without making the installation safe. They are there to buy you a few hours, not to replace the fix. They must be set in php.ini, in the PHP-FPM pool or in the web server configuration, never through ini_set() or a .user.ini file: those are read too late, after the request has already been parsed.
Against CVE-2026-109619, disable upload progress tracking. On PHP 8.5, also disable fatal error backtraces:
; in the FPM pool, for example /etc/php/8.3/fpm/pool.d/www.conf
php_admin_flag[session.upload_progress.enabled] = off
; PHP 8.5 only:
php_admin_flag[fatal_error_backtraces] = offAgainst CVE-2026-109618, the advisory recommends memory_limit = -1 enforced through php_admin_value, so that no application can redefine it, together with a bounded request size (post_max_size = 8M, or 32M if you need file uploads). In return, memory has to be capped somewhere else, with a container or cgroup limit. Do not use RLIMIT_AS or RLIMIT_DATA: they are exactly what causes the vulnerable allocation failure.
Then restart all PHP processes so that the settings take effect.
Add a barrier in front of PHP
Cap the size of requests at the web server level, before they ever reach PHP: client_max_body_size 8m; in nginx, LimitRequestBody 8388608 in Apache. If your site sits behind Cloudflare in proxied mode, WAF rules targeting the known PHP2Shell vectors have been rolled out to every account, the free plan included. These are safety nets only: nothing but the PHP update actually closes the flaw.
Look for traces of exploitation
The published attempts leave characteristic traces behind: PHP processes that crash, bursts of out-of-memory errors and multipart uploads that are abnormally large. If your server was exposed before you updated it, take ten minutes to check.
Checks to run after applying the fix
Look for killed PHP-FPM processes
sudo grep -E 'exited on signal (11|6)' /var/log/php*-fpm.log | tail -20A series of processes killed by signal 11 (SIGSEGV) since 21 October is a warning sign.
Look for memory limit overruns
sudo grep -rh 'Allowed memory size' /var/log/php* /var/log/nginx /var/log/apache2 2>/dev/null | tail -20Spot recently created PHP files
sudo find /var/www /home -name '*.php' -newermt '2026-10-20' -not -path '*/vendor/*' -not -path '*/cache/*' -lsAn unknown file with a generic name, in an upload folder or in
/tmp, should be examined before you delete anything.When in doubt, treat the server as compromised
Isolate the machine, keep a copy of the logs, then rotate the database passwords, the API keys and the secrets stored in
.envfiles: a memory leak may have exposed them without leaving any other trace behind.
More signs to look for, according to primary sources
- Unusually large or deeply nested
multipartrequests in the web server logs (watchTowr). - PHP processes that crash or hit their memory limit (watchTowr).
- Files written to web roots and outbound connections from PHP processes that you cannot explain (watchTowr).
- New web shells, unexpected cron jobs and recently created accounts tied to PHP processes (watchTowr).
- Preserve before you clean up: PHP and web server logs, configuration snapshots and suspicious files, before changing anything (watchTowr). CISA also attaches forensic triage requirements to its KEV entry.
- No numeric indicator is published: as of 27 October, neither watchTowr, nor PHP, nor the GitHub advisory for CVE-2026-109618 gives an IP address, a hash, a file name or a request signature. Be wary of unsourced indicator lists: the absence of an address in your logs proves nothing.
On shared hosting
On shared hosting, you are not the one who updates PHP: the hosting provider maintains the versions on offer. Your part of the job is to check that your site uses a branch that still receives fixes. In cPanel, the version selection tool (MultiPHP Manager, or Select PHP Version on a CloudLinux server) shows the active version for each domain. If your site still runs on 7.4, 8.0 or 8.1, those branches no longer receive official PHP releases: switch to 8.3 or 8.4 after testing your site, following our PHP migration checklist.
The official documentation
The technical details and the workaround settings are published in the PHP security advisory and in the GitHub advisories GHSA-w8hw-w9fx-j79w (CVE-2026-109618) and GHSA-6wmf-4rv5-p3rp (CVE-2026-109619). For distribution packages, see the Ubuntu announcement and the AlmaLinux one. For the follow-up: CISA's KEV catalog, the EasyApache 4 changelog, the cPanel & WHM release notes, CloudLinux's bulletin and watchTowr's FAQ.