PHP RCE
Two bugs in how PHP sets up and tears down a request let an unauthenticated request run code on the server. php.net fixed both on 2026-10-21 and asks every PHP user to update immediately.
Every PHP install that serves web requests is at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. php.net rates mod_php highest: it has a demonstrated exploit that triggers before any application code runs.
The two CVEs
CVE-2026-109618 — RCE via out-of-memory corruption. Out-of-memory handling can interrupt PHP while request data is only partly initialized, and request cleanup then treats it as valid.
CVE-2026-109619 — RCE via stale global state. Request-owned state can survive after its memory is freed, and a later request on the same worker can use it before normal initialization resets it.
Timeline
10-20php.net gives advance notice of a release for two critical bugs, both CVSS v4.0 9.2.10-21CERT-EU publishes advisory 2026-018.10-2114:00 UTC — PHP8.5.12,8.4.27,8.3.36and8.2.35ship, with source backports for 7.4, 8.0 and 8.1.10-21Ubuntu USN-8948-1 ships fixed builds for 22.04, 24.04, 26.04 and 26.10.
Fixed versions
- 8.5 →
8.5.12, 8.4 →8.4.27, 8.3 →8.3.36, 8.2 →8.2.35. - PHP 8.1 and older get no release from php.net: use your vendor's backport, or build from php.net's source backports for 7.4, 8.0 and 8.1.
- Distributions received the patches in advance and backport them without changing the PHP version, so a distro build below these numbers may already be fixed.
Partial mitigations
php.net says these reduce exposure to the demonstrated paths but do not make an installation safe. Set them where applications cannot override them, then restart every worker:
memory_limit = -1(CVE-2026-109618), and never cap memory withRLIMIT_ASorRLIMIT_DATA.post_max_sizeof8M, or32Mif you take uploads (CVE-2026-109618).session.upload_progress.enabled = 0in php.ini or the FPM pool, notini_set()(CVE-2026-109619).- PHP 8.5 only:
fatal_error_backtraces = 0(CVE-2026-109619). - Otherwise, keep internet-facing PHP off public networks until it is patched.
References
- php.net security advisory — affected SAPIs, fixed versions, full mitigation list
- GHSA-w8hw-w9fx-j79w · GHSA-6wmf-4rv5-p3rp
- CERT-EU advisory 2026-018
- Ubuntu USN-8948-1 · Debian security tracker
01Am I affected?
A host is likely exposed if any of these is true:
- It serves web requests through PHP-FPM, mod_php, php-cgi, FrankenPHP or LiteSpeed on an upstream build below
8.5.12,8.4.27,8.3.36or8.2.35for its branch. - It runs PHP 8.1 or older without a vendor backport.
- Its distro PHP package predates the vendor's fix. The version alone does not tell you: check the vendor's advisory for the exact build.
- It installs PHP from
rpms.remirepo.net, which php.net said would not have updates on 2026-10-21. - It runs container images built on a PHP release from before 2026-10-21.
Upgrading the package is not the end: PHP workers keep running the old code until they are restarted.
02Install Swamp
The @swamp/cve/php-rce-2026-10 extension finds every PHP binary, PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed install on a host, with its package, and gives each a verdict. Distro builds below the upstream fix that no security tracker marks fixed are reported as check-vendor, never guessed. scan needs no root and changes nothing.
Install Swamp:
curl -fsSL https://swamp-club.com/install.sh | shInitialize a new repo (run this in a new empty directory):
swamp repo initPull the scanner:
swamp extension pull @swamp/cve/php-rce-2026-10Create the scanner, with the SSH user and key it uses for remote hosts:
swamp behavior create @swamp/cve/php-rce-2026-10 php-rce-scanner \
--global-arg sshUser=ubuntu \
--global-arg sshKey=~/.ssh/id_ed25519Am I affected (this machine):
swamp behavior run php-rce-scanner scanMitigate (a dry run unless you pass dryRun=false):
swamp behavior run php-rce-scanner mitigateSet dockerContainer or dockerImage with --global-arg on a new behavior to scan a container or an image instead. Windows hosts are scanned over SSH, and never changed.
03Scan your fleet
Pass a comma-separated list of hosts and the scanFleet method scans each one in parallel over SSH. A host it cannot reach is reported as unreachable, and the rest are still scanned:
swamp behavior run php-rce-scanner scanFleet \
--input hosts=192.0.2.10,192.0.2.1104Scan Results
A real scan of the official php:8.2.34-apache image, running as a container named shop-web:
# PHP RCE Scan Results (CVE-2026-109618, CVE-2026-109619)
1 host(s) scanned: 1 affected, 0 to check with the vendor, 0 patched or without
PHP
┌─────────────────┬────────┬─────────────────────┬────────────┬────────┬──────────┬───────────────┐
│ Host │ PHP │ SAPIs │ Verdict │ Public │ Risk │ Action │
├─────────────────┼────────┼─────────────────────┼────────────┼────────┼──────────┼───────────────┤
│ docker-shop-web │ 8.2.34 │ cli, apache2handler │ vulnerable │ no │ CRITICAL │ rebuild-image │
└─────────────────┴────────┴─────────────────────┴────────────┴────────┴──────────┴───────────────┘
## Installs needing attention
┌─────────────────┬────────────────────────────────────┬────────────────┬─────────┬─────────┬────────────┬───────────────┐
│ Host │ Install │ SAPI │ Version │ Package │ Verdict │ Action │
├─────────────────┼────────────────────────────────────┼────────────────┼─────────┼─────────┼────────────┼───────────────┤
│ docker-shop-web │ /usr/local/bin/php │ cli │ 8.2.34 │ — │ vulnerable │ rebuild-image │
├─────────────────┼────────────────────────────────────┼────────────────┼─────────┼─────────┼────────────┼───────────────┤
│ docker-shop-web │ /usr/lib/apache2/modules/libphp.so │ apache2handler │ 8.2.34 │ — │ vulnerable │ rebuild-image │
└─────────────────┴────────────────────────────────────┴────────────────┴─────────┴─────────┴────────────┴───────────────┘
## Recommendations
* Rebuild this container's image (PHP 8.2.34) on PHP 8.2.35 or newer and redeploy; containers are not changed in place.
* Until upgraded, the advisories' partial mitigations for official are session.upload_progress.enabled=0, memory_limit=-1 (set them in the image's php.ini until it is rebuilt). They do not make PHP safe.
Fixed upstream releases: 8.2.35, 8.3.36, 8.4.27 and 8.5.12. Distro verdicts use
the tracker snapshot from 2026-10-21T15:16Z. No indicators of compromise have
been published; log counts are hints only.05Mitigate across your fleet
The mitigate method re-scans each host and skips the ones with nothing to do. On the rest it upgrades every installed PHP runtime package through apt, dnf, yum or apk, restarts the running PHP-FPM units, and Apache when mod_php is installed, then scans again. Containers are reported for an image rebuild and never changed in place.
Mitigation needs root, or passwordless sudo for the exact commands the dry run prints. If sudo would ask for a password, the host is reported as needs-privilege and nothing is changed. Restarting PHP-FPM or Apache briefly interrupts the requests they serve.
dryRun defaults to true — the method shows the plan and changes nothing. Pass dryRun=false to apply:
swamp behavior run php-rce-scanner mitigate \
--input hosts=192.0.2.10 \
--input dryRun=falseWhere no fixed package exists yet, add applyConfigMitigations=true to also write php.net's partial ini mitigations. They do not make PHP safe.
06Mitigation Results
A dry run on the same container: mitigate never changes a container, and reports the image to rebuild.
# PHP RCE Mitigation: DRY RUN
┌─────────────────┬──────────────────┬────────────┬──────────┬───────────────┐
│ Host │ Outcome │ Privilege │ Risk now │ Action │
├─────────────────┼──────────────────┼────────────┼──────────┼───────────────┤
│ docker-shop-web │ no-automatic-fix │ not-needed │ CRITICAL │ rebuild-image │
└─────────────────┴──────────────────┴────────────┴──────────┴───────────────┘
## docker-shop-web
* Target is a container: rebuild its image on a fixed PHP release instead of changing it in place.