On Wednesday, 21 October 2026, the PHP project released emergency security updates for two critical vulnerabilities that allow an attacker to run their own code on a web server — without logging in, without an account, and on many servers before a single line of the website’s own code has run. The flaws, tracked as CVE-2026-109618 and CVE-2026-109619 and quickly nicknamed “PHP2Shell,” affect the programming language that powers roughly seven out of every ten websites whose server-side technology is known, including most WordPress, Joomla, Drupal, Magento and Laravel sites. Palo Alto Networks counted more than 22.6 million internet-exposed instances that could be vulnerable. The PHP project’s own release notes are unusually blunt: “There are no complete mitigations, updating is the only safe choice.” This article explains what broke, which versions are affected, when the fixes arrived for each version, why getting them took hours even after release, and what to do if you run a website.
What actually broke: two memory bugs in PHP itself
Both flaws are memory-safety bugs in PHP’s core request handling — the machinery that wakes up every time a visitor requests a page, prepares the request, runs your code, and then cleans up. To escape from fatal errors, including running out of memory, PHP uses an old C mechanism called longjmp() — an abrupt jump that abandons whatever was happening mid-flight. The problem: that jump can leave memory and internal state half-prepared or stale, and later code trusts it anyway. Each CVE is a different way that goes wrong.
CVE-2026-109618 — corruption after an out-of-memory error. While PHP is setting up a request, some of its request memory is reachable before it is fully initialized. If an allocation fails at exactly that moment — an out-of-memory (OOM) error — the longjmp() bailout leaves that memory in an invalid state, and the request shutdown procedure then reads it or branches on it. An attacker who can force an OOM at the right instant can turn that into remote code execution running as the web server account. The confirmed triggers all live in multipart request parsing — the code that handles form submissions and file uploads automatically, before any application code runs. A multipart request with no usable Content-Length header can slip past the initial post_max_size check and keep feeding data; a single form part can carry an unlimited number of headers, which cost far more memory inside PHP than on the wire; and empty file fields combined with nested field names multiply the internal arrays. The fix removes longjmp() from OOM handling entirely, replacing it with a graceful “soft” failure at the next safe point, plus a hard process exit if memory use crosses a second, higher threshold.
CVE-2026-109619 — stale state leaking between visitors. PHP workers are long-lived: one worker process serves request after request. Those workers keep global state — error, session, object and extension state — that points into memory owned by the current request, and it must be reset before that memory is freed. A fatal error (a parse failure, an uncaught error, a failed require, an OOM, a timeout) can abandon an operation before its reset runs; a warning printed during shutdown can even refill state that was just cleared. The request’s memory is then freed while the worker’s globals still point into it — a classic use-after-free. A later request that lands on the same worker can consume that stale state before normal initialization resets it. PHP confirms two concrete cases. On PHP 8.5, the fatal-error backtrace feature stores request-owned state whose reset is, in the advisory’s words, “always missed during shutdown” — this is the basis of the confirmed break-in path on Apache servers. The second case is the session upload-progress feature, and it deserves attention: upload progress is enabled by default, it runs before session_start() and before ordinary initialization, and it does not need your code to call session_start() at all. It can act as the producer of stale state, the consumer, or both. Beyond code execution, the same bug gives attackers a memory-disclosure primitive that can leak passwords, authentication tokens, API keys and certificates belonging to other requests — potentially without breaking in first.
One note for readers comparing coverage: some security firms’ tables assign the upload-progress bug to CVE-2026-109618. PHP’s official advisories assign it to CVE-2026-109619, as this article does. The researchers also caution that the two CVEs together group four distinct memory-safety issues and do not cover every variant — another reason partial workarounds are not enough.
The bugs were found by Calif (Ryan Austin), Wiz Research and OpenAI’s Codex Security team, with Cloudflare also naming Quarkslab among the disclosers — and frontier AI models were used on the discovery side. The OOM weakness was first spotted as far back as 2020 and rediscovered in a 2024 security audit, but went unpatched because nobody had proven it exploitable. Calif and OpenAI reported it as a working remote-code-execution issue on 11 August 2026; Wiz reported in August too, and OpenAI added further trigger paths in September. In other words, the vulnerable code — some of it dating to PHP 5.4 in 2012 — sat in production for years before anyone connected the dots.
Who is most at risk
Both flaws are rated CVSS v4.0 9.2 and both are exploitable without any authentication. (Disregard the “10.0” figure from the initial leak, and a “9.4” quoted by some outlets — 9.2 per flaw is PHP’s official score. The attack complexity is rated high because exploitation needs careful memory grooming and defeating address randomization, which makes it hard — but very far from impossible.) Risk varies sharply by how PHP is wired into your server:
- Apache with mod_php — highest risk. PHP has confirmed complete remote code execution over plain HTTP against mod_php with default limits and a standard multi-worker setup. mod_php runs PHP’s request shutdown unconditionally, even when request startup has already failed — so the attack completes during automatic body parsing and shutdown, before any application code runs. Your login page, your CMS firewall and your security plugins never get a chance to see it.
- PHP-FPM — at risk, with a narrower path. For the OOM flaw, FPM is susceptible on source analysis but no complete exploit has been demonstrated, because FPM kills a child process whose request startup fails. For the stale-state flaw, session-lifecycle remote code execution was validated against FPM — but it needs the application to perform an operation that fatals at the right moment after startup.
- LiteSpeed (LSAPI) — treat like FPM. The advisories say LSAPI models FPM’s behaviour; application-specific exploits are “likely but unvalidated.”
- FrankenPHP — likely exposed to the OOM flaw, since it also runs shutdown unconditionally, but no exploit has been demonstrated.
- php-cgi — named by PHP among the setups at risk, though no separate public exploit analysis exists yet.
The most important implication: the flaw is in the runtime underneath your website, not in your website. Updating WordPress, Joomla or your plugins does not fix it — only updating PHP does. Researchers demonstrated pre-authentication code execution against current WordPress, Drupal and Joomla images, and stress that even a “Hello World” script is vulnerable on an unpatched server. Security plugins cannot save a mod_php site, because the attack finishes before the plugin’s code is ever loaded.
Forty-eight hours of chaos: leak, race, and an early release
The disclosure was supposed to be orderly. Coordinated release was set for Thursday 22 October at 14:00 UTC. Instead, on 20 October at around 15:20 UTC, a Hacker News post citing a “reliable source” claimed two PHP remote-code-execution flaws rated a perfect 10.0, affecting everything from PHP 5 up — while admitting there was no evidence. The post was deleted, but screenshots spread. Security firm watchTowr then confirmed publicly that the flaws were real (and that everyone was supposed to stay quiet until Thursday), saying it had reproduced the OOM flaw in its lab.
At 19:33 UTC on 20 October, PHP broke its own embargo: an advance notice on php.net moved the release forward a day to Wednesday 21 October, 14:00 UTC, publishing the real severity (9.2 for each flaw) and warning operators to prepare — while reserving the right to release even earlier if details leaked or attacks appeared. Within the hour, one of the discoverers mistakenly published a proof-of-concept video showing an exploitation tool run against WordPress, MediaWiki, phpBB, Magento, Joomla, Laravel, Symfony, Drupal and WHMCS; copies spread quickly.
Overnight, the race intensified. At 03:02 UTC on 21 October, Cloudflare switched on emergency firewall rules for all customers, including free plans. At 07:41 UTC, container vendor Chainguard shipped images containing the fix — more than six hours before the coordinated release — drawing sharp criticism from the PHP Foundation, since attackers could now study the patch while everyone else still waited. At 07:43 UTC, Cloudflare’s CTO Dane Knecht posted that the company was “seeing early attacks emerging” and stressed its rules were “a STOPGAP only.” Governments started pulling the plug: the Dutch National Cyber Security Centre took its own website offline as a precaution, and the Dutch parliament, government portals, the Port of Rotterdam, the football association and hospital sites followed, with similar precautionary shutdowns in Finland, France and Belgium, and at Wikimedia. Shortly before 14:00 UTC — at roughly 13:35 UTC — PHP published the advisories and the fixed releases.
Are websites actually being attacked?
Separate what is confirmed from what is merely claimed, because this story attracted both. Confirmed: Cloudflare observed attack traffic targeting its customers before disclosure, and saw attackers mutating their payloads to slip past firewall rules — a sign of serious, adaptive interest rather than casual scanning. watchTowr saw the first in-the-wild exploitation attempts hit its sensors around the time the patches landed, adding that “nobody has been successful to date” — with the warning that this is not expected to last. Not confirmed: as of 21 October, no successful compromise of any website has been publicly verified anywhere; neither CVE had been added to CISA’s Known Exploited Vulnerabilities catalog; Huntress reported seeing no exploitation across its partner base as of Wednesday morning US time, and the Dutch NCSC said it had not yet seen active exploitation even as it took its own site down.
Claims beyond that should be read with care. One vendor announced “confirmed exploitation incidents” early on Wednesday and softened that to probing with “no hard evidence of breaches yet” within hours; another firm’s claim of exploitation “at scale” before the release came with no published evidence. The widely quoted prediction that mass exploitation would begin “within 15 minutes of the release” was exactly that — a forecast by security firm Sansec, not an observation. Exploit code is circulating, but the PHP Foundation said it found no functional exploits among the circulating proof-of-concepts at release time, and the most prominent early proof-of-concept was publicly withdrawn by its own author on Wednesday morning, who re-scored his bug chain as “DEAD… no RCE.” The honest summary: the attack window is open, skilled actors are probing, working public exploits had not been confirmed at publication time — and that is precisely when patching matters most, before they are.

