On October 21, 2026 the PHP project shipped an out of band security release for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, together nicknamed php2shell. Both are rated CVSS v4.0 9.2. Both are unauthenticated remote code execution against any PHP that serves web requests: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed. The details leaked a day before the planned disclosure, CISA issued an alert urging immediate patching, and Cloudflare reported early attack attempts on the morning of October 21, hours before the patch shipped.
| CVE-2026-109618 | State corruption when PHP runs out of memory partway through a request |
|---|---|
| CVE-2026-109619 | Stale request state reused by a later request on the same worker (use after free) |
| Severity | CVSS v4.0 9.2, unauthenticated remote code execution as the web worker |
| Fixed releases | PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 |
| End of life branches | 7.4, 8.0, 8.1: source backport only, no release |
| Disclosure | Leaked October 20, patched out of band October 21 |
This was not a bug Emphere discovered, and we are not claiming otherwise. The fix is upstream work by the PHP core team. What we did is the part upstream deliberately left undone.
The gap: the fix exists, the build does not
The official releases cover 8.2 and newer. Everything older is end of life. For 7.4, 8.0, and 8.1 the PHP security team did something unusual and genuinely helpful: they published a minimal source backport of the fix. But a source backport is a patch file. It assumes you will download the matching release tarball, apply the patch, and compile PHP yourself, on every architecture you run, with the right extensions, and then stand behind the result.
A large amount of production PHP is sitting on exactly these versions. The teams running it are not careless. They are on 8.1 because moving a live fleet across a major PHP version is a quarter of work, not a weekend. The leaked exploit does not care which of those two camps you are in.
The patch was the easy part. Everyone got that on Wednesday. The hard part is the version you cannot move off of.
What we built
We took the official upstream security commit for each end of life branch and did the mechanical, boring work around it that is easy to get wrong:
- Fetched the official PHP release tarball from php.net over TLS and verified it against php.net's published SHA-256.
- Applied the exact upstream security commit, unmodified.
- Built on a pinned toolchain with a realistic web facing extension set (FPM, CLI, session, mbstring, curl, openssl, opcache, pdo_sqlite).
- Ran the regression tests that ship inside the fix, plus the session and upload surface where the two CVEs live.
- Recorded the applied patch, the build log, and the test results next to the binary, and published a checksum for every artifact.
| Build | What it is |
|---|---|
php-7.4.33-emphere-backport | Official 7.4.33 tarball plus the upstream security commit, built and tested |
php-8.0.30-emphere-backport | Official 8.0.30 tarball plus the upstream security commit, built and tested |
php-8.1.34-emphere-backport | Official 8.1.34 tarball plus the upstream security commit, built and tested |
Every artifact carries its provenance: the security.patch that was applied, the build.log, the test-summary.txt, and a BUILD_INFO stamp with the source version, the patch hash, and the builder image. Each build also ships with a CycloneDX SBOM. The builds are for Linux on amd64 today. The whole thing is reproducible from the repository. You do not have to trust us. You can rebuild it and diff.
What this is, and what it is not
Being precise matters here, because a backported binary is easy to oversell.
- It is the official upstream fix, applied to the official release source, built and tested so you can deploy it instead of running a compiler yourself.
- It is not a patch written by Emphere. The security logic is the PHP core team's. We did not change it.
- It is not, yet, verified against a working exploit. A real proof run is how we normally sign off a fix: the vulnerable build pops, the fixed build does not, and reverting the patch brings the pop back. That is the next thing we are doing here. Until it lands, the claim is "built and tested," not "proven against the exploit."
- It will not quiet a version based scanner. The version string stays 7.4.33, 8.0.30, or 8.1.34, so a scanner that matches on version will keep listing both CVEs. The applied patch and the
BUILD_INFOstamp are your evidence that the fix is in.
If you are below 7.4, there is no official backport at all. Take that PHP off the public internet, put it behind a WAF or VPN, and plan the move. We can help with that too.
Mitigation while you roll this out
The upstream interim guidance still applies and costs you nothing:
- For CVE-2026-109619, set
session.upload_progress.enabled = Offinphp.iniand restart every worker. This closes the one confirmed path for that bug, not the bug itself. - Treat a container or cgroup memory limit as an availability boundary only. It is not a fix.
- Patch internet facing systems first. Inventory the PHP you forgot about: control panels, bundled CMS runtimes, vendor appliances.
Get the builds, or get a hand
The signed artifacts, their checksums, SBOMs, and the exact build harness live in one public repo: github.com/emphereio/php-eol-backports. Grab a build from the latest release, verify the checksum and the cosign signature (the same packages-signing key behind app.emphere.io/cosign.pub), and deploy. Prefer to build it yourself? The repo rebuilds every artifact from the official php.net source in one command, so you can diff ours against yours.
On PHP 8.1 or older and not sure what your move is? Talk to us and our team will jump on a call quickly to help you sort it out. No charge, no pitch required.
Talk to usSources: the PHP project's October 21, 2026 security release and advisories; CISA's alert of the same date. CVE identifiers CVE-2026-109618 and CVE-2026-109619.

