At 21:33 CEST on Tuesday, 20 October, PHP pre-announced two critical vulnerabilities, with a fix due the next afternoon. A hosting provider running cPanel servers read that notice and saw the problem straight away. The fix would cover PHP 8.2 to 8.5 only. The sites hosted on their servers run every PHP version from 5.2 up, because each site stays on the version its application was built for.

PHP’s release would fix four branches. Those servers run 16.

The standard PHP security advice is to run a supported version and wait for your vendor. By the time TechCrunch called the week the “PHP-ocalypse“, that advice had a visible gap: somebody has to own the branches upstream has dropped. During PHP2Shell (CVE-2026-109618 and CVE-2026-109619), CloudLinux did.

CloudLinux shipped fixed ea-php (cPanel’s EasyApache PHP builds) and alt-php (CloudLinux’s PHP builds behind PHP Selector) for all 16 branches from 5.2 to 8.5, plus native PHP packages for every affected version.

The Imunify360 web application firewall (WAF) had been blocking the public exploit since the morning of 21 October, hours before PHP’s fix.

 

What PHP2Shell is (CVE-2026-109618 and CVE-2026-109619)

PHP2Shell is two remote code execution flaws in PHP itself, both scored 9.2 on CVSS v4.0 and neither needing a login.

In CVE-2026-109618, PHP runs out of memory mid-request, and cleanup treats the half-built data as valid. In CVE-2026-109619, one request’s state survives after its memory is freed, and the next request on the same worker can use it.

PHP2Shell sits below the application. PHP reads the request before the site’s code runs, so any PHP script on the server will do, whether or not it handles forms. The site’s own PHP application security never gets a say because the flaw triggers before that code starts.

PHP lists every web-facing setup as affected (PHP-FPM, mod_php, php-cgi, FrankenPHP, and LiteSpeed) and rates the risk highest on Apache with mod_php.

The exploit toolkit came first.

Details leaked on 20 October, and a public tool, also called PHP2Shell, went live before the fix. It abuses session upload progress, which is on by default. Some requests carry a User-Agent starting php2shell-, but about two-thirds of those carrying the tool’s multipart boundary used a different one.

PHP branchWhat the PHP project shipped on 21 OctoberFixed version
8.5Release8.5.12
8.4Release8.4.27
8.3Release8.3.36
8.2Release8.2.35
8.1, 8.0, 7.4Minimal source backports in the advisory; no releaseNo php.net release
7.3 and olderNothingNo php.net release

Sources: PHP security advisory; the CloudLinux advisory for CVE-2026-109618 and CVE-2026-109619.

 

Why a hosting server cannot just upgrade

The nine guides that ranked for PHP security on 26 October all end on the same instruction: run a supported version. On a shared hosting server, that advice reaches the wrong person.

A shared server holds hundreds of accounts, each pinned to the PHP version its application was written for. A shop module that breaks on PHP 8 doesn’t care about php.net’s calendar.

That is why PHP Selector, which lets each account pick its PHP version, supports PHP 5.2 to 8.5.

The provider can’t force everyone onto PHP 8.4. Forced upgrades break sites, and broken sites come back as tickets and churn. Providers already pay for it: 53% name outdated or vulnerable software as their top security challenge, and security incidents take 35% of their support time.

So when PHP says “upgrade,” a hosting provider hears a different question. Who patches the version my customer is stuck on, and how fast?

 

Inside the response: 20 to 23 October

Imunify360 telemetry recorded the first request from the public exploit tool at 01:33 CEST on 21 October, four hours after PHP’s notice and 14 hours before its fix. From about 10:20, scanning scaled up sharply, and by 13:00 requests naming the PHP2Shell exploit tool had reached more than 3,600 servers in the Imunify360 network.

The WAF got there first. At 11:10, Imunify360 ruleset 8.83 reached stable and blocked the known exploit request on ModSecurity and Coraza, about 4.5 hours before PHP’s fix. The rule matches how the request is built, not the tool’s name, so requests that hid the name were blocked too.

Around noon, an IP reputation rule began sending exploiting addresses to a CAPTCHA on every protected server. Over three days, five ruleset releases extended blocking to LiteSpeed, caught renamed variants of the tool, added a logging rule for malformed session cookies, and blocked a serialized object in the upload progress field. The Imunify360 coverage table by web server shows what each setup had, and when.

From 21 to 26 October, the dedicated PHP2Shell rules matched about 9 million times. Blocking rules accounted for about 6.25 million of those matches, and 99% of them were on requests the WAF denied. The public tool’s fingerprint appeared in 62% of all matches.

