DEV Community

Cover image for How to Fix PHP2Shell (CVE-2026-109618 and CVE-2026-109619)
Mohammad-Ali A'RÂBI for Docker

Posted on Originally published at containersecurity.dev

How to Fix PHP2Shell (CVE-2026-109618 and CVE-2026-109619)

Two critical vulnerabilities in PHP, two potential remote shells, and one very simple solution: update your PHP runtime.

Patching PHP to fix PHP2Shell

TL;DR: Patch Now

PHP fixed PHP2Shell on October 21, 2026, and the official container images have caught up.

The fixed versions and the ready-to-pull images are:

PHP branch Fixed version Official image Docker Hardened Image
8.2 8.2.35 php:8.2.35-fpm dhi.io/php:8.2.35-fpm
8.3 8.3.36 php:8.3.36-fpm dhi.io/php:8.3.36-fpm
8.4 8.4.27 php:8.4.27-fpm dhi.io/php:8.4.27-fpm
8.5 8.5.12 php:8.5.12-fpm dhi.io/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 php tag now, then rebuild, redeploy and verify (steps below). Prefer the pinned tag over the floating one.
  • Docker Hardened Images: caught up for all branches — see below.

To update now:

  1. Update the base image. For example, for PHP 8.4 with FPM:
FROM php:8.4.27-fpm
Enter fullscreen mode Exit fullscreen mode
  1. Rebuild and redeploy. For Docker Compose:
docker compose build --pull --no-cache
docker compose up -d --force-recreate
Enter fullscreen mode Exit fullscreen mode
  1. Verify that the deployed containers actually run the patched version — don't assume the rebuild worked:
docker compose exec <service> php -v
Enter fullscreen mode Exit fullscreen mode

On the official -fpm images the php CLI is present; if a runtime has no CLI (for example a Docker Hardened -fpm image, or a distroless build), use php-fpm -v or read the version from docker scout sbom.

Running PHP 8.1 or older? Those branches are end-of-life and receive no update releases. Given the severity, the PHP security team published minimal source backports for PHP 7.4, 8.0 and 8.1, but the durable fix is to move to a supported branch. 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}}'
Enter fullscreen mode Exit fullscreen mode

Then pin it in your FROM line:

FROM php:8.5.12-fpm@sha256:<digest>
Enter fullscreen mode Exit fullscreen mode

Re-check the digest whenever you bump the image; a tag gains a new digest each time the base OS is refreshed.

Release Timeline

PHP shipped the fixes hours before the images caught up. The sequence (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.
2026-10-21 18:38 Status check: all official patched tags are live.
2026-10-22 03:12–07:38 Docker Hardened Images rebuilds PHP: all four branches patched.

Docker Hardened Images

Docker Hardened Images ships PHP too, and it has now caught up for every supported branch:

DHI image Runs
dhi.io/php:8.5-fpm 8.5.12
dhi.io/php:8.4-fpm 8.4.27
dhi.io/php:8.3-fpm 8.3.36
dhi.io/php:8.2-fpm 8.2.35

Patched *-fpm tags are published for all four branches (dhi.io/php:8.2.35-fpm, dhi.io/php:8.3.36-fpm, dhi.io/php:8.4.27-fpm, dhi.io/php:8.5.12-fpm).

Verify rather than trust the tag, and don't mistake a clean scan for a fix. DHI ships full SBOM, provenance and VEX attestations, so a "no CVEs" result is a vendor assessment, not proof of being patched. Confirm the version directly:

docker scout sbom dhi.io/php:8.5-fpm --format list | grep -i php
Enter fullscreen mode Exit fullscreen mode

Use a -fpm variant at runtime and a -dev variant only for build stages. For what a hardened runtime does and does not buy you here, see Would a hardened image have contained PHP2Shell?.

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).

  1. Identify PHP versions in Dockerfiles, container images, CI/CD configurations, and deployment manifests.
  2. 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.
  3. Update image references and rebuild instructions. Don't upgrade to a different major or minor PHP branch unless necessary.
  4. Run available tests and vulnerability scans.
  5. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You can also scan with Trivy:

trivy image --scanners vuln my-php-app:latest
Enter fullscreen mode Exit fullscreen mode

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.

Would a Hardened Image Have Contained PHP2Shell?

Partially. These bugs execute code inside the PHP process, so a hardened runtime doesn't stop the exploit — it changes what the attacker can do afterwards:

Attack capability With a shell-less, non-root runtime
Run /bin/sh or /bin/bash ✅ Blocked — the runtime has no shell
Use common system utilities ✅ Mostly unavailable — no package manager, minimal binaries
Execute arbitrary code within the PHP process ❌ Still possible
Read secrets in PHP memory ❌ Still possible
Write files or open network connections ⚠️ Depends on filesystem and network policy
Become root ⚠️ Restricted by non-root execution, unless a separate privilege-escalation bug is found

dhi.io/php already ships this way — no shell, no package manager, non-root — and you can add the rest with runtime flags: a read-only root filesystem, dropped capabilities, restricted egress.

docker run --detach --rm --read-only --tmpfs /tmp --cap-drop ALL \
  --security-opt no-new-privileges:true "$image"
Enter fullscreen mode Exit fullscreen mode

PHP-FPM listens on 9000 and is reached by your proxy over the internal network, so don't publish the port. Think of this as insurance for the next vulnerability.

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.

Want More Container Security?

Docker and Kubernetes Security book cover

View book

This post covers one part of container security. If it helped, start with the first steps toward a secure supply chain:

If you want to get the full book, the PDF of Docker and Kubernetes Security is 25% off with the code PHP2SHELL.

Get the book

References

Top comments (0)