At 14:00 UTC today the PHP project released 8.5.12, 8.4.27, 8.3.36 and 8.2.35. The four releases close two critical remote code execution flaws, CVE-2026-109618 and CVE-2026-109619, both scored 9.2 by the PHP Foundation. On Apache with mod_php, the project states that an unauthenticated request can trigger the first one with default settings, before a single line of your application code runs. Your framework, your authentication, your WAF rules: none of it is in the path.
That part is already everywhere. The part nobody has measured is the one that decides whether this is an inconvenience or an incident for you: does a patch actually reach your server? We spent today measuring that. The answer is not a function of how old your PHP is. It is a function of who you buy your PHP from.
TL;DR
- Upstream patched four branches. Canonical patched seven. Ubuntu shipped fixes today for
php5,php7.0,php7.2,php7.4,php8.1,php8.3andphp8.5. PHP 5.5 has been dead upstream since July 2016 and it got a fix this afternoon, behind an Ubuntu Pro Legacy Support subscription. - 36.4% of the WordPress population runs a PHP branch with no upstream release. We cross-joined the WordPress.org PHP share API against endoflife.date: PHP 7.4 alone is 16.1%, PHP 8.1 is 10.7%. On 1 January 2027 PHP 8.2 joins them and the figure becomes 60.2%.
docker pull php:7.4-apachestill works. That image was last pushed on 15 November 2022 and is built with--with-apxs2, meaningmod_php: the exact configuration the advisory calls highest risk. The patchedphp:8.2-apachelanded at 17:18 UTC, three hours and eighteen minutes after the release.- 0 of 100 Irish sites disclose a PHP version. We proved 12 of them run PHP anyway. Not one tells you the branch, and none of the 100 tells you the SAPI, which is the thing that decides whether you are exploitable before authentication.
- The official mitigation is to remove your memory limit. PHP recommends
memory_limit=-1as a stopgap, inverting fifteen years of hardening advice. If that surprises you, your runbook needs reading before your scanner does.
What actually shipped
The two flaws sit in the parts of PHP that every single request touches: memory management and error handling.
CVE-2026-109618, RCE via OOM corruption. PHP uses longjmp() to abandon a request that hits its memory limit. In some windows the request memory is reachable but not fully initialised, and the early exit leaves it in a state that request shutdown then reads or branches on. Several multipart parsing weaknesses let an attacker reach out-of-memory while staying inside the apparent limits, including bodies with no usable declared content length and parts carrying an unbounded number of headers.
CVE-2026-109619, RCE via stale global state. Worker-level globals covering error, session, object and extension state can keep pointing at memory owned by a request that has already been freed. A fatal error or a timeout abandons the operation before its matching reset, and a later request on the same worker consumes the stale pointer before initialisation replaces it. Exploitation needs a producer request and a consumer request on the same worker, which is exactly what a long-lived FPM pool provides.
The SAPI you run decides your exposure, and the gradient is steep. Apache with mod_php invokes request shutdown unconditionally, even when request startup failed, so the whole chain completes before application code begins: the PHP Foundation reports a demonstrated unauthenticated exploit here with default settings. FPM exits the child when startup fails, which blunts the application-independent path, but remote code execution was still confirmed through application-level code paths. FrankenPHP calls shutdown unconditionally like mod_php, and LiteSpeed’s LSAPI models FPM. The official advisory names all five as at risk.
Measurement one: how much of the install base has an upstream release
WordPress.org publishes the PHP version share of every install that phones home, at api.wordpress.org/stats/php/1.0/. It is the largest free, first-party view of real-world PHP deployment available to anyone. We pulled it this afternoon and cross-joined every branch against the endoflife.date PHP dataset.
| Status | Branches | Share of WordPress installs |
|---|---|---|
| Upstream release available today | 8.2, 8.3, 8.4, 8.5 | 63.6% |
| No upstream release (end of life) | 8.1 and everything below | 36.4% |
| Not in the EOL dataset | 4.4, 8.6 | 0.026% |
Inside that 36.4%, the distribution is not a long tail of museum pieces. PHP 7.4 is 16.1% on its own, one in six WordPress sites on a branch whose last release was 3 November 2022. PHP 8.1 is 10.7% and only went end of life on 31 December 2025. PHP 8.0 adds 3.8%. Everything from PHP 5.1 to 7.3 together comes to 5.7%, so the genuinely ancient estate is the small part of the problem. The bulk is sites that were current eighteen months ago.
Then there is the date. PHP 8.2 is 23.8% of the population and its security support ends on 31 December 2026. Nothing changes on the server that night. The share of WordPress sites with no upstream release simply moves from 36.4% to 60.2%, because a support window closed. If you are planning a Q1 budget, that is the line item.
Two branches, 4.4 and 8.6, are absent from the EOL dataset and we excluded them rather than guessing. 8.6 is a release candidate, so 0.018% of the WordPress population is running a prerelease PHP in production.
Measurement two: your vendor decides, not your version
“No upstream release” is not the same as “no patch”, and this is where the received wisdom falls over. We checked what the distributors actually shipped today.
Canonical patched seven source packages. The Ubuntu tracker for CVE-2026-109618 carries a Critical priority and a fixed version for php5 on 14.04 (5.5.9+dfsg-1ubuntu4.29+esm18), php7.0 on 16.04, php7.2 on 18.04, php7.4 on 20.04 (7.4.3-4ubuntu2.29+esm5), php8.1 on 22.04 (8.1.2-1ubuntu2.28), php8.3 on 24.04 and php8.5 on 26.04 and 26.10. PHP 5.5 reached end of life on 21 July 2016 and was patched this afternoon. The four oldest fixes require an Ubuntu Pro subscription, two of them via the Legacy Support add-on; the 22.04 fix for PHP 8.1 is in standard updates and costs nothing.
Debian fixed stable before unstable. Bookworm’s php8.2 is fixed in 8.2.35-1~deb12u1 under DLA-4848-1 and trixie’s php8.4 in 8.4.27-1~deb13u1 under DSA-6574-1. At the time we checked, forky and sid still carried 8.4.26-1 and were marked vulnerable. Running unstable is not running ahead.
Upstream produced source-only backports. The PHP security team pushed three branches to php-src on 18 October, named for both CVEs, covering 7.4, 8.0 and 8.1. The commit message is honest about what they are: “Minimal mitigation for EOL version”. There is no tarball, no announcement release, and no package. They exist for people building from source or stranded without an LTS vendor.
One widely used third-party repository shipped nothing. The advisory urges users of the volunteer-maintained rpms.remirepo.net to move to distribution packages or build from source, stating the repo would not have updates on release day.
So take three servers running identical PHP 7.4 code. On Ubuntu 20.04 with Pro, one apt upgrade fixes it. On a self-built or third-party-repo install, you have a git branch and a compiler. In a container, as we are about to see, you have nothing. Same version number, three different risk positions, and the version number tells you none of it. We have written before about scanners reading the wrong version number; this is the same failure one layer down, in the thing the scanner reads.
Measurement three: the container registry remembers nothing
The official library/php repository on Docker Hub carries 16,043 tags. We queried the ones that matter.
| Tag | Last pushed | Patched today? |
|---|---|---|
php:8.3-apache |
21 Oct 2026, 17:24 UTC | Yes |
php:8.2-apache |
21 Oct 2026, 17:18 UTC | Yes |
php:8.1-apache |
31 Dec 2025 | No |
php:8.0-apache |
22 Nov 2023 | No |
php:7.4-apache |
15 Nov 2022 | No |
Three things follow. First, the patched images landed three hours and eighteen minutes after the 14:00 UTC release, so anyone who rebuilt in that window got a clean build of a vulnerable runtime. Second, php:8.1-apache froze on 31 December 2025, the exact day the branch went end of life: the image library tracks upstream support precisely and silently. Third, and most seriously, php:7.4-apache and php:8.0-apache still resolve and still pull, and nothing warns you. We pulled the image config for php:7.4-apache straight from the registry: built 15 November 2022, PHP_VERSION=7.4.33, configured --with-apxs2 and running apache2-foreground. That is mod_php, the one configuration the advisory singles out as having a demonstrated unauthenticated exploit. A FROM php:7.4-apache line written in 2021 will build you that server tonight.
Canonical will patch PHP 7.4 for a paying customer on 20.04. Docker Hub will hand the same branch to anyone, for free, frozen in 2022, in its worst configuration. Both are “PHP 7.4”.
Measurement four: you cannot see any of this from outside
We probed all 100 domains in our standing Irish sample, the same list behind our recent XSLT and TLS audits, with a single GET over HTTPS following redirects, from one host inside a four-minute window. 73 returned a 2xx. The remainder were twenty 403s, two 503s, a 405, two DNS failures, a certificate mismatch and one timeout.
Zero of 100 disclosed a PHP version. Not one X-Powered-By header carried a PHP string. Seven sites sent an X-Powered-By naming a stack, and every one of them named Next.js, Nuxt or ASP.NET.
That is not the same as no PHP. We proved 12 of the 100 run it: eight carry WordPress markers in their HTML, several expose a WordPress, AIOSEO or WPML generator tag, two set a PHPSESSID cookie, and two are Drupal 10 and Drupal 11. Twelve sites demonstrably executing PHP, and zero of twelve will tell you which branch.
Now the part that matters more. Seventeen of the 100 advertise Apache in a Server header and two advertise LiteSpeed, but Server: Apache does not distinguish mod_php from a reverse proxy in front of FPM. Those are the two ends of today’s risk gradient, and they are indistinguishable from outside. Twenty-two sites send no Server header at all and 27 answer from Cloudflare, so the header you do get describes the edge, not the origin. The SAPI, the one variable that decides whether an attacker needs your application to cooperate, is not externally observable on any of the 100.
Header suppression is good practice and we are not arguing against it. But it has a cost that is rarely stated plainly: the attacker loses a hint and you lose your inventory. If your asset register is “what the scanner found”, your asset register does not contain the field this advisory turns on.
What to do this week
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. If a distribution packages your PHP, take the vendor build; Debian and Canonical had the patches in advance.
- Inventory by SAPI, not by version. Every host, which SAPI, which branch, which supplier. That table is a morning’s work and it is the artefact this incident actually demands.
- Grep every Dockerfile for a pinned PHP tag. Anything on 8.1 or below will build successfully and ship an unpatched runtime. Builds that pass are the dangerous ones.
- If you are on 8.1 or below, price the three routes: vendor LTS with a support subscription, the upstream minimal source backports, or an upgrade. The third is the only one that is still true in six months.
- If you genuinely cannot patch today, apply the official stopgaps. Set
memory_limit=-1where applications cannot override it, usingphp_admin_valuein the FPM pool or Apache configuration. Setpost_max_sizeto 8M without uploads or 32M with them, keepingupload_max_filesizebelow it. Setsession.upload_progress.enabled=0and restart every worker. These reduce specific attack paths; none makes an installation safe. - Put 31 December 2026 in the budget, not the backlog. PHP 8.2 is 23.8% of the WordPress population and its support ends that night.
Note the inversion in step five: the recommended mitigation for a memory-handling flaw is to remove the memory limit, because a controllable limit is the attacker’s trigger. Every PHP hardening guide written in the last fifteen years says the opposite. Advisories are not a genre you skim.
Where we come in
This is the work REPTILEHAUS does between the headlines and the invoice. We run estate audits that produce a real inventory by SAPI, branch and supplier rather than a scanner report that stops at the CDN. We do the PHP 8.1 and 8.2 upgrade work, including the dependency and extension archaeology that is the actual cost of a major version move. We build the DevOps pipelines that make a same-day patch a non-event instead of a weekend, and we have form in measuring the WordPress supply chain rather than asserting things about it.
If you do not know which SAPI your production PHP runs under, that is the finding, and it is a fixable one. Get in touch and we will start with the inventory.
Method and limits
Every figure above was measured today, 21 October 2026, from one host, and is re-runnable in minutes. Sources: the WordPress.org PHP share API, endoflife.date, the Docker Hub v2 tags API, the Debian and Ubuntu security trackers, the GitHub API, and the php.net advisory.
Three limits worth stating. The WordPress.org share covers WordPress installs that report in, not all websites, and WordPress is not representative of PHP generally; treat it as the best free proxy, not a census. Our Irish sample is 100 domains chosen for prominence rather than drawn at random, so the proportions describe that sample and not the Irish web. And one correction we are publishing rather than hiding: a probe this morning recorded a single apex host emitting PHP/7.1.33 through an intermediate hop. Eight hours later it does not reproduce from the same box across repeated GET and HEAD requests on several paths, and the host now answers entirely from a static CDN origin. We report 0 of 100, because 0 of 100 is what reproduces. We have not named the host.
📷 Photo by Taylor Vick on Unsplash


