Skip to content

Go back

ArticleOct 23, 2026

PHP2Shell explained: who is affected, how to patch, and why updating WordPress is not enough

PHP2Shell (CVE-2026-109618, CVE-2026-109619) lets attackers run code on PHP servers with no login. Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and restart.

By Aidan Scott, AtasAI

PHP2Shell: CVE-2026-109618 and CVE-2026-109619, how to patch

PHP2Shell is the name for two critical bugs in PHP itself: CVE-2026-109618 and CVE-2026-109619. An attacker can run code on your server with one request and no login. PHP builds from before 21 October 2026 are affected, unless your package includes the backported fix. Update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your Linux distribution’s patched package, then restart all PHP workers.

Updating WordPress, Laravel or Composer packages does not fix this. The bug is in the PHP runtime on the server.

Update 24 October 2026: patched builds for PHP 8.1, 8.0 and 7.4 are now available from package maintainers, including the packages that Laravel Forge uses. See “Patched builds for PHP 8.1 and older” below.

Quick facts

Field Detail
CVE CVE-2026-109618 (GHSA-w8hw-w9fx-j79w), CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp)
Name PHP2Shell
Type Unauthenticated remote code execution (memory corruption)
Affected versions All PHP builds before the fixed releases, unless the package includes the backported fix. Reports say this goes back to PHP 5.
Fixed versions 8.5.12, 8.4.27, 8.3.36, 8.2.35 (released 21 October 2026, 14:00 UTC). Ubuntu and Debian ship the fix in their own packages under lower version numbers. 8.6.0 RC4 also has the fixes, but it is a release candidate.
PHP 8.1 and older No new php.net release. Patched builds exist from Ondřej Surý’s packages (used by Laravel Forge), Ubuntu and Remi. See “Patched builds for PHP 8.1 and older”.
CVSS 9.2 (CVSS v4.0), Critical, for each CVE
Exploitation status Widespread scanning and exploit attempts. Sources disagree on real compromises. No confirmed compromise was publicly documented when we wrote this.
Highest-risk setup Apache with mod_php

What is PHP2Shell?

PHP2Shell is two security bugs in the PHP interpreter. Details leaked on 20 October 2026 under the name “php2shell”. php.net announced an emergency release the same day and shipped the fixes on 21 October 2026.

php.net describes the two bugs like this:

In plain English, both bugs sit in the code PHP runs while it sets up an incoming request. This happens before WordPress, Laravel, your middleware or your login check runs.

  • CVE-2026-109618. If PHP runs out of memory while setting up a request, some internal data is left half built. The cleanup code trusts it anyway.
  • CVE-2026-109619. Some internal state lives longer than the memory it points to, so the next request on the same worker can act on stale data. The “session upload progress” feature, on by default, is one confirmed way to reach this bug.

So a security plugin, a framework update or a login page cannot stop the attack. PHP handles the request before your code runs.

Where vendors disagree

The official description comes from php.net and the php-src security advisories. Other researchers give different detail. Sansec describes use-after-free paths in the upload-progress unserializer and in fatal-error backtraces. SOCRadar says four bugs sit behind the two CVEs. We treat these as unconfirmed. For full technical detail, read the php-src GitHub advisories.

Am I affected?

First, find out where your PHP comes from. The fixed version number depends on it.

Case A: PHP from php.net, Ondřej Surý’s packages (ppa:ondrej/php or packages.sury.org), Laravel Forge or the official Docker php image. You need PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 or later on your branch. For PHP 8.1, 8.0 and 7.4, you need the backport revisions in “Patched builds for PHP 8.1 and older” below.

Case B: PHP from your Linux distribution’s own packages (Ubuntu or Debian). The version number stays lower, because the fix is backported into the older version. For example, a patched Ubuntu 24.04 server still shows PHP 8.3.6. Compare the package version with the notice for your release:

Release Package Fixed version Notice
Ubuntu 26.10 php8.5 8.5.9-0ubuntu2.1 USN-8948-1
Ubuntu 26.04 LTS php8.5 8.5.4-0ubuntu1.5 USN-8948-1
Ubuntu 24.04 LTS php8.3 8.3.6-0ubuntu0.24.04.13 USN-8948-1
Ubuntu 22.04 LTS php8.1 8.1.2-1ubuntu2.28 USN-8948-1
Ubuntu 20.04 (Ubuntu Pro only) php7.4 7.4.3-4ubuntu2.29+esm5 USN-8948-2
Ubuntu 18.04 (Ubuntu Pro only) php7.2 7.2.24-0ubuntu0.18.04.17+esm14 USN-8948-2
Debian 13 trixie php8.4 8.4.27-1~deb13u1 DSA-6574-1
Debian 12 bookworm php8.2 8.2.35-1~deb12u1 DLA-4848-1