The fixes: what to install for your version
PHP released all four supported branches on Wednesday 21 October 2026, slightly ahead of the announced 14:00 UTC slot. If you run any of these branches, you need at least the fixed version:
| Your current branch | Minimum safe version |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
| PHP 8.1, 8.0, 7.4 | No official release — see below |
Two practical warnings. First, “released” did not mean “installable” on day one. Ondřej Surý’s widely used packages.sury.org had fixed 64-bit packages by about 13:50 UTC but its ARM packages were still old hours later; the older Launchpad PPA that Laravel Forge servers use was still serving the vulnerable 8.3.35 and 8.4.26 at 13:50 and was still building the new ones mid-afternoon; Ubuntu published its security notice at 14:15 but the packages only became visible to apt around 14:50; the popular Remi repository had no updates at all on release day (php.net pointedly suggests its users switch to distribution packages or build from source); and most official Docker php image tags were still empty late in the afternoon. Check that your package source actually offers the fixed build — do not assume yesterday’s update command patched you.
Second, Linux distributions backport security fixes without changing the headline version number. Ubuntu, for example, fixed PHP 8.3 on Noble as 8.3.6-0ubuntu0.24.04.13 and PHP 8.1 on Jammy as 8.1.2-1ubuntu2.28. On a distro-packaged system, a version string that looks “too low” may still be patched — check the package changelog for CVE-2026-109618 and CVE-2026-109619 before panicking, and before celebrating.
The end-of-life problem: PHP 8.1, 8.0 and 7.4 get no official fix
PHP 8.1, 8.0 and 7.4 are end-of-life, and there will be no official PHP release fixing them. Because of the severity, the PHP security team did publish minimal source-level backports for 7.4, 8.0 and 8.1 for people who build PHP themselves or have no support vendor — with a real catch: those minimal patches disable the session upload-progress feature entirely, so upload progress bars stop working. For PHP 7.3 and older, PHP offers nothing at all.
Long-term-support channels are the other route: Ubuntu shipped fixes for every supported release and, through Ubuntu Pro’s ESM, backported all the way down to PHP 5 on Trusty, 7.0 on Xenial, 7.2 on Bionic and 7.4 on Focal; Debian fixed PHP 8.4 (Debian 13) and 8.2 (Debian 12); Zend’s commercial LTS builds of 7.2, 7.3, 7.4 and 8.1 were patched at release time; AlmaLinux was still preparing its backports on Wednesday afternoon and Red Hat had not yet published.
This is where the real exposure sits. Industry telemetry (BitSight) says the most common PHP branch on the internet is the end-of-life 7.4, with more than two million instances, and around 59% of hosts that report a version run PHP 8.1 or older. Those sites now depend on a patchwork of vendor backports — or on finally upgrading. And a deadline looms for the currently “safe” branch too: PHP 8.2 itself reaches end of life on 31 December 2026, so anyone patching to 8.2.35 should already be planning the move to 8.3 or 8.4.
What to do now
- Update PHP to 8.2.35, 8.3.36, 8.4.27 or 8.5.12 — or confirm your distribution package contains the fix by checking its changelog for the two CVE numbers.
- Check the version your website actually uses.
php -von the command line can show a different version from the one serving your site. Verify through your PHP-FPM binary, a phpinfo page, or your CMS: in WordPress, it’s under Tools → Site Health → Info → Server. - Restart every PHP worker after updating. Recycle PHP-FPM pools and Apache, and restart long-running workers such as Laravel Horizon or queue daemons — a mere web-server reload can leave old, vulnerable workers alive.
- On shared hosting, you cannot patch PHP yourself — your host owns the runtime. Check your version (step 2), then ask your host when its rollout reaches your server. Major hosts announced mitigations and patch rollouts throughout Wednesday; GoDaddy told its VPS customers on Tuesday that they must update PHP themselves, warning that the flaws could lead to stolen data, a defaced site or a full takeover. Self-managed VPS and dedicated-server customers everywhere are in the same position: the patch is yours to install.
- If you are on PHP 7.4, 8.0 or 8.1, treat this as the migration deadline. Apply a vendor or source backport today if you have one — and schedule the upgrade to a supported branch now.
If you cannot patch today
PHP’s position is that nothing below makes an installation safe; the steps below only narrow the risk, and PHP core developers were blunter still (“ini settings won’t save you”). With that warning:
- Turn off session upload progress at the server level — set
session.upload_progress.enabled=0in php.ini, the FPM pool or the server config (not inini_set()or.user.ini, which run too late) and restart every worker. Per PHP’s advisory, this blocks the confirmed session attack paths of CVE-2026-109619 — nothing else. Datadog goes further and warns the setting “won’t protect you” in general; read it as a narrow, single-path reduction, never a fix. - On PHP 8.5, also set
fatal_error_backtraces=0and restart — it blocks the confirmed backtrace path only. - For the OOM flaw, an administrator-set
memory_limit=-1(viaphp_admin_value, so applications cannot override it) removes the attacker-controllable out-of-memory trigger, combined with a lowpost_max_size(8M without uploads, 32M with) and proxy-level limits on decoded request size, part counts, header counts and nesting — including requests with no usable Content-Length. Do not useRLIMIT_ASorRLIMIT_DATAas a substitute; they can trigger the very failure the bug needs. Restore a real memory limit after patching. - A web application firewall helps but is a stopgap. Cloudflare’s emergency rules are on by default, free plans included — its own CTO calls them temporary. More drastic community stopgaps include blocking
multipart/form-datarequests where uploads aren’t needed (it will break upload and some checkout forms), or taking the site offline behind a static page that is not served through PHP. The UK NCSC explicitly advises organisations that cannot remediate immediately to consider taking the system offline until it is fully mitigated.
The bottom line
PHP2Shell is the rare vulnerability that matches its headlines: unauthenticated remote code execution in the engine beneath most of the web, confirmed against default configurations, with attacks already probing at the edges and no complete workaround. It is also, for anyone on a supported PHP branch, entirely fixable today: update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, restart your workers, and verify the version your site actually serves. If your site still runs PHP 7.4, 8.0 or 8.1, there is no official patch coming — a vendor backport buys you days, not safety, and the upgrade you have been postponing is now the security fix.
Frequently asked questions
Is my WordPress site affected by PHP2Shell?
If the PHP version on your server is below the fixed release for its branch (8.2.35, 8.3.36, 8.4.27, 8.5.12), yes. The flaw is in PHP itself, not in WordPress, so every WordPress site on a vulnerable PHP version is exposed. Check your version under Tools → Site Health → Info → Server.
I updated WordPress and all my plugins. Am I safe now?
No. Updating your CMS, theme or plugins does not fix these flaws, because they are in the PHP runtime underneath. Only updating PHP itself — or confirming your host/distribution backported the fix — closes them.
Which PHP version do I need to be safe?
PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 or later, depending on your branch. On Debian/Ubuntu-style distribution packages the version number may stay low because fixes are backported; check the package changelog for CVE-2026-109618 and CVE-2026-109619.
Will PHP 7.4, 8.0 or 8.1 get a patch?
Not as an official PHP release — those branches are end-of-life. PHP published minimal source-level backports for 7.4, 8.0 and 8.1 (which disable session upload progress), and vendors such as Ubuntu Pro and Zend LTS provide backported packages. The durable fix is upgrading to a supported branch.
I’m on shared hosting. What can I do?
You can’t update PHP yourself — your hosting provider controls it. Check the PHP version in your CMS or control panel, then contact your host and ask when its PHP patch rollout reaches your server. Most major hosts began rolling out patches and firewall mitigations on 21 October 2026.
Are websites actually being hacked with this right now?
Attack traffic and exploitation attempts have been observed (Cloudflare and watchTowr), and payloads are being adapted to evade firewall rules. However, as of 21 October 2026 no successful compromise had been publicly confirmed, and the most prominent public proof-of-concept was withdrawn by its own author as non-functional. Security firms expect working exploits to appear quickly, which is why patching now — rather than after the first confirmed breaches — is the right move.
Sources
- PHP release announcements and security advisory, php.net — https://www.php.net/archive/2026.php#2026-10-21-5
- CVE-2026-109618 advisory (GHSA-w8hw-w9fx-j79w) — https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
- CVE-2026-109619 advisory (GHSA-6wmf-4rv5-p3rp) — https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
- Cloudflare: emergency WAF protection for the PHP vulnerabilities — https://blog.cloudflare.com/php-vulnerabilities-waf-protection/
- Ubuntu: PHP2Shell fixes available (USN-8948) — https://ubuntu.com/blog/php2shell-vulnerability-fixes-available
- Palo Alto Networks Unit 42 analysis — https://unit42.paloaltonetworks.com/cve-2026-109618-cve-2026-109619/
- Researchers’ incident site — https://www.php2shell.com/




