Bali, Indonesia
Insights

Understanding PHP CVE-2026-109618 & CVE-2026-109619: Upstream Releases vs. Vendor Backports in Production Hosting

October 29, 2026
0:00
When PHP.net released patches for the critical vulnerabilities CVE-2026-109618 and CVE-2026-109619 (nicknamed PHP2Shell) on 21 October 2026, the first reaction in many engineering channels was to compare application runtimes against the new upstream version numbers:
  • PHP 8.2.35
  • PHP 8.3.36
  • PHP 8.4.27
  • PHP 8.5.12
However, as explained in our deep dive on CloudLinux backporting, treating the upstream version string as the only indicator of security creates real confusion in multi-tenant hosting environments. In shared hosting stacks, enterprise Linux distributions, and multi-version platforms (CloudLinux alt-php, cPanel ea-php, Remi RPMs, or extended support through TuxCare ELS), security fixes are routinely backported into older release branches. Understanding how the fix actually lands in production prevents unnecessary breaking changes and false alarms during security audits. One important limit: PHP 8.1 and older are end of life and receive no official fix. For those branches the only options are a vendor or extended-support backport, or migrating to a supported branch. PHP 8.2 is also close to the end of its security support, which ends on 31 December 2026, so patching now and planning a version migration are two separate tasks.
Upstream PHP fixes defects by releasing new patch versions (for example 8.4.26 to 8.4.27). Operating system packagers and hosting vendors must balance security against binary and API stability, so some of them copy the specific fix into the package version they already ship, while others now move to the new upstream number.
Deployment ChannelWhat php -v Typically DisplaysProtected?
Vanilla source build or official Docker imagePHP 8.4.27Yes
cPanel EasyApache 4 ea-php82 to ea-php85 (stock cPanel build)The new upstream version, for example PHP 8.4.27Yes
cPanel EasyApache 4 ea-php74, ea-php80, ea-php81 (end-of-life branches)The old number, for example PHP 8.1.34Yes, via backport (check the changelog)
CloudLinux-built ea-php84 (for example ea-php84-8.4.26-2.el8.cloudlinux.1)PHP 8.4.26Yes, via backport
CloudLinux alt-php85 (for example alt-php85-8.5.11-5)PHP 8.5.11Yes, via backport
Ubuntu / Debian APT (for example the 8.3.6 base on Ubuntu 24.04)The distro base versionYes, if the changelog or security notice lists the CVE
CloudLinux has since also published builds that carry the upstream numbers (for example alt-php82 8.2.35-1 up to alt-php85 8.5.12-1). On those newer builds php -v will show the fixed version, while earlier fixed builds keep their old number. Both are protected. If a vulnerability scanner or an engineer only looks at the version string from php -v, a fully patched backported build can look artificially vulnerable.
To verify that a vendor-managed PHP package is protected, inspect the package's RPM or DEB changelog instead of executing the binary.
Query the installed package metadata with rpm -q --changelog:
BASH
# CloudLinux alt-php (check the common package)
rpm -q --changelog alt-php85-common | grep -E "CVE-2026-(109618|109619)"

# cPanel EasyApache 4 / CloudLinux-built ea-php
rpm -q --changelog ea-php84-php-cli | grep -E "CVE-2026-(109618|109619)"

# System/native PHP
rpm -q --changelog php-common | grep -E "CVE-2026-(109618|109619)"
Any output means the fix is in the package. Be aware that where a distribution rebased its native PHP to a fixed upstream version (for example PHP 8.2 or 8.3 on some CloudLinux and AlmaLinux releases), the changelog may not name the CVE at all. In that case a grep returns nothing even on a fixed build, so check the version with rpm -q php-cli instead and confirm it is 8.2.35, 8.3.36 or later.
Examine the compressed Debian changelog, using your PHP version in the path:
BASH
zgrep -E "CVE-2026-109618|CVE-2026-109619" /usr/share/doc/php8.*-common/changelog.Debian.gz
Also check the distribution's security tracker (for Ubuntu, the USN pages) for the fixed package revision, because the exact revision differs per release.
A cPanel server can carry several independent PHP sets, and updating one does not update the others:
  1. EasyApache 4 PHP (ea-phpXX under /opt/cpanel)
  2. CloudLinux PHP Selector (alt-phpXX under /opt/alt), which accounts can select individually
  3. cPanel's internal PHP (cpanel-php), which runs WHM and cPanel themselves and updates with cPanel, not with EasyApache
