A hot CVE is a portfolio problem, not a patch command

Bright editorial illustration with the headline A hot CVE is a portfolio problem, not a patch command, and a row of four glossy glass cards: Inventory, know every site; Mitigate, buy time safely; Verify, check what’s running; Report, say what’s confirmed.

On 20 October, the PHP security team gave a day’s notice of a critical release. On 21 October it shipped PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, fixing two remote code execution vulnerabilities, both rated CVSS v4.0 9.2, which security write-ups have taken to calling PHP2Shell. Two days later, it published an informational advisory about a third, much narrower issue.

The remediation is clear: install a fixed PHP build. If you look after one server, that might be the whole job. If you’re responsible for a portfolio of sites, across different hosts, PHP versions and owners, the update is the easy part. Knowing where it needs to happen, and proving it has, is harder.

In short: PHP2Shell (CVE-2026-109618 and CVE-2026-109619) affects PHP installations serving web requests, and the fix is to update or apply your vendor’s patched build. Mitigations reduce specific attack paths while you wait, but they leave a site partially mitigated, not patched. On managed hosting, the version number may not tell you whether you’re patched, because fixes are often backported, so until you’ve confirmed the build, treat a site as not yet verified. Treat it as an inventory, verification and communication exercise, not just a one-line command.

What happened

According to PHP’s advisory and CERT-EU, the two vulnerabilities are:

  • CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): out-of-memory handling can interrupt PHP while internal request data, such as a file upload being parsed, is only partially initialised. Cleanup may then treat that data as valid.
  • CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): internal state from one request can survive after its memory is freed, and a later request on the same worker may use it.

PHP says installations serving web requests are at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. It considers mod_php the highest risk, with a demonstrated exploit in which an unauthenticated request triggers the attack before any application code runs.

On exploitation, the picture moved quickly. Sophos initially reported a successful exploitation in a customer environment. In its 22 October, 21:21 UTC correction, it said its customer telemetry showed scanning and a small number of failed exploitation attempts, and that as of that update it had no evidence of a successful compromise. That’s one vendor’s telemetry at one point in time, not proof that nobody has been compromised. A public proof of concept exists.

Then, on 23 October, PHP published an informational advisory for CVE-2026-115560. It describes an “unlikely” RCE path that needs a specific combination of session configuration and application code. It isn’t fixed by the 21 October releases. PHP will publish full details with the next regular release. PHP says disabling session upload progress fully protects against this specific vector while awaiting the next release. That is a configuration mitigation, rather than a patched build, and does not replace patching the original two vulnerabilities.

Step one: know what you actually run

The first question isn’t “have we patched?”, it’s “what do we have?” For each site, that probably means:

  • the PHP version and the build or package that provides it
  • how PHP is served: FPM, mod_php, LiteSpeed’s lsphp or something else
  • who hosts it and who is allowed to change it: your team, the client or a managed host
  • who needs to be told
  • the accountable owner for getting it fixed
  • the next action, and who’s waiting on whom
  • when its status was last verified, and how

For PHP 8.1 and older, confirm a vendor-supported backport or plan an upgrade to a supported branch.

If that list doesn’t already exist, a hot CVE is an expensive time to start it. It’s also the point at which it pays for itself.

Step two: patch promptly; mitigate while waiting

Updating is the only complete fix. If you can’t update straight away, PHP and CERT-EU list mitigations for CVE-2026-109619, including setting session.upload_progress.enabled=0 and, on PHP 8.5, fatal_error_backtraces=0, then restarting every worker. Two caveats in the advisory matter here:

  • The settings must be applied where they take effect before request parsing: php.ini, an FPM pool or server configuration. PHP says not to rely on ini_set() or .user.ini.
  • Disabling session upload progress blocks the confirmed session paths; disabling fatal-error backtraces on PHP 8.5 blocks the confirmed backtrace path. Neither covers every variant.

These settings reduce specific attack paths for CVE-2026-109619; they do not mitigate CVE-2026-109618. If an immediate update is impossible, follow PHP’s separate guidance for that issue.

For the fix, hosting vendors moved quickly. cPanel published patched EasyApache 4 builds, and, according to CloudLinux’s incident page, the release of fixed alt-php packages to its stable repositories was complete by 22 October, 00:07 UTC. I haven’t seen equivalent statements from every managed WordPress host, so for those sites, ask.

Step three: verify. The version number can mislead

This is the part most likely to catch a team out. CloudLinux’s guidance is explicit: many fixed builds are backports, so the PHP version stays below the php.net release. A server reporting 8.5.11 may be patched (alt-php85 8.5.11-5) or not. For a backported build, check the vendor’s package release and security changelog; the PHP version alone may not establish patch status.

Two more checks follow from the same guidance:

  • Check what the web server runs, not just the command line. The CLI binary and the handler serving requests can be different builds with different settings.
  • Check that workers restarted. CloudLinux notes that on LiteSpeed, restarting the web server doesn’t always stop running lsphp processes. A patched package on disk doesn’t help a worker that started before it was installed.

Step four: communicate what’s confirmed

With clients and stakeholders, the useful update is short and precise: which sites are confirmed patched, which are mitigated and awaiting a vendor build, which are waiting on someone else, and when you’ll next report. The Sophos correction is a good reminder to separate what’s confirmed from what’s reported. And CVE-2026-115560 is a reminder that there may be a second wave, so it’s worth keeping the inventory from step one up to date rather than closing the ticket.

What I checked on my own site

On Wednesday 21 October, I checked my own site with a temporary file that reported what the web server sees, and deleted it straight afterwards. It showed PHP 8.5.11 under LiteSpeed, with session.upload_progress.enabled already off. That confirmed one mitigation was active, but left the patch status unresolved: CloudLinux’s backported fixes keep the old version number, and disabling session upload progress doesn’t cover every attack path.

I checked again on Saturday 24 October. The web server now reported PHP 8.5.12, the upstream release with the fix, and my check reported binaries built on 22 October. My host had rolled out the fixed build on Thursday 22 October, the day after PHP’s release. The setting was still off. My check showed it in the host’s server-level configuration (php.ini plus CloudLinux’s alt_php.ini), not set via .user.ini or ini_set(). Because the version came from the running web process rather than the command line, this confirmed that the worker serving my check was running PHP 8.5.12. I’d still need host confirmation to establish that every worker had been recycled. The package tools aren’t available to my cPanel account, so I couldn’t read the package changelog myself; the reported version and build date are my evidence. My check read fatal_error_backtraces as 1, so the extra PHP 8.5 mitigation isn’t applied, which matters less on a fixed release.

The lesson for me: one check is a snapshot. Check again after your vendor’s release window, and check what the web server reports.

Before you close the ticket

For anyone with a portfolio of PHP sites, these are the questions I’d want answered this week:

  1. Do we have a current list of every site, its PHP build and its handler?
  2. Have we confirmed a fixed upstream release or a vendor build documented as containing both fixes?
  3. Have the workers restarted since the patch?
  4. Where we’re relying on a mitigation, is it set somewhere PHP says it takes effect?
  5. Have the people who own each site heard from us, with which sites are patched, which are partially mitigated and which are not yet verified?

Installing the update is only one part of the job. The rest is engineering management.

Sources and further reading

Related reading