On 21 October 2026 the PHP project released PHP 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, that allow unauthenticated remote code execution on web-facing PHP installations. Both are rated 9.2 on CVSS v4.0, the exploit chain is circulating under the name PHP2Shell, and Cloudflare reported the first attack attempts within hours of the release. This post explains what the bugs are, which servers are exposed, and what to do, in order, today. Two companion posts cover how to apply the patches on every platform and what to do if you cannot patch yet.
What happened, and when
The timeline was unusually compressed, which is part of why this one matters.
- 20 October 2026: the PHP security team posted an advance notice of a security release for the next day, naming two critical vulnerabilities rated CVSS v4.0 9.2 and reserving the right to release early if details leaked or exploitation appeared. The same day, the CVE identifiers and screenshots of an exploit tool with a "php2shell" banner started circulating, and the original embargo date of 22 October was pulled forward.
- 21 October 2026, about 13:35 UTC: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 were published, slightly ahead of the announced 14:00 UTC slot, together with a security advisory on php.net and two GitHub advisories with the technical detail.
- 21 October 2026, afternoon: Debian 13, Ubuntu 24.04 and the packages.sury.org repository shipped fixed builds within the first hour; others were still building at the time of writing. Cloudflare said it was seeing early attacks and enabled emergency WAF rules on all plans, and watchTowr and Huntress reported reproducing CVE-2026-109618.
In other words, the gap between "patch available" and "exploit in use" was hours, not weeks. If you run PHP on the internet and have not updated yet, this is the kind of advisory where you stop reading and start patching, then come back for the details.
The two vulnerabilities in plain language
Both bugs live in the PHP engine itself, not in any extension, framework or CMS, and both are classified as use-after-free (CWE-416). They are separate issues with separate CVE numbers, but they share a theme: PHP's handling of a request that goes wrong part-way through, and what it leaves behind.
CVE-2026-109618: remote code execution via out-of-memory corruption
Definition: when a PHP request runs out of memory, PHP aborts it with a longjmp() that jumps straight out of whatever it was doing. If that happens while request structures are only partly initialised, the cleanup code that runs at request shutdown treats the half-built data as valid, reads and frees invalid memory, and can be steered into executing attacker-controlled code.
The attacker's job is to make a request run out of memory at exactly the wrong moment, and the GitHub advisory lists several ways to do that while staying inside the apparent limits: a multipart body sent without a usable Content-Length so it passes the post_max_size check and keeps streaming, multipart parts with unlimited headers whose in-memory representation is far larger than the bytes on the wire, and empty file controls that do not count towards max_file_uploads but still allocate metadata. None of this requires an account, a form, or any particular application. Apache's mod_php is the worst case because it parses the request body during startup and still calls request shutdown when startup fails, so the exploit runs before a single line of application code. The PHP team validated unauthenticated remote code execution against mod_php over plain HTTP with default input and memory limits.
CVE-2026-109619: remote code execution via stale global state
Definition: PHP workers (FPM children, Apache processes, FrankenPHP threads) handle many requests in a row. Some request-owned state, such as error, session, object and extension data, is referenced from persistent worker globals and is supposed to be reset before the request's memory is released. A fatal error, an execution timeout or an out-of-memory condition can abort the operation before that reset runs, or a diagnostic emitted during late shutdown can repopulate the state after it was cleared. The worker then frees the request heap while still holding a pointer into it. The next request on the same worker can touch that dangling pointer before normal initialisation resets it, which gives a use-after-free that can be turned into memory disclosure and code execution.
Exploitation needs two requests that land on the same worker: a producer that leaves stale state behind and a consumer that touches it early. The confirmed consumers are INI diagnostics raised before request initialisation (any warning from a deprecated or invalid setting applied per request, for example through .htaccess php_value directives or PHP_VALUE passed by nginx) and the session upload progress feature, which runs before normal session initialisation, is enabled by default and does not need session_start(). On PHP 8.5 the fatal_error_backtraces feature provides a confirmed producer, and that chain is the basis of the demonstrated exploit against mod_php. Hiding warnings with error_reporting, display_errors or the @ operator does not help, because the stale state is touched whether or not the message is shown.
Who is exposed
Every PHP installation that serves web requests is in scope. The advisories rank the server APIs (SAPIs) by how much has been demonstrated:
| Deployment | CVE-2026-109618 (OOM) | CVE-2026-109619 (stale state) | Practical reading |
|---|---|---|---|
| Apache with mod_php (prefork) | Confirmed, unauthenticated RCE before application code runs | Confirmed; .htaccess and php_value directives supply the early consumer | Highest risk. Patch first. |
| PHP-FPM behind nginx or Apache mod_proxy_fcgi | Conditional; FPM kills the child when startup fails, but OOM after startup can still reach the bug | Conditional; exposed when the frontend passes PHP_VALUE or PHP_ADMIN_VALUE, and the session upload path was validated on FPM | Not safe, just harder. Patch today. |
| FrankenPHP | Likely susceptible (calls shutdown unconditionally), unvalidated | No early consumer in the default configuration; not immune | Patch today. |
| LiteSpeed and OpenLiteSpeed (LSAPI) | Likely susceptible, unvalidated | Conditional, no default consumer established | Patch today. |
| php-cgi | In scope per the php.net advisory | One process per request, so cross-request state is less reachable | Patch today. |
| CLI scripts and cron jobs | No HTTP body parsing | One request per process | Low risk, but the same binary. Update with everything else. |
Version-wise, the bugs are old. The PHP project only lists the branches it still supports (8.2 to 8.5), but CERT-EU and the leaked tool's own banner put the start of the affected range at PHP 5.x, and the PHP security team took the unusual step of publishing minimal source backports for 7.4, 8.0 and 8.1, which tells you those versions are affected too. If you run anything older than 8.2 and have no vendor backporting fixes for you, assume you are vulnerable and read the mitigations post.
The scale is what makes this a bad day for the internet rather than for one vendor. PHP sits behind roughly seven in ten websites with a known server-side language, Shodan searches turn up close to two million internet-exposed hosts advertising PHP, and WordPress, Laravel, Magento, Drupal, Nextcloud, Moodle and most control panels run on it.
The fixed versions
Updating is the only complete fix. The PHP project is explicit that there are no complete mitigations, only measures that narrow specific attack paths.
| Branch | Fixed in | Support status |
|---|---|---|
| PHP 8.5 | 8.5.12 | Active support |
| PHP 8.4 | 8.4.27 | Active support |
| PHP 8.3 | 8.3.36 | Security support |
| PHP 8.2 | 8.2.35 | Security support until 31 December 2026, then end of life |
| PHP 8.1, 8.0, 7.4 | No release; source-only backport branches from the PHP security team | End of life. Distribution and LTS vendors may ship backports; otherwise build from the branch or upgrade |
| PHP 7.3 and older | Nothing | End of life. Upgrade, isolate, or take offline |
The fix for CVE-2026-109618 replaces the longjmp() on out-of-memory with a "soft" OOM that is raised gracefully at the next safe point in the engine, backed by a "hard" OOM that calls _exit() if memory use reaches a second, higher threshold. The fix for CVE-2026-109619 makes sure request-owned state is reset before the request heap is released. Both are engine changes, which is why there is no application-level patch, no framework update and no plugin that fixes this for you.
One thing to know about Linux distributions: Debian, Ubuntu and Red Hat backport security fixes into the version they ship rather than moving to the new upstream number. A patched Ubuntu 24.04 server still reports PHP 8.3.6; what changes is the package release (8.3.6-0ubuntu0.24.04.13 at the time of writing). So on a distro-packaged PHP, php -v tells you nothing about this vulnerability. Check the package changelog for the CVE numbers instead. The patching guide has the exact commands per platform.
What to do today, in order
- Inventory every PHP you run. Servers often carry more than one: a distro package, a cPanel EasyApache build, a CloudLinux alt-php, a Docker image, a PHP inside a Plesk handler. Each one needs updating. Include the staging server and the forgotten marketing microsite.
- Patch anything running Apache with mod_php first. That is where the exploit is demonstrated and where it needs no application involvement. Then PHP-FPM, FrankenPHP and LiteSpeed.
- Restart the right process. A new binary on disk changes nothing until the workers are restarted. For mod_php that means a full Apache restart, not a graceful reload. For FPM, restart the service. For Docker, recreate the container.
- Verify by changelog or image tag, not by version string, for the reason above. Then confirm no process is still mapping a deleted library.
- If you cannot patch a server today, apply the layered mitigations from the PHP advisory (
memory_limit=-1with a cgroup boundary, tightpost_max_size,session.upload_progress.enabled=0,fatal_error_backtraces=0on 8.5, blocking multipart at the edge) and understand that they narrow the attack surface rather than close it. The mitigations post has the configuration snippets and the trade-offs. - Look for signs of compromise on anything that was exposed for long. Exploitation was underway within hours of the release, and a server patched on day two may already have a web shell on it. Recently modified
.phpfiles, unexpected cron entries, outbound connections from the web user and new processes spawned by PHP workers are the first things to check. - Plan the version move if you are on 8.1 or older. The backport branches and vendor fixes buy time; they do not change the fact that the branch gets no further fixes. PHP 8.2 joins that list on 31 December 2026.
What this means for MassiveGRID customers
Patching is part of the service on our managed products. Managed cPanel hosting, managed WordPress hosting, managed cloud servers and the support plans that include OS updates and security patches all cover PHP security releases, and the cPanel platforms additionally run Imunify360, whose web application firewall shipped rules for the known PHP2Shell exploit pattern. If you want written confirmation of the patch status of your specific server, open a ticket and ask for it; that is a reasonable thing to want for your own change records.
On MassiveGRID PaaS, built on Virtuozzo Application Platform (formerly Jelastic), PHP runs inside the application server container you chose (Apache PHP, NGINX PHP, LiteSpeed). Updating means redeploying that node to the patched tag of the same branch once it is published, which keeps your data volumes and the files you marked for preservation. The patching guide has the steps.
On self-managed Cloud VPS and Dedicated VPS, the operating system and everything on it is yours to maintain, and this advisory is exactly the case automated security updates exist for. If you have unattended-upgrades or dnf-automatic running, the fix arrives on its own as soon as your distribution publishes it; if you do not, now is the moment to run the update by hand and then set that up. A support plan is the alternative if you would rather we did both.
Frequently Asked Questions
Is my PHP version affected by CVE-2026-109618 and CVE-2026-109619?
Almost certainly, if it serves web requests. Every PHP 8.2, 8.3, 8.4 and 8.5 release before 8.2.35, 8.3.36, 8.4.27 and 8.5.12 is affected. PHP 8.1, 8.0, 7.4 and older are affected too but get no release from php.net; the security team published source-only backport branches for 7.4, 8.0 and 8.1, and some distributions backport the fix into the version they ship. The CLI is the same engine but is not reachable through a web request in the usual way.
Is PHP2Shell being exploited in the wild?
Yes, by the afternoon of 21 October 2026. Cloudflare said it was seeing early attack attempts and enabled emergency managed WAF rules on every plan, watchTowr and Huntress reported reproducing CVE-2026-109618, and exploit code claiming to implement the chain was circulating publicly, some of it from untrusted sources. Treat any unpatched, internet-facing PHP server as actively targeted.
I run PHP-FPM behind nginx, not mod_php. Am I safe?
No. You are in a better position than an Apache mod_php server, because FPM kills a child whose startup fails, which blocks the simplest path for CVE-2026-109618. But the PHP advisory validated the session upload progress path of CVE-2026-109619 on FPM, and an out-of-memory condition after startup can still reach the first bug. Patch today; the FPM architecture is not a mitigation.
Does my WAF or Cloudflare protect me?
Partly, and only for traffic that actually goes through it. Cloudflare, Bunny Shield, Imunify360 and the OWASP Core Rule Set have rules matching the known exploit pattern, which raises the bar for opportunistic scanners. They do not fix the bug, they do not stop variants, and they do nothing if the origin server accepts connections directly. Use a WAF as a layer while you patch, not instead of patching.
Will PHP 8.1, 8.0 or 7.4 get a fix?
Not as a release. The PHP project published minimal source-only backport branches for 7.4, 8.0 and 8.1 on GitHub for people who build from source or have no LTS vendor. Ubuntu is backporting the fix into the 8.1 package on 22.04 and, through Ubuntu Pro, into older releases; Red Hat typically backports into its supported module streams; CloudLinux has said it is preparing alt-php packages. Debian 11 users have no free fix because Debian LTS for bullseye ended on 31 August 2026.
Do I need to restart anything after installing the update?
Yes. PHP workers keep the old code in memory until they are restarted. Restart PHP-FPM, do a full restart of Apache for mod_php (a graceful reload is not enough), recreate Docker containers from the new image, and restart Laravel Octane, queue workers and any other long-running PHP process. Then check that no process still maps a deleted library.
Are command-line PHP scripts and cron jobs affected?
They are the lowest-risk case: the CLI does not parse HTTP request bodies and runs one script per process, so neither attack path is reachable in the usual way. The binary and shared engine are the same, though, so update it with everything else rather than carving out an exception.
Why is it called PHP2Shell?
The name comes from the banner of a leaked exploit tool whose screenshots circulated on 20 October, a day before the fix, after details escaped the coordinated disclosure embargo. It is a nickname for the exploit chain that combines the two CVEs, not an official name from the PHP project.
Security patches applied for you, with a 100% uptime SLA
MassiveGRID managed cloud servers include 24/7 monitoring, OS and security patch management, firewall configuration and incident response on a high-availability platform in New York, London, Frankfurt and Singapore. Advisories like this one are handled by our engineers, so your team reads the write-up instead of writing the runbook.
Explore Managed Cloud ServersFurther Reading
- php.net: Security advisory, critical remote code execution vulnerabilities, update now (21 October 2026)
- GitHub advisory GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)
- GitHub advisory GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)
- php.net: downloads for PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35
- Tenable: php2shell frequently asked questions, exploitation status and exposure estimates
- Mattias Geniar: distribution package status for the PHP fixes, updated through the day
- MassiveGRID: how to patch PHP for CVE-2026-109618 and CVE-2026-109619 on every platform
- MassiveGRID: mitigations for servers that cannot patch yet