BASH
dnf clean all && dnf upgrade 'ea-php*'
dnf clean all && dnf upgrade 'alt-php*'
Use plain update commands rather than security-only ones. CloudLinux notes that security-only updates may not list these packages because the advisory metadata was not published at first, and one report found that /scripts/upcp --security updated cPanel's internal PHP but not the EasyApache packages.
During fast patch rollouts, a web application firewall gives useful interim cover. Imunify360 delivered several ModSecurity ruleset updates for this disclosure: ruleset 8.83 on 21 October blocked the publicly circulating exploit request on ModSecurity, 8.84 added blocking for the public exploit tool and for upload-progress requests that do not come from the site's own pages (including on LiteSpeed, where 8.83 only logged), and later rulesets up to 8.88 added more variants. It is important to be precise about what these rules cover:
  • They target the session upload-progress path used by the publicly known exploit chain.
  • CloudLinux states that no rule blocks the out-of-memory path of CVE-2026-109618 yet, and describes the rules as a virtual patch that leaves the vulnerable PHP code in place.
  • They only apply when the Imunify360 WAF is enabled. ImunifyAV, or Imunify360 with the WAF disabled, gets no coverage from them.
  • The 8.84 cross-site upload rule can also block a legitimate upload form hosted on another domain, or a browser that strips the Referer header.
To check and refresh the ruleset on a cPanel server with Apache:
BASH
cat /etc/apache2/conf.d/modsec_vendor_configs/imunify360-full-apache/VERSION
imunify360-agent update --force modsec-rules
TEXT
Client HTTP Request
      |
      v
Reverse Proxy / Web Server (Nginx / Apache / LiteSpeed)
      |
      +-> Layer 1: Imunify360 / WAF (blocks known signature patterns)
      |      +- Interim filter: reduces exposure, does not cover every path
      |
      v
PHP Process Worker (PHP-FPM / lsphp / suPHP)
      |
      +-> Layer 2: Patched PHP binary (root fix)
             +- Complete remediation inside the runtime
  • WAF rules (compensating control): useful for shielding applications while updates are staged, but limited to known patterns and can be bypassed by variations.
  • Package updates (root remediation): the only complete fix.
PHP's own guidance recommends disabling session upload progress as an interim measure. On a CloudLinux server with PHP Selector, CloudLinux gives this route for all alt-php versions:
INI
; /etc/cl.selector/global_php.ini
session.upload_progress.enabled = Off
BASH
cagefsctl --setup-cl-selector
This reduces risk but does not replace the update, and it breaks session-based upload progress bars.
A common mistake is to run yum update, dnf upgrade or apt-get upgrade and assume the host is instantly protected. Updating a package replaces files on disk, such as /usr/bin/php and /usr/lib64/php/.... Long-running processes such as PHP-FPM pools, LiteSpeed lsphp workers and Apache MPM workers keep executing the old code from memory until they are restarted.
BASH
# cPanel / EasyApache environments
/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpm

# systemd-managed PHP-FPM (quote the glob so the shell does not expand it)
systemctl restart 'php*-fpm'
On LiteSpeed Web Server 5.3 and later, PHP runs in detached mode, so restarting the web server alone does not restart PHP. LiteSpeed documents two server-wide methods:
BASH
# Immediate: stops all PHP workers, new ones start right away
pkill lsphp

# Gradual: workers restart one by one as the server needs them
sudo touch /usr/local/lsws/admin/tmp/.lsphp_restart.txt
Note the leading dot in .lsphp_restart.txt. To restart only one account, touch .lsphp_restart.txt in that user's home directory. Avoid kill -9 on lsphp unless a worker is stuck, because it drops in-flight requests without cleanup. After restarting, confirm that the PHP processes actually started after the update, for example with ps -eo pid,lstart,cmd | grep php-fpm (use lsphp or httpd as needed).
  1. Patch the vendor packages for every active PHP set: ea-php, alt-php, distro packages, and cPanel's own internal PHP. Do not rely on a WAF instead of patching.
  2. Handle end-of-life branches deliberately: PHP 8.1 and older have no upstream fix, so use a vendor or extended-support backport, or migrate to a supported branch.
  3. Verify via package metadata: check rpm -q --changelog or zgrep rather than relying only on php -v, and fall back to the version number for rebased native packages.
  4. Restart the serving daemons, including detached lsphp on LiteSpeed, then confirm process start times.
  5. Keep WAF rules current as a secondary layer: with Imunify360, update to ruleset 8.88 or later, and remember it does not cover the CVE-2026-109618 out-of-memory path.
  6. Use the interim setting only as a stopgap if a server cannot be updated yet.