DEV Community

Cover image for Two Critical PHP Bugs Leaked Early, and Four Branches Now Carry the Fix
Taha Echakiri for NeticsLabs

Posted on Originally published at blog.neticslabs.com

Two Critical PHP Bugs Leaked Early, and Four Branches Now Carry the Fix

TL;DR

  • PHP is the scripting language that runs a large share of the web, and on 21 October 2026 two critical remote code execution vulnerabilities in it were fixed in versions 8.5.12, 8.4.27, 8.3.36 and 8.2.35.
  • The pair is known as php2shell, both identifiers score 9.2, and the bugs sit in memory management and error handling, code that nearly every request touches.
  • The first bug interrupts a request at the memory limit and turns that interruption into code execution; the second leaves stale state in a worker that a later request reuses.
  • The embargo broke about two days before the planned 22 October release: the CVE identifiers circulated at around 15:00 UTC on 20 October with a wrong 10.0 score, PHP moved its release forward by one day, and a distributor published fix images at 07:41 UTC on 21 October.
  • Four versions carry the fix, released at 13:30 UTC on 21 October, and distribution packages follow on each distributor's own schedule.
  • Where the update waits, PHP's own advice is to remove the memory limit through php_admin_value, lower post_max_size and enforce request limits at the proxy.
  • The first signs of the memory bug surfaced during a 2024 external audit, its full impact became clear only in August 2026, and the PHP Foundation calls the delay a structural failure caused by the security team's decision process and its lack of resources.

What php2shell breaks

CISA calls the pair php2shell. Both vulnerabilities end in the same place, which is arbitrary code running inside a PHP worker with the permissions that worker already holds, reached by a request that carries no credentials at all. Every PHP installation that answers web requests is exposed, and that set includes PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.

PHP's own notice ranks mod_php as the highest risk. Under mod_php a demonstrated exploit fires before any application code runs, so a framework patch, an application firewall rule inside the app, or a hardened CMS plugin never gets the chance to look at the request. AWS described the blast radius as bounded to the affected worker and its application permissions, with no cross-customer propagation established at the time of its bulletin, which is the reassuring half of the statement and also its limit.

Capture of the php.net release archive showing the 21 October 2026 security notice

The php.net release archive (php.net/archive/2026.php, retrieved 2026-10-21), which lists PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 as the versions fixing two critical vulnerabilities allowing unauthenticated remote code execution.

A memory limit that turns into code execution

CVE-2026-109618 is remote code execution through out-of-memory handling. PHP enforces the memory_limit setting by aborting a request that exceeds it, and that abort can arrive while internal request data is only partially initialised, for example during the parsing of a form-based file upload. PHP can later treat that partially initialised data as valid, which corrupts memory.

The interesting part for anyone running shared hosting or a multi-tenant platform is that the trigger is a resource limit, where a limit normally exists to protect the server from a greedy script. Here the path that enforces it becomes the attack surface itself, which is why PHP's first mitigation for organisations that cannot update immediately is to remove the trigger by setting memory_limit to -1 through php_admin_value in the pool or the Apache configuration.

That mitigation buys time and carries its own cost. An unlimited memory limit on a PHP worker means one badly written request can consume the machine, so the second half of PHP's advice matters as much as the first: set post_max_size to 8M where uploads are unnecessary or 32M where they are needed, keep upload_max_filesize below it, and enforce decoded request size, field count, multipart part count, header count and nesting depth at the web server or the proxy.

Stale state in the same worker

CVE-2026-109619 is remote code execution through stale global state, and its shape is different. Internal state owned by one request survives after the memory behind it has been freed, which PHP names as happening after a fatal error. The worker that handled the failed request goes on to serve the next one, and that later request can use the stale state before normal initialisation resets it.

The PHP Foundation's post reports that a use-after-free and a worker crash were confirmed, and that the reporter demonstrated remote code execution against a real-world application running on Apache with mod_php. The detail that matters operationally is the word worker: the Foundation writes that a later request handled by the same worker could then use the freed memory, and that remote code execution was also confirmed on PHP-FPM through application-level code paths.

Netics editorial timeline of the PHP disclosure, from the leak to the release

Netics editorial timeline of the disclosure: the CVE identifiers circulating at 15:00 UTC on 20 October with a wrong 10.0 score, the pre-announcement at 19:30 UTC, a distributor publishing fix images at 07:41 UTC on 21 October, and the release at 13:30 UTC.

The embargo broke two days early

Coordinated disclosure works on a timetable that distributors need in order to have packages ready on the day. Here the identifiers leaked about two days before the planned release date, and the release itself moved forward by one day. The PHP Foundation's account places the first break at around 15:00 UTC on 20 October, when the two CVE identifiers began circulating on forums and social media with a wrong release time and a wrong CVSS score of 10.0. The real score is 9.2.

