WritingPHP

PHP RCE CVE-2026-109618 and CVE-2026-109619: Patch Now

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix two critical RCE bugs that are already under attack. What they are, who is affected and how to patch.

Mirza Saikat Ahmmed · 9 min read

PHPSecurityBackendDevOps

On 21 October 2026 the PHP project released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical vulnerabilities: CVE-2026-109618 and CVE-2026-109619. Both can lead to remote code execution (RCE), both are rated 9.2 on CVSS v4.0, and both sit inside the PHP interpreter itself, so no application code of yours has to be buggy for you to be affected.

The bugs were nicknamed PHP2Shell. Details leaked a day before the coordinated disclosure, and attackers started probing right away. This post explains what is known, how to patch, and what the official interim mitigations do and do not cover.

The short version

  • Update PHP now. The PHP team says: "There are no complete mitigations, updating is the only safe choice."
  • Fixed versions: 8.5.12, 8.4.27, 8.3.36, 8.2.35.
  • PHP 8.1 and older get no official fix. The PHP security team published minimal source backports for 7.4, 8.0 and 8.1, and some distributions or LTS vendors ship their own backports.
  • Restart everything after updating: PHP-FPM, Apache, and long-running CLI processes such as queue workers.
  • Assume probing is already happening. Amazon's honeypot recorded an attempt on 17 October, four days before disclosure.

What the two bugs are

PHP describes them in two GitHub advisories. The public descriptions are short.

CVE-2026-109618 CVE-2026-109619
Name RCE via out-of-memory (OOM) corruption RCE via stale global state
Advisory GHSA-w8hw-w9fx-j79w GHSA-6wmf-4rv5-p3rp
Severity Critical, CVSS v4.0 9.2 Critical, CVSS v4.0 9.2
In plain words When PHP runs out of memory while request data is only half set up, the cleanup afterwards treats that half-built data as valid. State owned by one request can outlive the memory behind it. A later request on the same worker can use that dangling state before PHP resets it.
Bug class Memory corruption Use-after-free

Researchers also showed that the second bug can be used to read PHP worker memory without running code. Worker memory can hold passwords, session data, tokens and API keys, so a successful attack is a credential leak even before any shell appears.

I am deliberately not describing exact trigger steps. The official advisories do not publish them, they are not fully public, and code claiming to be a proof of concept is circulating. The PHP Foundation says its team inspected the post-leak proofs of concept and found no functional exploits at release time. Treat any random "PHP2Shell exploit" repository as possible malware, not as a test tool.

A correction worth knowing: some early listings showed a CVSS score of 10.0. The PHP Foundation says that was incorrect. The score is 9.2.

Who is affected

According to the PHP advisory, every PHP installation that serves web requests is at risk:

  • PHP-FPM (Nginx and Apache with FPM)
  • Apache with mod_php
  • php-cgi
  • FrankenPHP
  • LiteSpeed

PHP rates the risk highest for mod_php, where a demonstrated exploit lets an unauthenticated request trigger the attack before any application code runs. That is why updating WordPress or Laravel does not help: the bug lives below your framework.

Wiz Research reported that every PHP version back to 5.4 has at least one of the two issues, and demonstrated unauthenticated RCE against the latest WordPress, Drupal and Joomla container images. Some reports say that even a minimal "Hello World" app on a vulnerable version can be hit. Those are researcher claims, and the PHP advisory does not list affected app versions.

Fixed versions

PHP branch Fixed in Notes
8.5 8.5.12
8.4 8.4.27
8.3 8.3.36
8.2 8.2.35 PHP 8.2 reaches end of life on 31 December 2026.
8.1, 8.0, 7.4 No official release Minimal source backports exist for people who build from source. Ask your distro or LTS vendor.
7.3 and older End of life No fix from the PHP project.

If you are on 8.1 or older, this is the moment to schedule an upgrade to a supported branch. Backports are a bridge, not a plan.

How to patch

1. Find out what you really run

php -v
php-fpm8.4 -v   # replace 8.4 with your version

The CLI and the web server can run different PHP versions. Check both, and check inside containers.

ls /etc/php   # Debian/Ubuntu: every installed PHP version

2. Update the packages

On Debian or Ubuntu with a PHP package repository, upgrade every package for each PHP version you have installed:

sudo apt-get update
apt-cache policy php8.4-fpm   # "Candidate" should be the fixed version
sudo apt-get install --only-upgrade -y \
  -o Dpkg::Options::="--force-confold" \
  $(dpkg -l 'php8.4*' | awk '/^ii/ {print $2}')

Repeat for every installed PHP version, including ones no site currently uses. These commands come from the Laravel Forge advisory. If Candidate is not the fixed version yet, the patched packages have not reached your repository. Wait and retry.