PHP released 8.2.35, 8.3.36, 8.4.27, and 8.5.12 at 15:45. That left four released fixes to package, source backports for 7.4, 8.0, and 8.1, and nothing for the nine branches from 5.2 to 7.3. The build team paused other builds and wrote the missing fixes itself.

The result covered every branch a hosting server runs. Fixed ea-php shipped for all 16 branches, ea-php52 to ea-php85, on CloudLinux 7 to 10. Fixed alt-php shipped for all 16 branches on CloudLinux 7, 8, and 9. Native PHP packages followed for every affected version, and TuxCare Endless Lifecycle Support (ELS) released packages for alt-php, distribution PHP, and PHP for Windows. Each arrived as a normal package update.

What shipped for PHP2Shell

BuildBranches fixedWhere
ea-php (cPanel EasyApache)16: ea-php52 to ea-php85CloudLinux 7, 8, 9, and 10
alt-php (PHP Selector)16: 5.2 to 8.5CloudLinux 7, 8, and 9
Native PHP (distribution packages)Every affected versionCloudLinux 7 to 10
TuxCare ELS for PHPalt-php, distribution PHP, and PHP for WindowsELS repositories
php.net-numbered rebuildsalt-php and ea-php 8.2 to 8.5alt-php on CloudLinux 7, 8, and 9; ea-php on CloudLinux 7 to 10 and CloudLinux for Ubuntu 22.04

Source: the CloudLinux advisory, which lists every fixed package and version.

Timeline: PHP2Shell response, 20 to 23 October 2026 (CEST)

When (CEST)LaneEvent
20 Oct 21:33Disclosure and attackPHP pre-announcement
21 Oct 01:33Disclosure and attackFirst exploit request
21 Oct 10:20Disclosure and attackMass scanning starts
21 Oct 11:10Imunify360 WAFRuleset 8.83 blocks the known exploit request
21 Oct 12:00Imunify360 WAFIP reputation CAPTCHA
21 Oct 15:18Imunify360 WAFRuleset 8.84 adds LiteSpeed
21 Oct 15:45ReferencePHP releases its fix (8.2.35, 8.3.36, 8.4.27, 8.5.12)
21 Oct 19:17Imunify360 WAFRuleset 8.85: renamed variants
21 Oct 22:55Fixed PHP packagesea-php 5.2 to 8.5
22 Oct 02:07Fixed PHP packagesalt-php in stable
22 Oct 07:50Imunify360 WAFRuleset 8.86: more variants
22 Oct 21:50Fixed PHP packagesNative PHP, all versions
23 Oct 02:08Fixed PHP packagesalt-php with php.net version numbers
23 Oct 10:40Imunify360 WAFRuleset 8.88: serialized object

Everything in the WAF lane before 15:45 on 21 October was in place before PHP released its fix.

Not all of it went well. The first fixed alt-php and ea-php packages kept their old version numbers, so scanners flagged patched servers as vulnerable. On 21 October, we announced fixed alt-php for CloudLinux while it sat only in the TuxCare ELS repository; the correction took about three hours (customers hit the gap before the correction went out).

Servers with the WAF off, in log-only mode, or running ImunifyAV, Imunify’s malware scanner, had no WAF protection. As of 26 October, the blocking rules still target the upload progress path that the public exploit uses. The out-of-memory path of CVE-2026-109618 is covered by logging rules that measure its likely request shapes, but not yet by a blocking rule.

A change is already in place. alt-php and ea-php for 8.2 to 8.5 were rebuilt with php.net version numbers on 23 October.

The status page incident keeps the full record.

 

Who patches PHP after PHP stops

Three layers patch PHP, and each stops somewhere different.

  • The PHP project releases fixes for supported branches, this time 8.2 to 8.5, and publishes source backports without releases for a few older ones.
  • Linux distributions ship fixes for the PHP versions in their own repositories, on their own schedule.
  • The third layer is a vendor that owns the branch: it writes, builds, and tests the fix for versions upstream won’t touch, and ships it through the server’s package manager.

The OWASP PHP Configuration Cheat Sheet makes a fair point: extended support from a distribution or vendor does not make a branch “supported.” We agree. A backported fix leaves PHP 7.4 outside php.net’s policy. It closes the CVE on the exact version the site runs, so the upgrade can happen on the customer’s schedule instead of the CVE’s.

HardenedPHP, the backported patch set included in CloudLinux and Imunify360, carries security fixes to end-of-life PHP 5.x, 7.x, and 8.x as drop-in packages that work with PHP Selector. If you already run CloudLinux or Imunify360, it covers your end-of-life PHP today.