The project responded by publishing its pre-announcement at 19:30 UTC and by moving the release from 22 October to 21 October at 14:00 UTC, because distributors were still packaging the fix and an immediate release would have left users without an update path. The second break followed right after the pre-announcement, when Calif, one of the reporting firms, published a proof-of-concept video by mistake at around 20:00 UTC on 20 October and copies spread on social media.

The third break came from inside the process: at 07:41 UTC on 21 October, more than six hours before the coordinated release, Chainguard published built images containing the fix. Anyone could study the fix in binary form while every other PHP user was still waiting. PHP monitored the proofs of concept that appeared and reported no functional exploit at the moment of release, which is a narrow statement covering a short window. The case for publishing minor vulnerabilities in the open is covered in a separate Netics article. Both policies share the same scarce input, which is a maintainer with enough hours to answer.

What to patch today, and the four versions that fix it

The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released at 13:30 UTC on 21 October 2026 according to CERT-EU, half an hour before the 14:00 UTC slot the PHP Foundation had announced. The affected ranges are 8.5.0 to 8.5.11, 8.4.0 to 8.4.26, 8.3.0 to 8.3.35 and 8.2.0 to 8.2.34. Distribution packages follow on each distributor's own schedule, so the package on a managed server can trail the upstream release, as the AWS timeline below shows.

PHP 8.1 and older sit outside every one of those ranges because the project stopped supporting them. AWS lists PHP 5.4 to 8.1 as having no upstream fix and requiring migration, and notes that its own Amazon Linux packages and WorkMail upgrade were targeted for 22 October while Elastic Beanstalk platform version v4.13.12 shipped on 21 October. PHP also published minimal source backports for 7.4, 8.0 and 8.1 for teams that build from source or have no access to a long-term support vendor.

CERT-EU points at one more category that inventories usually miss: third-party software that embeds PHP and never exposes it as a package, which the NCSC-NL repository tracks. That is the same problem CISA named in its alert, where PHP is often a component of other software and its prevalence may not be directly observable.

Netics editorial banner on what one unauthenticated request reaches

Netics editorial banner placing both CVEs at 9.2 and naming the shared mechanism: memory management and error handling, which every PHP request traverses, with mod_php reachable before application code runs.

What to do when the update waits

Some systems cannot take an update the same day, and the interim advice is specific enough to act on. Removing the memory limit through php_admin_value closes the trigger for CVE-2026-109618, and PHP notes that an underlying allocation failure can still reach the vulnerable path, so the mitigation reduces exposure and the installation stays vulnerable until it is patched. PHP also recommends a container or cgroup limit as an availability boundary, and warns against substituting RLIMIT_AS or RLIMIT_DATA, which can cause the vulnerable allocation failure.

The second layer sits in front of PHP. A web application firewall may provide some protection until systems are updated, according to CISA, and PHP's own guidance pushes request limits to the server or the proxy. Both reduce the space an attacker has to work in until the patch is applied.

The third layer is detection, and it is the one that tells you whether the day went badly. CISA asks defenders to watch for PHP worker processes launching shells or downloading tools, which is a short rule to write into whatever monitoring already exists and a reliable signal that a worker crossed from parsing requests into running commands.

Why the engine fix shipped in October 2026

The disclosure history explains the delay better than any severity score. In 2024 PHP went through its first external security audit in years, funded by the Sovereign Tech Agency, organised through OSTIF and carried out by Quarkslab. While fixing one of the issues that audit reported, a core developer contracted by the PHP Foundation found the first signs of the out-of-memory problem. A potential exploit was theorised in 2024, no concrete vector was found at the time, and other issues with clearer impact took the attention.

The picture sharpened through 2026. On 11 August a researcher at Calif reported an unconditional remote code execution, and OpenAI independently reported the same root cause. Further attack vectors came from Wiz on 24 August and from OpenAI on 18 September, and from 11 August the fix became the team's top priority. The Foundation writes that the bugs were hard to fix without breaking compatibility, hurting performance or forcing changes on the large ecosystem of third-party extensions, and it calls the delay a structural failure caused by the security team's decision process and its lack of resources.

The volume is the part that shapes the next year. The security team has published 15 CVEs since 1 July and worked through more than 100 reports that turned out to be invalid, duplicates or not reproducible. AI tooling helps validate reports and group the ones that share a root cause, and a person still makes every call and writes every patch. For an operator the lesson is unglamorous: the runtime under a large share of the web rests on a small team of core developers, several of whom could work on this issue full time only because of Foundation funding, and the day the embargo breaks is a bad day to discover that nobody knows how many PHP installs the company runs.

Capture of the PHP Foundation post of 21 October 2026 on the release and its disclosure timeline

The PHP Foundation's post of 21 October 2026 (thephp.foundation, retrieved 2026-10-21), which announces the release, describes the two vulnerabilities and records the disclosure timeline that moved the release forward by a day.


Originally published on the Netics blog.

Top comments (0)