On 21 October 2026, the PHP project released fixes for two critical vulnerabilities. Both are rated 9.2 on the CVSS v4.0 scale, and both can allow unauthenticated remote code execution. Hosting providers have warned that exploitation is already happening. Here is what the bugs are, how to fix them, and why running PHP in containers made our response much simpler.
What was disclosed
- CVE-2026-109618 is remote code execution through out-of-memory corruption. If PHP runs out of memory while it is building internal request data, it can be interrupted with that data only partly initialised. Request cleanup may then treat the invalid data as valid.
- CVE-2026-109619 is remote code execution through stale global state. Request-owned internal state can outlive the memory behind it. A later request on the same worker may use that stale state before it is reset.
An attacker needs no login, because the problem sits in how PHP handles the request itself. PHP's advisory says the risk is highest with mod_php, where the attack can run before any application code does. PHP-FPM, php-cgi, FrankenPHP and LiteSpeed are also affected.
Fixed versions
| Branch | Fixed in |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 (end of life on 31 December 2026) |
PHP 8.1 and older no longer get updates from the PHP project. Source-only backports exist for 7.4, 8.0 and 8.1. If you run one of those versions, upgrade, or ask your vendor for a backported fix.
The only complete fix is updating
The advisory lists interim mitigations, such as disabling session.upload_progress.enabled, capping request sizes, and avoiding RLIMIT_AS limits. They narrow the known attack paths but do not close the holes. PHP itself warns that other variants may exist. Treat them as a stopgap while you patch.
Patching a traditional server
On a classic VPS or shared panel, the fix looks like this:
- Take a snapshot or backup.
- Wait for your distribution or control panel to publish a patched package. Some third-party repositories do not ship on release day.
- Update PHP, and every other PHP version installed on the machine.
- Restart PHP-FPM, Apache or whatever serves PHP. Without a restart the old code keeps running.
- Check the version actually in use, with
php -vand with aphpinfo()page, because the CLI and the web server can use different binaries. - Repeat for every server.
Each step is easy to forget, and mistakes tend to show up only after an attacker finds them.
Patching a containerised deployment
Our production environment runs PHP-FPM and nginx in a Docker image. The PHP version is declared in a single line of the Dockerfile, so the fix was a one-line change per base image:
# before
FROM php:8.4-fpm-bookworm
# after
FROM php:8.4.27-fpm-bookworm
Then we rebuilt the image without cache and redeployed. In addition, we turned off session.upload_progress.enabled in the image's php.ini as defence in depth.
This approach has several advantages.
There is no drift. The image contains PHP, its extensions and its configuration. Every container is built from the same recipe, so no server is left on an old version. There are no forgotten PHP installs.
The restart is built in. A redeploy replaces the running containers, so every worker starts on the new binary. The step where the old code keeps running because nobody restarted it disappears.
The fix is reviewable and reversible. The change is a small commit that can be peer-reviewed, tested in CI and rolled back if something goes wrong.
You can test what you ship. We ran the full test suite against the exact PHP version production will use, before it reaches production.
Verification is simple. Running php -v inside the container reports exactly the version that serves traffic.
The attack surface is smaller. The container holds what the application needs and little else: no control panel, no other sites and no leftover tools. If an attacker did get code execution, they would land in a disposable container rather than on a shared host. We could discard it and redeploy a clean one in minutes.
Pin your versions
One detail matters more than it looks. A floating tag such as php:8.4-fpm only moves to 8.4.27 if the build pulls the base image fresh. A cached layer can quietly keep the vulnerable PHP. Pinning to the exact patched version, or building with --pull --no-cache, removes that risk. It also makes the PHP version in each deployment visible in your git history.
A note on honesty
Containers do not make a PHP vulnerability harmless. This bug is in PHP itself, so a container running a vulnerable version is just as exposed as a server running one. What Docker gives you is speed, consistency and a smaller blast radius, and those matter most when a critical patch is out and attackers are probing.
Checklist
- Back up or snapshot.
- Update PHP to a fixed version: 8.5.12, 8.4.27, 8.3.36 or 8.2.35.
- Rebuild and redeploy containers, or restart PHP-FPM and the web server on traditional hosts.
- Confirm the running version with
php -vinside the container or on the server. - Plan an upgrade if you are on PHP 8.2 or older.
- Look for signs of compromise: unknown files in web directories, new cron jobs, odd processes, and spikes in load or outbound traffic.
- Rotate secrets such as application keys and database credentials if anything looks suspicious.
- Enable automatic security updates or scheduled image rebuilds, so the next patch needs less effort.
Top comments (0)