How to Fix PHP2Shell (CVE-2026-109618 and CVE-2026-109619)
Fix PHP2Shell (CVE-2026-109618 and CVE-2026-109619): patch PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12, rebuild Docker images, and verify the runtime.
Two critical vulnerabilities in PHP, two potential remote shells, and one very simple solution: update your PHP runtime.

TL;DR: Patch Now
PHP fixed PHP2Shell on October 21, 2026, and the official container images have caught up. Here is the timeline (UTC):
| When | What happened |
|---|---|
| 2026-10-20 | PHP pre-announces two critical RCEs and tells the distributions to get ready. |
| 2026-10-21 13:48 | Fixed releases published on php.net: 8.5.12, 8.4.27, 8.3.36, 8.2.35 (source tarballs and Windows builds). |
| 2026-10-21 14:00 | The php.net security advisory goes live. |
| 2026-10-21 15:41 | The docker-library/php tracking issue is closed. |
| 2026-10-21 15:48–16:05 | Official php images rebuilt and published for every supported branch. |
| Now | The patched official tags are live. Docker Hardened Images is still behind. |
The fixed versions and the ready-to-pull images are:
| PHP branch | Fixed version | Official image |
|---|---|---|
| 8.2 | 8.2.35 | php:8.2.35-fpm |
| 8.3 | 8.3.36 | php:8.3.36-fpm |
| 8.4 | 8.4.27 | php:8.4.27-fpm |
| 8.5 | 8.5.12 | php:8.5.12-fpm |
So, depending on how you run PHP:
- Outside containers (bare metal, VM, distro packages): patch from the vendor now.
- In containers: pull the patched
phptag now, then rebuild, redeploy and verify (steps below). Prefer the pinned tag over the floating one —php:8.5-fpm,php:8.4-fpmandphp:8.3-fpmalready resolve to the fix, butphp:8.2-fpmstill points at 8.2.34, so pinphp:8.2.35-fpm. - Docker Hardened Images: not patched yet — see below.
To update now:
- Update the base image. For example, for PHP 8.4 with FPM:
FROM php:8.4.27-fpm
- Rebuild and redeploy. For Docker Compose:
docker compose build --pull --no-cache
docker compose up -d --force-recreate
- Verify that the deployed containers actually run the patched version — don't assume the rebuild worked.
If your Linux vendor backports security patches, the package version may differ; check the vendor's security advisory.
Pin the digest
Tags can be rebuilt and repointed; digests cannot. For a production base image, pin the immutable digest instead of the tag. Get the current one with:
docker buildx imagetools inspect php:8.5.12-fpm --format '{{.Manifest.Digest}}'
Then pin it in your FROM line:
FROM php:8.5.12-fpm@sha256:8b4b4a764f7985137b13e4cb49dd59e967d9daa7946a731f9d06e31e748e39bb
The multi-arch index digests at the time of writing (verified 2026-10-21):
| Image | Digest |
|---|---|
php:8.2.35-fpm | sha256:c4790315a6c550b759f971677deaca83bbd7543dd3d233fbd920e529b1fe4ddb |
php:8.3.36-fpm | sha256:a2d39885e245cdf5120b9eafada552cd49c73edc53285179148dd3e2ec42c2a6 |
php:8.4.27-fpm | sha256:64aff665308e23ba8804a6c43f75837e9bcdcc31735fc0f74af8899fe5304b07 |
php:8.5.12-fpm | sha256:8b4b4a764f7985137b13e4cb49dd59e967d9daa7946a731f9d06e31e748e39bb |
Re-check them before pinning; a tag gains a new digest whenever the base OS is refreshed.
Docker Hardened Images
Docker Hardened Images publishes PHP as well, but it has not caught up yet. Its current runtimes still ship the vulnerable versions:
| DHI image | Runs |
|---|---|
dhi.io/php:8.5-fpm | 8.5.11 |
dhi.io/php:8.4-fpm | 8.4.26 |
dhi.io/php:8.3-fpm | 8.3.35 |
dhi.io/php:8.2-fpm | 8.2.34 |
No patched DHI tag (dhi.io/php:8.5.12-fpm, dhi.io/php:8.4.27-fpm, and so on) is published yet. DHI scans clean (no critical or high CVEs) thanks to its minimal base and VEX data, but that does not mean it carries this fix. So treat Docker Hardened Images as another place to wait for the patched version. Use a -fpm variant at runtime and a -dev variant only for build stages.
Let Your AI Agent Fix It 🤖
If you're using an AI coding agent, give it this prompt:
Check this repository for PHP2Shell (CVE-2026-109618 and CVE-2026-109619).
- Identify PHP versions in Dockerfiles, container images, CI/CD configurations, and deployment manifests.
- Upgrade affected runtimes to patched releases (PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12 or later), accounting for vendor backports.
- Update image references and rebuild instructions. Don't upgrade to a different major or minor PHP branch unless necessary.
- Run available tests and vulnerability scans.
- Show me the changes, remaining risks, and how to verify the running production version.
Don't deploy without my approval. Don't claim the vulnerability is fixed without verifying the runtime or its vendor patch status.
And please, sandbox your coding agent. You don't need another security incident while fixing this one. 😅
What Is PHP2Shell?
PHP2Shell is the name given to two critical remote code execution (RCE) vulnerabilities in PHP itself.
- CVE-2026-109618: Out-of-memory handling can leave internal request data partially initialized, leading to memory corruption during cleanup.
- CVE-2026-109619: Request-specific global state can outlive its allocated memory, creating a use-after-free vulnerability in subsequent requests.
Both have a CVSS v4.0 score of 9.2.
The vulnerabilities affect PHP installations serving web requests, including PHP-FPM, Apache mod_php, and other PHP server integrations.
The especially nasty part? PHP reports a demonstrated attack against mod_php that can trigger before your application code even runs.
This is not a WordPress plugin vulnerability. It's not something you can fix with a Composer update. The problem is in the PHP runtime.
How to Check Your Docker Images
First, identify the PHP version in your container:
docker run --rm --entrypoint php my-php-app:latest -v
Vulnerability databases can lag behind new advisories, so confirm the runtime version from the image's package inventory before trusting a CVE scan:
docker scout sbom my-php-app:latest --format list | grep -i php
Then scan the image for the two vulnerabilities using Docker Scout:
docker scout cves \
--only-cve-id CVE-2026-109618,CVE-2026-109619 \
my-php-app:latest
You can also scan with Trivy:
trivy image --scanners vuln my-php-app:latest
Remember that vulnerability databases may take time to incorporate new advisories. No CVE findings doesn't necessarily mean your image is safe. Verify the PHP runtime version and vendor patch status.
Also verify your running containers. An updated image sitting in your registry doesn't protect a container that's still running yesterday's code.
What If You Can't Update Immediately?
There are temporary measures, but none is a complete fix, and PHP is blunt about it: patching is the only complete mitigation.
The headline configuration knobs, each applied administratively and followed by a restart of every worker:
memory_limit=-1— the primary configuration mitigation for CVE-2026-109618, because it removes the per-request limit that enables the confirmed OOM exploit. Make sure no pool,.user.ini, directory or application setting restores a finite limit.fatal_error_backtraces=0(PHP 8.5) andsession.upload_progress.enabled=0— remove the producer and the consumer used by the confirmed CVE-2026-109619 cases.
Do not try to replace memory_limit with RLIMIT_AS or RLIMIT_DATA: they make mmap() fail and trigger the vulnerable longjmp() path. A cgroup memory.max is an alternative but is not guaranteed to prevent allocation failure.
Also keep post_max_size conservative, enforce the decoded request size at the frontend, and bound the number of input variables, parts, headers and uploads (for example, lower max_input_nesting_level). If performance allows, consider pm.max_requests=1 so a poisoned worker is recycled quickly.
PHP explicitly warns that no configuration mitigation covers every path: an application, extension or server path can still publish or consume stale state without a predictable log entry.
A non-root container, restricted network access, dropped capabilities, and a read-only filesystem can reduce the damage after compromise. They cannot fix memory corruption inside PHP.
SIP It Before You Ship It ☕
PHP2Shell is another reminder that your application can be vulnerable without a single vulnerable application dependency.
My Security Immediate Plan (SIP) recommends hardened container images, SBOMs, provenance attestations, and scanning the actual release artifact.
But today, the most important step is simpler:
Patch PHP. Rebuild your images. Redeploy. Verify.
Don't give PHP2Shell a shell.