Package versions last checked 24 October 2026.

Which case are you in? Look at the installed package version:

apt-cache policy php8.3-cli
dpkg -l 'php8.*'

Change 8.3 to your version. If the version contains deb.sury.org, you are in case A. If it contains ubuntu or deb12u1 / deb13u1, you are in case B.

You are affected if any of these is true:

  • Your PHP package is older than the fixed version for your case.
  • Your server runs PHP 8.1 or older and you have not installed a patched build. php.net released no new version for these.
  • Your server has more than one PHP version installed, and any one of them is unpatched.
  • Your Docker image was built before 21 October 2026.
  • You patched PHP but did not restart your long-running workers (see “How to confirm the fix is running”).

Check the PHP version on the command line

php -v

Then list every installed version:

ls -1 /usr/bin/ | grep php

Each one needs the patch, even if your site does not use it. On distribution packages (case B), php -v shows the base version, for example 8.3.6. Use the package version instead.

Check the version your web server really uses

Command-line PHP and web PHP (PHP-FPM or mod_php) can differ. Check the web version too:

  • Run the FPM binary directly, for example php-fpm8.4 -v. This starts a new process. It does not prove that the running workers restarted.
  • Never put phpinfo() on a public URL. It gives attackers useful information. On the server, run php -i | grep 'PHP Version'. If you must check the web runtime, use a one-off script behind authentication, and delete it right after.

Docker

Check the PHP version inside the running container, not on the host:

docker exec <container> php -v

An image built before 21 October 2026 is almost certainly unpatched.

Shared hosting and managed hosts

Check the PHP version in your control panel (for example the PHP selector in cPanel). If you cannot see the exact package version, ask your host in writing.

How to patch

The fix is always the same: install a fixed PHP version, then restart every PHP process. Workers keep the old code in memory until they restart. This includes PHP-FPM, Apache, Laravel Octane, Swoole, RoadRunner and FrankenPHP. Then check the version again, on the command line and in the web context.

Ubuntu and Debian (apt)

sudo apt update
sudo apt install --only-upgrade 'php8.*'
sudo systemctl restart php8.4-fpm   # repeat for each installed version
sudo systemctl restart apache2      # if you use Apache / mod_php

Then check the package version for your case: case A needs 8.4.27, 8.3.36 or 8.2.35; case B needs the distribution version in the table above.

Old Ubuntu releases. Ubuntu 20.04 and older do not get a patched PHP 8.2 from the usual PPA. The lowest patched path is Ubuntu 22.04. Ubuntu’s own PHP packages on 20.04 and older are fixed only through Ubuntu Pro (USN-8948-2). Plan a rebuild, and use the temporary measures below until then.

Docker images

Change the image tag to a fixed version and rebuild with --pull, so Docker downloads the new base image:

docker compose build --pull
docker compose up -d
docker exec <container> php -v

docker compose build only builds the new image. It does not replace the running containers. docker compose up -d recreates them. You can also do both in one step:

docker compose up -d --build --pull always

For services that use a prebuilt image: (no build:), pull first, then recreate:

docker compose pull
docker compose up -d
  • Official image: use a tag that names the fixed version, for example php:8.4.27-fpm.
  • serversideup images shipped fixed tags on 21 October 2026, for example 8.4.27-fpm-nginx.
  • Do not trust a floating tag such as 8.4-fpm until you check the version inside the container. Lando’s PHP images had not shipped a fix as of 22 October 2026.

Laravel Forge and Ploi

  • Laravel Forge: Forge’s automatic security updates do not patch PHP (Forge knowledge base). Click Update PHP on each server in Forge, for every installed PHP version. Removing an unused version also works. Forge installs PHP from Ondřej Surý’s packages (case A), so the Ubuntu versions in the table above do not apply to Forge servers. Servers on Ubuntu 20.04 or older cannot get the fix from Forge.
  • Ploi: we found no Ploi notice for this release. Use Ploi’s PHP management, or SSH and the apt steps above.
  • Laravel Cloud: patched automatically by the platform.
  • Bref and DigitalOcean: both shipped updates. Redeploy to pick them up.

cPanel and shared hosting

Your host controls the PHP binary, so you cannot patch it yourself.

  1. Check the PHP version in the control panel, or ask your host.
  2. If it is below the fixed version, open a support ticket and ask for the exact version installed.
  3. If your account offers several PHP versions, choose 8.4 or 8.5.
  4. If your site is on PHP 8.1 or older, plan an upgrade now.

