
PHP2Shell: two critical PHP vulnerabilities, update now
PHP2Shell: two critical PHP vulnerabilities (CVE-2026-109618, CVE-2026-109619, CVSS 9.2) allowing unauthenticated RCE. Fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35: who is exposed, how to update and what to do if you can't.
On the PHP security team announced an out-of-band security release to fix two critical vulnerabilities, both rated CVSS v4.0 9.2. The community has already nicknamed the issue PHP2Shell, because the real risk is going from an HTTP request to a shell on the server: unauthenticated remote code execution.
⛔ The fix is out: update now
On , slightly ahead of the 14:00 UTC schedule, PHP released 8.5.12, 8.4.27, 8.3.36 and 8.2.35, which fix both vulnerabilities. According to the PHP team there are no complete mitigations: updating is the only safe choice.
Last updated: — fixed versions, official advisory and mitigations.
At a glance
| Name | PHP2Shell (unofficial nickname) |
| CVE | CVE-2026-109618 (GHSA-w8hw-w9fx-j79w), CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp) |
| Severity | CVSS v4.0 9.2 for both |
| Impact | Unauthenticated remote code execution (RCE) |
| Who is at risk | Every PHP installation serving web requests: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed |
| Fixed versions | 8.5.12, 8.4.27, 8.3.36, 8.2.35 |
| Unsupported versions | No official release; source backports for 7.4, 8.0 and 8.1 |
| Exploitation | Early attempts reported by Cloudflare, no confirmed compromise, not in CISA KEV |
What the two vulnerabilities are
The official advisory describes two flaws in how PHP manages internal request state:
- CVE-2026-109618 — RCE via OOM corruption: out-of-memory handling can interrupt PHP while internal request data is only partially initialized. Request cleanup may then treat the invalid data as valid.
- CVE-2026-109619 — RCE via stale global state: request-owned internal state can survive after its backing memory has been freed. A later request handled by the same worker may use that stale state before normal initialization resets it.
The PHP team considers the risk highest for mod_php, with a demonstrated exploit where an unauthenticated request triggers the attack before any application code runs. In other words: it does not matter how well written your application is, the problem is in the interpreter.
Full technical details are in the GitHub advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp.
Who is exposed
In practice: anyone running an internet-facing PHP application. Not just custom apps, but every popular CMS and e-commerce platform too:
- WordPress, Joomla, Drupal
- PrestaShop, Magento, WooCommerce
- frameworks such as Laravel and Symfony
- admin panels and tools written in PHP (phpMyAdmin, Roundcube, etc.)
⛔ Updating your CMS does not update PHP
This is the most common misconception: updating WordPress, plugins or themes does not change the PHP version on the server. They are two separate layers. Here the vulnerability lives in the PHP interpreter, so PHP itself needs to be updated (by you or by your hosting provider).
How to update
1. Take an inventory of your PHP versions
A single server often runs several versions (CLI, FPM, separate pools per site, containers). Check them all:
# CLI version
php -v
# all installed versions (Debian/Ubuntu)
ls /usr/bin/php* /usr/sbin/php-fpm* 2>/dev/null
# active FPM services
systemctl list-units --type=service | grep -i php
# PHP version inside running Docker containers
docker ps --format '{{.Names}}' | xargs -I{} sh -c 'echo -n "{}: "; docker exec {} php -r "echo PHP_VERSION, PHP_EOL;" 2>/dev/null || echo "-"'
On a WordPress site, the version actually used by the web server is also shown under Tools → Site Health → Info → Server.
2. Install the fixed version
The target is 8.5.12, 8.4.27, 8.3.36 or 8.2.35, depending on your branch. Linux distributions and LTS vendors received the patches in advance, so packages are already landing.
-
Shared or managed hosting: your provider applies the patch. Ask them when the fixed build will be live and make sure the PHP version selected in your panel (cPanel, Plesk, etc.) is a supported one.
-
Debian/Ubuntu with Ondřej Surý’s repository (
packages.sury.org/ppa:ondrej/php): the fixed packages are already available.sudo apt update sudo apt install --only-upgrade 'php*' -
Distribution packages (official Debian, Ubuntu, RHEL, etc.): these backport fixes into the version you already run, so a patched package can keep an old-looking version number. Do not judge by
php -valone: check the package changelog for the CVE or compare the exact package version against your distribution’s advisory.# Debian/Ubuntu: look for the CVEs in the package changelog apt changelog php8.3-common 2>/dev/null | grep -E 'CVE-2026-10961[89]' -
Remi’s repository (
rpms.remirepo.net): per the PHP advisory it will not have updates today. The PHP team recommends switching to distribution packages or building from source so you can patch immediately. -
Containers: rebuild your images from the new official
php:*tags (e.g.php:8.3.36-fpm). Pulling the new image is not enough: you have to recreate the running containers. -
Windows: binaries are on the php.net downloads page.
3. Restart and verify
Installing the package does not replace processes already running. Both flaws live in long-lived workers, so restart every PHP-FPM pool and Apache if you use mod_php:
# adjust to the versions you actually run
sudo systemctl restart php8.3-fpm php8.4-fpm
sudo systemctl restart apache2 # if you use mod_php
Then verify the version seen by the web server, not the CLI one: a temporary phpinfo() page (delete it right after), Site Health in WordPress, or the X-Powered-By header if it is enabled.
After updating, review your logs for anything suspicious that happened before the patch: crashes and segfaults of PHP workers, unusual requests, new files in web directories.
4. Unsupported versions (8.1, 8.0, 7.x, 5.x)
The PHP project no longer releases updates for 8.1 and older. Given the severity, though, the security team has published minimal source backports for 7.4, 8.0 and 8.1, for those who build from source or have no LTS vendor. Some distributions and extended-support vendors also ship backported fixes.
For anything older than 7.4 there is nothing: migrate, or isolate the application. And whatever happens, use this as the push to move to a supported version (8.2 is in security-only maintenance until the end of 2026, so aim for 8.4 or 8.5).
If you cannot update right away
The PHP advisory is clear: only an update is a complete solution. The following measures reduce exposure to specific attack paths but do not make an installation safe.
Against CVE-2026-109618 (OOM corruption)
- Set
memory_limit=-1, preferably in a way applications cannot override (php_admin_valuein the FPM pool or Apache config), and check that no pool, directory or application setting puts a finite limit back. This removes the controllable memory-limit failure, but an underlying allocation failure can still reach the vulnerable path. - Set a low
post_max_size:8Mfor applications without uploads,32Mif uploads are needed, withupload_max_filesizebelowpost_max_size. - Enforce limits at the web server or proxy on decoded request size, number of input fields, multipart parts, headers and nesting depth, including for requests without a usable
Content-Length. - Use a container or cgroup memory limit as an availability boundary, ideally one that kills only the affected worker. Do not use
RLIMIT_ASorRLIMIT_DATAinstead: they can trigger the vulnerable allocation failure themselves.
With memory_limit=-1 a single request can eat all the RAM: that is exactly why the cgroup limit is part of the package.
Against CVE-2026-109619 (stale global state)
- Set
session.upload_progress.enabled=0and restart every worker. It must be set inphp.ini, in the FPM pool or in server config that applies before request parsing: do not rely onini_set()or on.user.ini. It blocks the confirmed session paths, not other variants. - On PHP 8.5, also set
fatal_error_backtraces=0and restart the workers: it blocks the confirmed fatal-backtrace path only. - Remove invalid or deprecated settings applied per request that emit diagnostics before initialization. Hiding diagnostics with
error_reporting,display_errorsor@does not help. - Fix fatal errors and execution timeouts that an attacker can trigger, including failures in callbacks, upload or import processing, and cleanup.
⚠ session.upload_progress is not a fix
Before the release, session.upload_progress.enabled=0 was being passed around on social media as “the” fix. The PHP advisory confirms it helps, but only against some paths of CVE-2026-109619, and does nothing against CVE-2026-109618. Useful as a stopgap, not as protection.
Network and blast radius
- For applications that cannot be patched promptly, CERT-EU recommends considering isolating them from public networks. Short of that, put them behind a VPN, IP allowlist or authentication at the edge, and make sure the origin cannot be reached directly around those controls.
- Cloudflare has pushed emergency WAF rules for the known exploit paths, free plan included. Its CTO calls them “a STOPGAP only”: they only see traffic going through Cloudflare and may miss new variants.
- Shrink what an attacker would get if the server were compromised: less data stored on the server, fewer privileges for the PHP user, no credentials or cloud roles lying around, and logs shipped somewhere safe.
Timeline
- — The PHP team announces a security release for two vulnerabilities rated CVSS 9.2.
- – — CERT-EU publishes advisory 2026-018 with identifiers CVE-2026-109618 and CVE-2026-109619.
- — GMO Flatt Security clarifies that
session.upload_progress.enabled=0is not a complete fix. - — Cloudflare reports early exploitation attempts and releases emergency WAF rules.
- , just before 14:00 UTC — PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 together with the security advisory and backports for 7.4, 8.0 and 8.1.
Sources
- PHP.net — Security advisory: Critical remote code execution vulnerabilities, update now
- GitHub — GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- GitHub — GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- PHP.net — PHP 8 ChangeLog
- PHP.net — Upcoming Critical PHP Security Release
- CERT-EU — Security Advisory 2026-018: Critical Vulnerabilities in PHP
- The Hacker News — PHP2Shell: what actually protects you
- Cloudflare — Emergency WAF release
- Serverplan — PHP2Shell: due vulnerabilità critiche in PHP (Italian)
- PHP.net — Supported Versions
If you manage WordPress sites, use this moment to go through my WordPress security checklist as well: updating PHP closes this hole, but not the others. And if you need to test compatibility with a newer PHP version before migrating production, WPDockerize lets you set up a local environment in a few minutes.

Co-Founder & CTO at PAPION. Senior full-stack engineer specializing in React, TypeScript, Node.js, and application security.