ELS for PHP is the same technology sold standalone for the rest of the fleet, on 20 platforms: EL6 to EL10, Ubuntu 16.04 to 26.04, Debian 10 to 13, Alpine 3.23 and 3.24, and Windows Server 2019, 2022, and 2025.

PHP’s release fixed four branches; we shipped fixes for 16.

 

The PHP lifecycle, and what expires next

PHP 8.2 reaches end of life on 31 December 2026, nine weeks after this post.

After that, the next PHP CVE gets no php.net release for 8.2, whatever its score. Since PHP 8.1, each branch gets about two years of active support and two more years of security-only fixes, ending on 31 December.

PHP branchSecurity support ends (php.net)Status on 26 Oct 2026Who patches it after that
8.531 Dec 2029SupportedPHP project
8.431 Dec 2028SupportedPHP project
8.331 Dec 2027Security fixes onlyPHP project
8.231 Dec 2026Security fixes only; ends in nine weeksPHP project until 31 Dec, then distributions for their own packages and HardenedPHP / ELS for PHP
8.131 Dec 2025End of lifeDistributions for their own packages; HardenedPHP / ELS for PHP
8.026 Nov 2023End of lifeSame
7.428 Nov 2022End of lifeSame
7.36 Dec 2021End of lifeSame
5.631 Dec 2018End of lifeSame (alt-php and ea-php patch back to 5.2)

Sources: php.net supported versions and end-of-life branches, read 26 October 2026.

 

PHP security practices that hold up on a shared server

Most PHP security best practices still apply on a shared server.

What changes is who owns each one. The provider sets some fleet-wide in php.ini, while others live in the customer’s code.

PHP2Shell is a useful test: almost none of them stopped it.

Practice or PHP configurationWhat it stopsAgainst PHP2ShellWho owns it on a shared server
Patched PHP buildThe CVE itselfThe only complete fixProvider installs it; whoever owns the branch builds it
WAF in blocking modeKnown exploit requestsBlocked the public exploit’s upload progress path from ruleset 8.83; no rule for the out-of-memory path of 109618Provider; log-only mode protects nothing
session.upload_progress.enabled = 0The upload progress featurePHP’s interim measure for 109619. Since 23 October, PHP advises keeping it off until its next regular release because of CVE-2026-115560Provider, in php.ini or the PHP-FPM pool; not ini_set() or .user.ini
Memory and request-size limits (memory_limit, post_max_size, max_file_uploads)Oversized requests and uploadsPHP’s advisory gives settings for the out-of-memory flaw; apply them as it describesProvider
Per-account isolation (CageFS, a virtualized filesystem for each account)A compromise spreading between accountsContains it; doesn’t prevent itProvider
disable_functions (exec, system, shell_exec, passthru)Shell commands from injected PHPNo: the flaws trigger while PHP reads the requestProvider, per PHP version
open_basedirScripts reading outside allowed pathsNo, same reasonProvider, per account
allow_url_include = Off, allow_url_fopenRemote file inclusion (RFI)NoProvider
expose_php = OffVersion disclosure in headersNo: scanners sprayed every serverProvider
display_errors = Off, log_errors = OnStack traces shown to visitorsNoProvider default; site owner can override
session.cookie_httponly, session.cookie_secure, session.use_strict_modeSession hijacking and fixationNoProvider default; site owner can tighten
Prepared statementsSQL injectionNoSite owner
Output escaping and Content Security Policy (CSP)Cross-site scripting (XSS)NoSite owner
CSRF tokensCross-site request forgeryNoSite owner

Full directive reference: the OWASP PHP Configuration Cheat Sheet. Vulnerability classes: TuxCare’s guide to common PHP vulnerabilities.

How to test whether a server is fixed

Run this PHP security test for every PHP version the server serves.

Step 1. Check each build’s changelog for the CVE IDs (commands below; repeat for each installed alt-php and ea-php version, and use dpkg -l for ea-php on Ubuntu). Rebased native packages name no CVE, so check for 8.2.35, 8.3.36, or later instead. If fixed packages don’t appear, confirm cloudlinux-release is current.

rpm -q --changelog alt-php85-common | grep -E 'CVE-2026-(109618|109619)'
rpm -q --changelog ea-php84-php-cli | grep -E 'CVE-2026-(109618|109619)'
dpkg -l ea-php84-php-cli   # CloudLinux for Ubuntu: compare the version with the fixed list
rpm -q --changelog php-cli | grep -E 'CVE-2026-(109618|109619)'
rpm -q php-cli   # rebased native builds: 8.2.35 or later on 8.2, 8.3.36 or later on 8.3
rpm -q cloudlinux-release   # if the update fails or finds nothing to install