Two things to know:

  • Distributions backport. Your package may keep an older version number but still contain the fix. Check your vendor's security advisory or changelog for the CVE IDs instead of only comparing numbers.
  • Some repositories lag. The PHP team warns that the volunteer-run Remi repository would not have updates on release day and recommends distribution packages or a source build until it does. Managed platforms may also not patch PHP automatically. Laravel Forge, for example, says its automatic security updates do not touch PHP, so you must update each server yourself.

3. Docker and containers

Rebuild, do not just restart. An old cached layer still contains the old PHP.

docker build --no-cache -t my-app .

Pin your base image to a patched tag, for example a php:8.4.27-fpm style tag once it is available for your variant. Check the tag exists on Docker Hub first.

4. Restart everything that holds PHP

Updating the package restarts PHP-FPM, but long-running processes keep the old interpreter in memory until they are restarted. That includes queue workers, Horizon, Octane, Reverb, Supervisor-managed scripts and cron-launched daemons.

php artisan queue:restart
php artisan horizon:terminate
php artisan octane:reload

5. Verify

php -v
php-fpm8.4 -v

Confirm both report the fixed version, or confirm in your vendor's changelog that the CVEs are listed as fixed.

If you cannot patch today

PHP is clear that these measures block specific paths only and do not make an installation safe. Use them to buy time, not as a substitute.

For CVE-2026-109618 (OOM):

  • Set memory_limit=-1 where applications cannot override it, for example with php_admin_value in the FPM pool. Make sure no pool, directory or app setting re-applies a finite limit.
  • Lower post_max_size (8M if you do not need uploads, 32M if you do) and keep upload_max_filesize below it.
  • Enforce request size and multipart limits at the web server or proxy, including requests without a usable Content-Length.
  • If you use a memory cap, use a container or cgroup limit that kills only the affected worker. Do not use RLIMIT_AS or RLIMIT_DATA: PHP says those can cause the vulnerable allocation failure.

For CVE-2026-109619 (stale state):

  • Set session.upload_progress.enabled=0 in php.ini, the FPM pool or the server config, then restart every worker. Do not rely on ini_set() or .user.ini.
  • On PHP 8.5 only, also set fatal_error_backtraces=0 and restart workers.
  • Suppressing errors with error_reporting, display_errors or @ does not help.
  • Fix fatal errors and execution timeouts that an attacker can reach.

An FPM pool example, adapted from the PHP advisory:

; php.ini or FPM pool configuration
session.upload_progress.enabled = 0
post_max_size = 8M        ; or 32M if uploads are required
upload_max_filesize = 8M  ; must stay below post_max_size

; FPM pool: applies before request parsing and cannot be overridden per app
php_admin_value[memory_limit] = -1
php_admin_value[session.upload_progress.enabled] = 0

Note the trade-off: an unlimited memory_limit means a runaway script can consume memory, which is why the cgroup limit is part of the advice.

At the edge: Cloudflare says it deployed WAF rules for known vectors on all plans, including free. Cloudflare calls this a stopgap, and it only helps if your origin accepts traffic solely from Cloudflare.

Network: CERT-EU recommends isolating internet-facing PHP applications until the fix is applied and verified.

Signs someone already tried

Wiz suggests these indicators. They are hints, not proof:

  • Unusual multipart requests followed by memory-limit errors or repeated HTTP 500 responses.
  • Unexpectedly large or malformed PHPSESSID cookies.
  • Unexplained PHP worker restarts.

Amazon recommends looking back at logs from 17 October onward. If you see these signs, update first, then treat the server as possibly compromised and rotate the credentials it held: database passwords, API keys, session secrets and tokens, because memory disclosure is possible.

What is still unknown

Being honest about the gaps matters as much as the fixes:

  • Exact trigger conditions and exploit mechanics are not public in the official advisories.
  • It is unclear whether any attempt seen on 21 October would succeed against a real system. Early reports describe probing, with no confirmed breach counts.
  • Researchers say the flawed code goes back to PHP 5.4, but the PHP project's own table lists only supported branches.
  • Numbers for exposed hosts (estimates above 1.3 million) are unverified.

My take

I mostly work with Node.js and NestJS, not PHP, but this is the kind of bug that hurts everyone who runs anything on a shared host or old server: the vulnerable component is the runtime, so your own code review does not help. Update the runtime, restart every long-lived process, and check the version inside each container.

I have not tested the exploits or the mitigations myself. This post summarizes the official PHP advisory and the vendor and researcher write-ups listed below. If anything here differs from php.net, php.net wins.

Sources

Working on something like this?

I take on backend, payments and deployment projects. I reply within one working day.

Hire me
Share
↑↓ navigate↵ openesc closeCtrl K toggles this menu