This is a special follow-up to this morning’s brief, which went out while PHP’s emergency release was still pending. The patches shipped at 14:00 UTC on October 21, the GitHub advisories are now public, and the picture has moved quickly: exploitation attempts were being reported before the fix was even available. Everything below is drawn from the PHP project’s own advisory, the two GHSA entries, and the researchers who were first to confirm the bugs.
The short version
Two critical bugs in the PHP interpreter itself, not in any framework or application, allow unauthenticated remote code execution against essentially any PHP installation serving web requests. Both are rated CVSS v4.0 9.2 by PHP. Fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. There are no complete mitigations short of updating. Cloudflare reported early attack traffic at 07:43 UTC on October 21, roughly six hours before the patch, and watchTowr says it has observed in-the-wild exploitation attempts against both CVEs. If you run PHP anywhere that accepts HTTP requests, treat this as a patch-today event.
“Put simply: if you have not applied the patch, your deployment of PHP is vulnerable.” — watchTowr
How we got here: the timeline
October 20. A post on Hacker News claimed two critical PHP RCE flaws would be disclosed on October 22, ahead of any patch. The post was removed, but screenshots spread, along with screenshots of an exploit tool styled “PHP2Shell” that claimed to work against PHP 5.4.0 and later. watchTowr publicly confirmed the leaked details were real and under embargo. That evening the PHP security team published an advance notice of an out-of-cycle release for October 21 at 14:00 UTC, pulling disclosure forward by a day.
October 21, 07:43 UTC. Cloudflare CTO Dane Knecht said the company was seeing early attacks and updating mitigations as new vectors appeared.
October 21, ~14:00 UTC. PHP published its advisory and the four fixed releases, plus minimal source backports for the end-of-life 7.4, 8.0 and 8.1 branches. The UK NCSC issued an alert, and CISA published an alert titled “Critical Vulnerabilities in PHP Require Immediate Patching.”
October 21, 14:19 UTC. watchTowr published its technical write-up and reported exploitation attempts in the wild.
The two bugs
CVE-2026-109618, “RCE via OOM corruption” (GHSA-w8hw-w9fx-j79w). PHP handled out-of-memory conditions by calling longjmp() to abort the request. In some code paths, request memory is reachable before initialization has finished; an allocation failure at that moment leaves partially initialized data behind, and request shutdown then reads or branches on it. The failed allocation does not have to be related to the memory that ends up corrupted. The advisory’s primary trigger is multipart parsing: a request without a usable Content-Length can pass the initial post_max_size check, and a single part can carry an unbounded number of headers whose in-memory representation is far larger than the wire form. Empty file controls do not count toward max_file_uploads but still allocate metadata, and nested field names multiply the work. Full RCE over HTTP was demonstrated against Apache mod_php with default limits. PHP-FPM is assessed as susceptible from source analysis, though no complete exploit was demonstrated; FrankenPHP and LSAPI are considered likely susceptible but not validated. The fix removes the longjmp() OOM path entirely: a soft OOM is now raised at the next VM safe point, and a hard OOM calls _exit() past a higher threshold.
CVE-2026-109619, “RCE via stale global state” (GHSA-6wmf-4rv5-p3rp). In persistent worker models, PHP’s global state (error, session, object and extension state) can retain pointers into memory owned by a previous request. That state is supposed to be cleared before the request heap is freed, but a fatal error such as OOM or “Maximum execution time exceeded” can abort an operation before its reset runs, and nonfatal diagnostics emitted late in shutdown can repopulate error state after it was cleared. The next request on the same worker can then read, free or branch on a dangling pointer before normal initialization replaces it. Three confirmed consumers are described: INI diagnostics raised while applying per-request settings (reachable via .htaccess and php_value directives on mod_php, and conditionally on FPM if the frontend passes PHP_VALUE/PHP_ADMIN_VALUE); session upload progress handling, which runs before ordinary session initialization, is enabled by default and does not require session_start(); and, on PHP 8.5 only, the new fatal_error_backtraces feature, which is the confirmed RCE path on mod_php. Exploitation requires a producer request and a consumer request to land on the same worker plus a cooperative heap layout, which is why both CVEs carry AC:H and AT:P in their vectors.
Both advisories share the vector CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H and credit the same reporters: lcfr-hax, sagitzadik-wiz (Wiz), tomash-areion and amyb-oai. The remediation was developed by arnaud-lb, iluuu1994, bukka and ndossche.
“Updating to a PHP release containing the patch to this vulnerability is the only complete mitigation.” — php/php-src advisory GHSA-w8hw-w9fx-j79w
Who is affected
PHP’s advisory is blunt: all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The project considers mod_php the highest-risk configuration because there is a demonstrated exploit where an unauthenticated request triggers the bug before any application code runs. Every version from PHP 5 onward is believed to be affected; only 8.2 through 8.5 receive official fixed releases. PHP 8.2 itself reaches end of life on December 31, 2026. For scale, Silas Cutler estimates over 1.3 million internet-exposed hosts are potentially vulnerable, a Shodan query by Henk Poley counts over 1.9 million hosts advertising PHP, and Mallory counted roughly 884,000 hosts whose banners show PHP 8.1 or older. These are banner counts, not confirmed vulnerable systems, but they illustrate the exposure.
“The PHP situation will lead to a mass of incidents – it’s one of the biggest vulns in years.” — Kevin Beaumont, via Help Net Security
Exploitation status
Before the patch, watchTowr and Huntress both said they had not seen exploitation. That changed on the morning of October 21: Cloudflare reported early attacks at 07:43 UTC, and SecurityWeek’s updated story notes firms observed exploitation attempts, some before the fixes landed. watchTowr’s post-patch write-up lists CVE-2026-109619 as exploited in the wild. Sansec, which tracks e-commerce attacks, said it expects mass exploitation now that both the patch and the write-ups are public, and noted that the circulating PHP2Shell tool combines both CVEs into a single unauthenticated attack. As of the reports I could verify, neither CVE had yet appeared in CISA’s KEV catalog, though CISA did publish a standalone alert; I was unable to load the alert page itself to confirm its contents.
“We expect mass exploitation now that the patch and the writeups are public.” — Sansec
Patches and where to get them
Upstream: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, with source and Windows binaries on php.net. Linux distributions and LTS vendors received the patches in advance. Ubuntu has fixes for every supported release (php8.5 for 26.10 and 26.04, php8.3 8.3.6-0ubuntu0.24.04.13 for 24.04, php8.1 8.1.2-1ubuntu2.28 for 22.04) and ESM builds for 20.04 back to 14.04. AlmaLinux had patched packages in testing on October 21. The PHP team specifically warned that the volunteer-maintained rpms.remirepo.net would not have updates on release day and urged those users to switch to distribution packages or build from source. For anyone stuck on 7.4, 8.0 or 8.1 without a vendor, PHP published minimal source-only backport branches on GitHub (PHP-7.4-CVE-2026-109618-109619 and siblings). After updating, restart every worker; a patched binary on disk does nothing for a worker that is still running the old code.
If you cannot patch in the next hour
PHP’s advisory is explicit that the measures below reduce exposure to specific paths but do not make an installation safe. PHP 8.6 release manager Joe Ferguson put it more bluntly: “ini settings won’t save you.”
For CVE-2026-109618, set memory_limit=-1 in a way applications cannot override (for example php_admin_value in the FPM pool or Apache config) and confirm nothing re-imposes a finite limit. This removes the controllable memory-limit failure but not an underlying allocation failure. Set a low post_max_size (8M where uploads are not needed, 32M otherwise) and keep upload_max_filesize below it. Enforce limits at the web server or proxy for decoded request size, field count, multipart part count, header count and nesting depth, and make sure those limits apply to requests with no usable Content-Length. Use a container or cgroup limit as the availability boundary, and do not substitute RLIMIT_AS or RLIMIT_DATA, which themselves trigger the vulnerable path.
For CVE-2026-109619, set session.upload_progress.enabled=0 in php.ini or pool configuration (not via ini_set() or .user.ini) and restart every worker. On PHP 8.5, also set fatal_error_backtraces=0. Remove invalid or deprecated per-request INI settings that emit diagnostics before initialization; suppressing them with error_reporting, display_errors or @ does not help. Consider pm.max_requests=1 on FPM. Fix attacker-reachable fatal errors and execution timeouts.
Sansec adds two blunter options for sites that cannot patch at all right now: block multipart/form-data at the web server (breaks uploads and some checkout flows), or reject every method except GET and HEAD until the update lands. Cloudflare has WAF rules for the known vectors available on all plans including free, but both Cloudflare and Sansec stress that this only covers traffic that actually routes through the proxy, and that the attack executes inside PHP before any application-layer rule can see it.
What to do now
Inventory every host running PHP, including the ones nobody remembers: internal dashboards, admin panels, bundled appliances, Docker images built months ago. Update to a fixed release and restart workers; do not stop at the package upgrade. If you are on mod_php, move to the front of the queue. If you are on 8.1 or older, get a vendor backport, apply the PHP source backport, or take the system offline, which is what the NCSC has recommended for anything that cannot be fixed immediately. Then look backward: with attack traffic observed before 08:00 UTC on the 21st, any exposed PHP host that was unpatched through the day should be reviewed for signs of compromise, starting with unexpected processes spawned by the web server user, new files in writable directories, and outbound connections from the web tier.
This follow-up reflects primary sources available as of the evening of October 21, 2026 (UTC).
Primary sources:
- PHP.net security advisory: Critical remote code execution vulnerabilities, update now
- GHSA-w8hw-w9fx-j79w (CVE-2026-109618, RCE via OOM corruption)
- GHSA-6wmf-4rv5-p3rp (CVE-2026-109619, RCE via stale global state)
- PHP.net advance notice, October 20
- watchTowr: PHP Remote Code Execution (“PHP2Shell”)
- Sansec: PHP2Shell
- Ubuntu: php2shell fixes available
- AlmaLinux: patched packages in testing
- CISA alert: Critical Vulnerabilities in PHP Require Immediate Patching
- SecurityWeek · Tenable FAQ · Check Point · Help Net Security