Managed WordPress hosts

Managed WordPress hosts usually patch PHP for you. Do not assume it. Ask the host to confirm in writing that your site runs a fixed version, and check it yourself if the host shows the PHP version in its dashboard.

How to confirm the fix is running

Installing a fixed package is not enough. The PHP processes that serve requests must restart too.

  • PHP-FPM restarts by itself. On Debian and Ubuntu, the php8.x-fpm package restarts PHP-FPM when it is upgraded. In containers, a policy-rc.d rule can block this.
  • Apache with mod_php reloads by itself on current Ubuntu and Debian releases (Launchpad bug 2038912 is fixed). A manual sudo systemctl reload apache2 does no harm.
  • Long-running CLI workers do not restart. Laravel queue workers, Horizon, Octane and Supervisor jobs keep the old PHP code in memory. Restart them by hand:
php artisan horizon:terminate
php artisan queue:restart
php artisan octane:reload
sudo supervisorctl restart all

Check that a process started after the new package was installed:

ps -o lstart= -C php-fpm8.3
ls -l --time-style=full-iso /usr/sbin/php-fpm8.3

Change 8.3 to your version. If a process started before the file time, it still runs the old code. Restart it.

Patching does not prove that the server was not compromised before. If a server was reachable and unpatched after 21 October, while attacks were reported, review its logs and consider a compromise assessment.

Why updating WordPress, Laravel or Composer is not enough

Your application runs on top of PHP. WordPress updates, plugin updates and composer update laravel/framework do not change the PHP binary on the server.

composer audit and GitHub Dependabot will not flag PHP2Shell. They check the packages in composer.lock, not the interpreter. A clean composer audit report does not mean you are safe. Check the PHP version on the server.

If you cannot patch yet

First, find out if you really cannot patch. Many servers on PHP 8.1, 8.0 or 7.4 can get a fixed build today (see the next section).

If you cannot install a fixed build yet, reduce the risk while you plan:

  • Take the server off the public internet if you can. Forge’s advice is to power down servers that cannot be updated.

These steps make some attacks harder. They do not make PHP safe. The PHP project says only an update is a complete fix.

For CVE-2026-109618 (out-of-memory corruption):

  • Set memory_limit=-1 with php_admin_value in the PHP-FPM pool config, so apps cannot change it. Check that no other setting puts a limit back.
  • Set a low post_max_size: 8M without file uploads, 32M with uploads. Keep upload_max_filesize below it. Limit request size at the web server or proxy too.
  • Use a container or cgroup memory limit as the safety net. Do not use RLIMIT_AS or RLIMIT_DATA. Without a PHP memory limit, one bad request can use a lot of memory; the cgroup limit protects the rest of the server.

For CVE-2026-109619 (stale global state):

  • Set session.upload_progress.enabled=0 in php.ini or the PHP-FPM pool config. Do not use ini_set() or .user.ini; they apply too late.
  • On PHP 8.5, also set fatal_error_backtraces=0.
  • Then restart every PHP worker: PHP-FPM, queue workers, Horizon, Octane.

A separate issue: CVE-2026-115560. On 23 October 2026, php.net announced another session upload progress issue. It is an unlikely RCE vector: the app must use a non-default session.serialize_handler and switch it to php with ini_set() before session_start(). As of 24 October there is no fixed version yet, and 8.5.12 is still affected. The mitigation is the same: session.upload_progress.enabled=0.

Patched builds for PHP 8.1 and older

The PHP project did not release new versions of PHP 8.1, 8.0 or 7.4. But it did publish source patches for these three versions. Some package maintainers used them to build fixed packages.

On Laravel Forge (Ubuntu 22.04 or 24.04). On 23 October, Forge told customers that patched versions are available “for every PHP version on Laravel Forge, from PHP 5.6 to 8.5.” Forge installs PHP from Ondřej Surý’s packages. Those packages were updated on 21 October. The sources conflict: as of 24 October, Forge’s public knowledge base page still says PHP 8.1 and earlier are not patched. Check the package version on each server. To update:

  1. Open the server in Forge and go to the PHP tab.
  2. For each installed PHP version, open the menu and click Update PHP X.X.
  3. Restart queue workers, Horizon and Octane.

On any Ubuntu 22.04 or 24.04 server that uses ppa:ondrej/php:

sudo apt-get update
apt-cache policy php8.1-fpm

The candidate should be 8.1.34-9+ubuntu22.04.1+deb.sury.org+1 (or ubuntu24.04.1). Then upgrade every package for that version:

sudo apt-get install --only-upgrade -y \
  -o Dpkg::Options::="--force-confold" \
  $(dpkg -l 'php8.1*' | awk '/^ii/ {print $2}')
sudo systemctl restart php8.1-fpm

Change 8.1 to 8.0 or 7.4 as needed. The fixed revisions are 1:8.0.30-25 and 1:7.4.33-31.

Check the package changelog, not php -v. The version number does not change. A fixed PHP 8.1 still says 8.1.34. Run:

zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.1-cli/changelog.Debian.gz

The pattern matches either CVE number. If the command prints a line, the installed package contains the fix. It does not prove that the running PHP processes restarted (see “How to confirm the fix is running”). If it prints nothing, the check is not conclusive: compare the package version with the table below.

Patched builds by version. “Verified” means we found it in two or more independent sources. “Reported” means one source only. Package versions last checked 24 October 2026.

PHP Fixed build From How to get it Status
8.1 8.1.34-9+ubuntu22.04.1+deb.sury.org+1 (or ubuntu24.04.1) Ondřej Surý’s packages (used by Laravel Forge) Forge Update PHP, or apt on Ubuntu 22.04 or 24.04 Verified
8.1 8.1.2-1ubuntu2.28 Ubuntu 22.04, Ubuntu’s own php8.1 (USN-8948-1) Normal Ubuntu update Verified
8.1 php81 8.1.34-6 Remi (RHEL, Alma, Rocky 8 to 10) dnf update Reported
8.0 1:8.0.30-25 Ondřej Surý’s packages Forge Update PHP, or apt Verified
8.0 php80 8.0.30-21 Remi dnf update Reported
7.4 1:7.4.33-31 Ondřej Surý’s packages Forge Update PHP, or apt Verified
7.4 7.4.3-4ubuntu2.29+esm5 Ubuntu Pro on Ubuntu 20.04 (USN-8948-2) sudo pro fix CVE-2026-109618 and sudo pro fix CVE-2026-109619 Verified
7.4 php74 7.4.33-31 Remi dnf update Reported
7.3, 7.2, 7.1, 5.6 Not checked Ondřej Surý’s packages (Debian and Ubuntu) apt Reported
All ea-php versions Fixed ea-php packages CloudLinux (cPanel) EasyApache update Reported
Any version on Forge with Ubuntu 20.04 or older No fix from Forge None Move the sites to a new server on Ubuntu 22.04 or 24.04. For PHP 7.4, Ubuntu Pro (pro fix) is the only official option Verified
8.1 or older, official Docker php image No fix None Upgrade to PHP 8.2 or later. Unofficial community images exist, for example ghcr.io/mpyw/php-eol-cve-2026-109618-109619 Reported

Some limits:

  • These builds come from package maintainers, not from the PHP project.
  • Forge servers on Ubuntu 20.04 or older cannot get the fix. Move the sites to a new server.
  • ARM servers got their builds later than x86 servers. Check apt-cache policy first.
  • A patched PHP 8.1 is a short-term fix. Plan the upgrade. Aim for PHP 8.3 or later, because PHP 8.2 security support ends on 31 December 2026.

A WAF can be bypassed if the origin is reachable

Cloudflare shipped emergency WAF rules on 21 October 2026. On the Free plan the protection is automatic (Cloudflare Managed Free Ruleset). On paid plans, confirm that the Cloudflare Managed Ruleset is deployed in Block mode. The 23 October update also covers CVE-2026-115560, but not sites that use a custom session.upload_progress.name.

A WAF only checks traffic that passes through it. If your origin server is reachable directly by its IP address, an attacker can bypass the WAF. Restrict the origin firewall to Cloudflare’s IP ranges. We found this gap on more than one server during our own PHP2Shell response. It is easy to miss, because the site looks protected when you test it through its domain name.

Cloudflare calls its rules a stopgap: a new variant can pass until the next update. Also avoid community rules that block every PHPSESSID cookie. That is PHP’s default session cookie, so the rule breaks logged-in users.

Was it exploited?

Reports differ. Here is what each source said:

  • watchTowr: its honeypots saw exploitation of both CVEs in the wild on 21 October 2026.
  • CISA: its alert on 21 October 2026 said no exploitation was observed at publication. The CVEs were not in the CISA Known Exploited Vulnerabilities catalogue as of 22 October 2026.
  • Huntress: no exploitation seen on partner systems (21 October 2026, 20:30 UTC).
  • Wordfence: blocked more than 74,000 exploit or probing attempts, with no confirmed compromises.

Reports say most public proof-of-concept code crashes PHP workers rather than running code. Sansec later said mass exploitation is “less likely than we expected.”