Step 2. Restart PHP-FPM or the web server after updating. A patched package doesn’t fix workers that are already running. For ea-php on cPanel:

/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpm

Step 3. Keep session upload progress off. Set session.upload_progress.enabled = 0 in php.ini or the PHP-FPM pool (php_admin_value), where accounts can’t override it; a .user.ini can switch it back on. PHP first gave this as an interim measure for PHP2Shell. On 23 October, it extended the advice to patched servers: a third session flaw, CVE-2026-115560, will be fixed only in PHP’s next regular release. It needs an unusual setup, an application that switches session.serialize_handler to php at runtime, so applications that never do that can keep the feature on. Restart PHP, confirm the effective value on a phpinfo() page for each version, and remove the page afterwards; php -i shows command-line settings, which can differ. PHP’s advisory gives separate memory and request-size settings for the out-of-memory flaw.

Step 4. Confirm the Imunify360 WAF is on, in blocking mode, and on ruleset 8.88 or later. The path below is for cPanel with Apache; other panels and LiteSpeed use different paths. Run as root:

cat /etc/apache2/conf.d/modsec_vendor_configs/imunify360-full-apache/VERSION
imunify360-agent update --force modsec-rules   # if older than 8.88, then check again

Step 5. Check whether exploit requests reached PHP before the server was patched. Default access logs record the User-Agent but not the multipart boundary or form fields, so they catch only requests that name the tool. On Imunify360, the Incidents list shows WAF matches by rule (77830995, 77318849, 77866818, 77236259, and later PHP2Shell rules), and the ModSecurity audit log, where enabled, may include the request headers of flagged requests. A request the WAF blocked never reached PHP. Others did: anything before the rules arrived (11:10 CEST on 21 October, or 15:18 on LiteSpeed), anything on servers with the WAF off or in log-only mode, and variants the rules don’t match. Those leave no trace in the Incidents list, so don’t wait for a hit. For every account that ran unpatched PHP, keep the logs first, run a malware scan for web shells, look for PHP files written to website folders on or after 20 October, and check for unexpected processes running as the account’s user (the web server user with mod_php). Confirm what a file is before you delete it.

General hygiene, beyond PHP2Shell: run composer audit on Composer-based applications, because a PHP security audit of the interpreter says nothing about the libraries above it.

IndicatorValue
User-AgentStarts with php2shell- (for example php2shell-109618, php2shell-scan/109618); some security checkers use it too
Multipart boundaryB7kQpoc618, B7kQpoc619; renamed boundaries containing php2shell or nphp618; boundaries starting p2s, or lfi plus 16 hex characters
Request shapeMultipart POST with a PHP_SESSION_UPLOAD_PROGRESS field, a session ID, a file, and text fields holding binary data, usually with no Referer

 

The Internet doesn’t run only PHP 8.xx

Back to the ops lead at the hosting provider reading PHP’s notice on Tuesday night.

By Friday, every branch on those servers had a fixed package, and the four php.net still-supported versions carried version numbers a scanner could read.

The next deadline is 31 December, when 8.2 leaves the supported list.

Check your accounts’ branches against the lifecycle table. For anything past end of life, the patched build is HardenedPHP on CloudLinux and Imunify360, or ELS for PHP everywhere else.

 

FAQ

Is it safe to run PHP 7.4 in 2026?

Not on a stock build. PHP 7.4 reached end of life in November 2022, and for PHP2Shell, php.net shipped only a source backport. Run it on a patched build, such as HardenedPHP or ELS for PHP, while the upgrade is planned.

Who provides security patches for PHP after end of life?

Distributions patch the PHP versions they ship, and vendors that own a branch patch the rest. CloudLinux covers 16 branches, 5.2 to 8.5: HardenedPHP on CloudLinux and Imunify360, ELS for PHP elsewhere.

Does disable_functions or open_basedir protect against PHP2Shell?

No. Both act on running scripts, and PHP2Shell triggers while PHP is still reading the request. Turning off session upload progress narrows one path; only a patched build closes both CVEs.

How do I run a PHP security test on my server?

For PHP2Shell: check each PHP version’s changelog or version number against the fixed list, restart PHP, confirm the WAF ruleset is 8.88 or later, and check WAF incidents and access logs for the tool’s indicators. For applications, run composer audit on their dependencies.

What is the difference between HardenedPHP and ELS for PHP?

Same technology, different packaging. HardenedPHP comes included with CloudLinux and Imunify360. ELS for PHP is the standalone product for other distributions and servers without Imunify360, on 20 platforms including Ubuntu, Debian, Alpine, and Windows Server.