A poster of a freight train at night. A gantry arm lifts the red container with its padlock sprung open off the train and lowers a clean one in. The locomotive's side panel reads Arvion.

CVE-2026-109618 · CVE-2026-109619

PHP2Shell in Docker:updating WordPress won't fix it

Antonio Firmiano

CEO · · 4 min read

PHP released fixes today for two critical flaws in PHP itself, the pair now called PHP2Shell. If you run WordPress in Docker, the WordPress dashboard can't apply them. PHP comes from the image your container runs, so the fix comes from pulling a new image or changing the tag. This post covers how to see which PHP you have and what to do for each kind of tag.

What PHP2Shell is

On 20 October the PHP security team announced a security release for 21 October at 14:00 UTC. It "addresses two critical vulnerabilities, both rated CVSS v4.0 9.2." Huntress and Sansec track them as CVE-2026-109618 and CVE-2026-109619 and describe both as remote code execution. As of 20 October, Huntress wrote that it had "not seen in-the-wild exploitation."

PHP shipped the fixes a little ahead of schedule on 21 October. Its security advisory says the new releases "fix two critical vulnerabilities that can allow unauthenticated remote code execution":

  • PHP 8.5: 8.5.12
  • PHP 8.4: 8.4.27
  • PHP 8.3: 8.3.36
  • PHP 8.2: 8.2.35

Every earlier release on those branches is affected. PHP says all installations serving web requests are at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, and it considers the risk highest for mod_php.

Those are the four branches PHP still supports. PHP 8.1 and older get no official release. PHP's security team published minimal source patches for 7.4, 8.0 and 8.1 for people who build PHP themselves, and some distributions and LTS vendors ship backported fixes.

The fix has to land in PHP. In Sansec's words, "You cannot fix it from within your store codebase." The same holds for WordPress, its plugins and its theme.

Why Docker is different

On shared hosting, your host updates PHP. On a server you run, your package manager does. In Docker, PHP is part of the WordPress image. The official wordpress images are built on the official php images. The PHP 8.3 FPM variant, for example, starts with FROM php:8.3-fpm (Dockerfile). The PHP inside a container stays the same until you replace the image.

Updating WordPress from the dashboard writes new WordPress files to your volume. It doesn't touch the PHP in the image. The MySQL, MariaDB and nginx containers have no PHP in them and aren't part of this bug.

How to see your PHP version

From outside, the version is often in the response headers. The official images don't set expose_php, and PHP's default for it is on (see main.c and php.ini-production). So PHP adds an X-Powered-By header to every page it serves. By default, nginx only drops Status and X-Accel-* from FastCGI responses (nginx docs), so the header reaches the browser unless someone hid it.

curl -sI https://your-site.example | grep -i x-powered-by
X-Powered-By: PHP/8.3.35

That site runs 8.3.35, the last 8.3 release before the fix. No output means the header is hidden, for example by fastcgi_hide_header X-Powered-By in nginx, a security plugin or a CDN rule. A cache in front of the site can also keep reporting the version from before an update.

From inside, ask the container. Use your service name if it isn't wordpress.

docker compose exec wordpress php -v

What to do, by tag

Look at the image: line of your WordPress service, or the FROM line if you build your own image.

Floating tags such as wordpress:latest, wordpress:php8.3-fpm or wordpress:7.1-php8.3-fpm move to new builds. They get rebuilt when the php image they're built on is updated, which takes some time after PHP's release. At 13:45 UTC on 21 October, the newest wordpress builds on Docker Hub dated from 12:16 UTC, before PHP's release. A pull gets the fix only once a build newer than the release is out:

docker compose pull wordpress
docker compose up -d wordpress
docker compose exec wordpress php -v

If php -v still shows the old version, the new build isn't out yet. Pull again later.

Digests and pinned versions never change. A digest pin (wordpress@sha256:...) or a full PHP version in your own Dockerfile (FROM php:8.3.12-fpm) stays on that build. A tag that names an older WordPress release stops being rebuilt too. On Docker Hub, wordpress:7.1.2-php8.3-fpm hasn't been pushed since 6 October, while the 7.1.3 tags were rebuilt on 21 October. Change the tag, then pull and restart.

This is where the dashboard misleads most. With an older WordPress tag pinned, a dashboard update shows the new WordPress version while PHP stays on the old image.

PHP 8.1 and 7.4 tags such as wordpress:php8.1-fpm or wordpress:php7.4-apache are past end of life. Docker Hub shows the php8.1 tags last pushed on 1 January 2026 and the php7.4 tags in November 2022. Don't wait for an official fix. Move to php8.2 or newer. Security support for 8.2 ends on 31 December 2026, so 8.3 or newer gives you more time. Test your plugins and theme on the new branch before you switch production.

Your own Dockerfile with FROM wordpress:... needs a rebuild that pulls the new base. Without --pull, Docker can reuse the old base image it already has.

docker compose build --pull wordpress
docker compose up -d wordpress

Distribution packages report a different number

The official php images compile PHP from the php.net source releases, so the version they report is the upstream one. Images that install PHP from Debian or Ubuntu packages are different. Distributions backport security fixes without changing the upstream number. Ubuntu 22.04's PHP, for example, reports a version like 8.1.2-1ubuntu2.27. The 8.1.2 is an old upstream release, and the suffix carries Ubuntu's own fixes. The version number alone can't tell you whether the PHP2Shell fix is in, so check your distribution's security notice. Huntress gives the same advice: "check your Linux distribution and hosting provider for backported packages."

wp2shell is a different bug

wp2shell was a pair of flaws in WordPress core, CVE-2026-63030 and CVE-2026-60137, made public on 17 July 2026 (Eye Security's guide). A WordPress update fixed those. PHP2Shell is in PHP, and fixing one doesn't fix the other.

If you'd rather not read the output yourself, paste your php -v output or your compose file into our free PHP2Shell check and it says what to change.