Our summary: scanning and attempts are widespread, but confirmed compromises were not publicly documented when we wrote this. Patch now anyway. A crashing exploit can still take your site down.

Other PHP ecosystem vulnerabilities this week

Laravel token guard authentication bypass (GHSA-f9x3-7vq9-cph6)

  • Affected: laravel/framework below 12.68.0 and below 13.29.0. No fix is listed for 11.x or older.
  • Fixed: 12.68.0 and 13.29.0. The fix shipped in August 2026. The advisory was published on 19 October 2026.
  • Severity: Critical, CVSS v4.0 9.2.
  • What it is: the built-in token guard accepted a token that is not a string. On MySQL or MariaDB, a crafted value can match the wrong user, so an attacker can log in as that user on API routes that use this guard. The advisory does not name Sanctum or Passport.
  • What to do: run composer update laravel/framework. Search config/auth.php for 'driver' => 'token'. Unlike PHP2Shell, composer audit does flag this one.

Duplicator (WordPress) object injection: CVE-2026-82814

Reported by Wordfence, as covered by SecurityOnline. We found one source only.

  • Affected: Duplicator 1.5.17 and earlier, and Duplicator Pro 4.6.10 and earlier. The plugin has more than 1 million active installs.
  • Fixed: 5.0.0 (both editions).
  • Severity: High, CVSS v3.1 8.8. No known exploitation as of 22 October 2026.
  • What it is: an attacker posts a comment with a crafted PHP object. If an admin later backs up and restores the site, the installer can run commands (free) or delete files such as wp-config.php (Pro).
  • What to do: update to 5.0.0, then build new backup packages. Old archives still contain the vulnerable installer.

Bricksforge (WordPress) file upload: CVE-2026-85097

  • Affected: Bricksforge 3.1.8.9 and earlier, about 6,000 sites.
  • Fixed: 3.1.8.10.
  • Severity: Critical. SecurityWeek lists CVSS 9.8; Cybersecurity News lists 10.0.
  • Status: exploited in the wild. Patchstack saw automated attacks from 7 October 2026.
  • What to do: update, look for unexpected .php files in upload folders, and block PHP execution in wp-content/uploads.

Need help checking your servers?

We can check every server and container for PHP2Shell, confirm that your origins cannot bypass your WAF, and plan upgrades from end-of-life PHP. Book a PHP patch audit.

Aidan’s first-person notes on responding to this: aidanscott.ai/posts/php2shell-lessons.

Sources

FAQ

What is PHP2Shell?

PHP2Shell is the name for two critical bugs in the PHP interpreter: CVE-2026-109618 and CVE-2026-109619. They let an attacker run code on a server with one request and no login. PHP released fixes on 21 October 2026.

Which PHP versions fix PHP2Shell?

From php.net, the fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Ubuntu and Debian ship the fix in their own packages under lower version numbers, for example 8.3.6-0ubuntu0.24.04.13 on Ubuntu 24.04, so compare your package version with your distribution’s notice. PHP 8.6.0 RC4 also contains the fixes, but it is a release candidate, not a production upgrade.

Does updating WordPress or Laravel fix PHP2Shell?

No. The bug is in PHP itself, not in WordPress, Laravel or any plugin. You must update the PHP package on the server and restart PHP.

Will composer audit detect PHP2Shell?

No. composer audit and GitHub Dependabot check the packages in your project. They do not check the PHP interpreter on the server, so you must check the PHP package version yourself.

Is a WAF enough to protect against PHP2Shell?

No. A WAF such as Cloudflare blocks known attack patterns, but a new variant can pass until the rules are updated. A WAF can also be bypassed if your origin server is reachable directly, so restrict the origin to Cloudflare’s IP ranges. You still need to patch PHP.

Can I patch PHP 8.1 or older for PHP2Shell?

Often, yes. The PHP project did not release new 8.1, 8.0 or 7.4 versions, but it published source patches, and package maintainers built fixed packages from them. On Ubuntu 22.04 or 24.04 with Ondřej Surý’s packages (this includes Laravel Forge), update PHP: the fixed packages are 8.1.34-9, 1:8.0.30-25 and 1:7.4.33-31. Ubuntu’s own php8.1 on 22.04 is fixed in 8.1.2-1ubuntu2.28. On Ubuntu 20.04, PHP 7.4 has a fix through Ubuntu Pro only. The version number stays the same after the fix, so check the package version or changelog, not php -v. Until you patch, isolate the server and set session.upload_progress.enabled=0. Then plan an upgrade to PHP 8.3 or later.

Want us to check your PHP setup? Get a free PHP audit