Skip to content

OCIO y TECnología

  • Privacy Policy

OCIO y TECnología

  • Home » 
  • Tecnología » 
  • Docker » 
  • Fixing critical PHP RCE vulnerabilities in dockerized WordPress

Fixing critical PHP RCE vulnerabilities in dockerized WordPress

Emilio González Montaña 2026/10/25
A protective shield around PHP in front of stacked software containers with a security patch and check mark.

Security guidance checked on 25 October 2026. The version numbers below are the first releases fixing the two October 21 vulnerabilities, not a promise that those releases remain the latest secure choice. Recheck the official advisories when applying this guide.

An up-to-date WordPress installation can still run on a vulnerable PHP runtime. In a Docker deployment, the PHP binary usually belongs to the application image, while WordPress files and database data may live in persistent volumes. Those layers have separate update paths.

This guide shows how to patch the runtime with a reviewed image, apply the remaining session upload-progress mitigation, and verify the result using a generic Docker Compose configuration. It assumes an existing installation whose application service is named wordpress.

What the PHP vulnerabilities affect

CVEFailure modePotential impact
CVE-2026-109618Invalid request state after an out-of-memory interruptionUnauthenticated remote code execution
CVE-2026-109619Request-owned memory referenced by stale worker stateUnauthenticated remote code execution

The first PHP advisory describes memory corruption during request cleanup after an allocation failure. The second advisory covers state that can outlive the request memory it references. Apache with mod_php is particularly exposed, including a demonstrated path before application code runs. Changing to PHP-FPM does not replace the need to patch PHP.

This is why a WordPress core update, a plugin update or HTTPS alone cannot fix these runtime defects. The PHP executable serving requests must be replaced with a patched build. Neither setting a different WordPress version string nor restarting an unchanged vulnerable image achieves that.

Choose a patched PHP release, then check compatibility

PHP branchFirst release fixing both CVEs
8.28.2.35
8.38.3.36
8.48.4.27
8.58.5.12

These thresholds are listed in the two PHP advisories. Select the latest available security release in a supported branch compatible with your installation. A patch update within the existing branch can reduce compatibility risk; moving to another PHP branch deserves separate theme and plugin testing.

The examples use wordpress:7.1.3-php8.5-apache. WordPress 7.1 supports PHP 8.5 according to the official compatibility matrix, but that does not certify every extension or custom theme. Test a restored copy of the site before changing production.

Resolve and verify the image before deployment

A tag containing php8.5 identifies a branch, not its embedded patch release. Tags can also be rebuilt. Resolve the candidate in the official registry, inspect its platforms, and pin the reviewed artifact using both its readable tag and its immutable digest:

image_tag=wordpress:7.1.3-php8.5-apache
docker buildx imagetools inspect "$image_tag"

image_digest="$(docker buildx imagetools inspect "$image_tag" --format '{{.Manifest.Digest}}')"
test -n "$image_digest"
export WORDPRESS_IMAGE="${image_tag}@${image_digest}"

docker pull "$WORDPRESS_IMAGE"
docker run --rm --network none --entrypoint php "$WORDPRESS_IMAGE" -v

The isolated command above runs the candidate PHP binary without mounting site data. Check the patch release on every architecture you deploy. For a mixed-architecture cluster, retain a suitable multi-platform index digest and verify its platform manifests. Docker documents the registry inspection command and digest output.

Record the verified WORDPRESS_IMAGE reference in the deployment configuration or version catalog. A pinned digest makes the reviewed artifact reproducible; future security updates require an intentional digest refresh. Resolving a digest establishes identity, while checking the embedded PHP version establishes the relevant patch baseline.

Apply the session upload-progress mitigation at startup

On October 23, PHP published an additional notice concerning CVE-2026-115560: an uncommon combination of session serializer changes and upload-progress handling can leave a residual RCE path. PHP recommends disabling session upload progress until a fixed release is available. The recommendation also applies after installing the October 21 fixes. See the official PHP notices.

Create config/php/security.ini:

; Reassess against the official PHP advisory before removing this mitigation.
session.upload_progress.enabled = Off

This disables PHP session upload-progress bookkeeping, not file uploads themselves. Features that explicitly depend on that bookkeeping need testing. Load the setting before request parsing, through startup INI configuration. A late ini_set() in WordPress or a plugin is not an equivalent mitigation. PHP reads server-module startup configuration when the web server starts, so recreate the container to restart its workers.

Disabling this feature alone does not fix the two critical CVEs. Keep the patched runtime and the residual mitigation together.

Add a security-aware healthcheck

Create config/wordpress/healthcheck.php. The check below verifies the reviewed PHP thresholds, the session setting and a local HTTP response:

<?php

function fail(string $message): never
{
    fwrite(STDERR, $message . PHP_EOL);
    exit(1);
}

// First fixes for CVE-2026-109618 and CVE-2026-109619.
$minimum = [
    '8.2' => '8.2.35',
    '8.3' => '8.3.36',
    '8.4' => '8.4.27',
    '8.5' => '8.5.12',
];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;

if (!isset($minimum[$branch]) || version_compare(PHP_VERSION, $minimum[$branch], '<')) {
    fail('PHP runtime does not meet the reviewed security baseline');
}

if (filter_var(ini_get('session.upload_progress.enabled'), FILTER_VALIDATE_BOOLEAN)) {
    fail('PHP session upload progress must be disabled');
}

$context = stream_context_create([
    'http' => [
        'timeout' => 5,
        'ignore_errors' => true,
        'follow_location' => 0,
        'header' => "Connection: close\r\n",
    ],
]);

$headers = @get_headers('http://127.0.0.1/wp-login.php', false, $context);
$status = is_array($headers) ? ($headers[0] ?? '') : '';

if (!preg_match('/^HTTP\/\S+\s+[23]\d\d\b/', $status)) {
    fail('Unexpected WordPress HTTP response: ' . $status);
}

The version map enforces a reviewed security baseline and deliberately rejects unreviewed PHP branches until it is updated. The HTTP test uses PHP’s get_headers() and accepts successful responses and redirects; it does not prove that login, database writes, uploads or every plugin work. Adapt the endpoint if your authentication setup changes the normal login route, and keep functional checks outside the probe.

Wire the files into Docker Compose

Save the following as compose.security.yaml beside your existing compose.yaml. It is an overlay for the existing wordpress service: the base file continues to define its database connection, credentials, storage, networks and routing. Review the merged configuration, especially if another config already uses one of these target paths. Compose merge rules keep file paths relative to the first Compose file.

services:
  wordpress:
    image: ${WORDPRESS_IMAGE:?Set a reviewed tag@sha256 image reference}
    configs:
      - source: php_security
        target: /usr/local/etc/php/conf.d/zz-security.ini
        mode: 0444
      - source: wordpress_healthcheck
        target: /usr/local/bin/wordpress-healthcheck.php
        mode: 0444
    healthcheck:
      test: ["CMD", "php", "/usr/local/bin/wordpress-healthcheck.php"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

configs:
  php_security:
    file: ./config/php/security.ini
  wordpress_healthcheck:
    file: ./config/wordpress/healthcheck.php

The INI file is non-secret configuration, so a Compose config is appropriate. Keep passwords in your existing secret-management mechanism. This patch does not require changing the database engine version or replacing a database volume.

Recreate the WordPress container and verify the result

Before the change, take a logical database backup and a consistent copy or snapshot of the application volume, and test recovery on an isolated installation. Check free space for the candidate image and rollback artifacts. For a single WordPress instance, allow a short maintenance window while the container is replaced.

With WORDPRESS_IMAGE set to the reviewed reference, apply the overlay to the existing installation:

docker compose -f compose.yaml -f compose.security.yaml config --quiet
docker compose -f compose.yaml -f compose.security.yaml pull wordpress
docker compose -f compose.yaml -f compose.security.yaml up -d --no-deps --force-recreate --wait --wait-timeout 180 wordpress

docker compose -f compose.yaml -f compose.security.yaml exec -T wordpress php -v
docker compose -f compose.yaml -f compose.security.yaml exec -T wordpress php --ini
docker compose -f compose.yaml -f compose.security.yaml exec -T wordpress php -r 'var_export(filter_var(ini_get("session.upload_progress.enabled"), FILTER_VALIDATE_BOOLEAN)); echo PHP_EOL;'
docker compose -f compose.yaml -f compose.security.yaml exec -T wordpress php /usr/local/bin/wordpress-healthcheck.php
docker compose -f compose.yaml -f compose.security.yaml ps
docker compose -f compose.yaml -f compose.security.yaml logs --since 5m wordpress

--no-deps limits this operation to the application service, while --force-recreate ensures fresh workers load the startup INI settings even when only configuration changed. Compose documents these options and the health wait. Inspect failures before continuing: an HTTP 200 alone does not establish the PHP version or mitigation state.

Expect a patched PHP release, the security INI file in the scanned configuration, false for upload progress and a successful probe. CLI checks are useful, but confirm that the web SAPI loads the intended PHP build and startup configuration too, using an authenticated diagnostic or a staging-only probe. Remove temporary probes afterwards.

  • Check the public HTTPS endpoint through the real reverse proxy, not just loopback HTTP.
  • Exercise login, an existing post, media handling and any critical forms or integrations.
  • Review PHP and application logs, health failures, restarts, CPU, memory and out-of-memory events during an observation window.
  • Keep backup files, credentials and detailed diagnostic output out of public pages and source control.

Keep persistent WordPress updates separate

When /var/www/html is mounted from persistent storage, the official WordPress entrypoint initializes the application only when the expected installation files are absent. Replacing the image can therefore update PHP while the mounted WordPress core, plugins and themes remain unchanged. The image tag and the code actually served must be checked independently.

Manage core and extension updates through the supported WordPress update process, with their own compatibility checks and backups. A routine PHP patch does not require automatically replacing the application tree or running a database updater. If a later application update changes files or schema, returning to an older image cannot undo those persistent changes.

The Swarm and rollback details that matter

For Docker Swarm, apply equivalent settings through your stack deployment workflow. Swarm Configs are immutable: give each changed INI or healthcheck Config a new name or content-derived version, and update the service reference while keeping the in-container target path stable. Remove old Configs only after the replacement tasks are healthy. Docker documents Config rotation.

Health checks also have different operational consequences. A standalone Compose container can be marked unhealthy without its restart policy automatically restarting it for that reason alone; Swarm replaces tasks that fail health checks. Plan a maintenance procedure before a core or plugin updater temporarily makes HTTP requests fail. Do not let a health-triggered restart interrupt a file replacement or schema migration.

A runtime-only rollback is possible when the application files and database remain compatible and unchanged, but restoring an old vulnerable PHP image reopens the security exposure. If application data or schema changed too, recovery needs the matching files and database backup. Keep the runtime patch, the residual mitigation and the recovery plan aligned.

Official references

  1. PHP advisory: CVE-2026-109618 — RCE via OOM corruption
    https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
  2. PHP advisory: CVE-2026-109619 — RCE via stale global state
    https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
  3. PHP 2026 news archive: October 21 security release and October 23 session upload-progress advisory
    https://www.php.net/archive/2026.php
  4. WordPress core: PHP compatibility and WordPress versions
    https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/
  5. Docker: inspect registry images and digests with buildx imagetools
    https://docs.docker.com/reference/cli/docker/buildx/imagetools/inspect/
  6. Docker Compose: merge configuration files
    https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/
  7. Docker Compose: configs
    https://docs.docker.com/reference/compose-file/configs/
  8. PHP manual: startup configuration files
    https://www.php.net/manual/en/configuration.file.php
  9. Docker Compose: service healthchecks
    https://docs.docker.com/reference/compose-file/services/#healthcheck
  10. Docker Compose: up, force-recreate and wait
    https://docs.docker.com/reference/cli/docker/compose/up/
  11. Official WordPress image: initialization and persistent files
    https://github.com/docker-library/wordpress/blob/master/docker-entrypoint.sh
  12. WordPress documentation: updating WordPress
    https://wordpress.org/documentation/article/updating-wordpress/
  13. Docker Swarm: immutable configs and rotation
    https://docs.docker.com/engine/swarm/configs/
  14. Docker Swarm: tasks, health checks and replacement
    https://docs.docker.com/engine/swarm/how-swarm-mode-works/services/
  15. PHP manual: get_headers()
    https://www.php.net/manual/en/function.get-headers.php

Comparte esto:

  • Share on X (Opens in new window) X
  • Share on Facebook (Opens in new window) Facebook
Tags : Tags CVE   docker   Docker Compose   PHP   Security   WordPress
Share
facebookShare on FacebooktwitterShare on TwitterpinterestShare on Pinterest
linkedinShare on LinkedinvkShare on VkredditShare on ReddittumblrShare on TumblrviadeoShare on ViadeobufferShare on BufferpocketShare on PocketwhatsappShare on WhatsappviberShare on ViberemailShare on EmailskypeShare on SkypediggShare on DiggmyspaceShare on MyspacebloggerShare on Blogger YahooMailShare on Yahoo mailtelegramShare on TelegramMessengerShare on Facebook Messenger gmailShare on GmailamazonShare on AmazonSMSShare on SMS
Post navigation
Previous post

Detachable screens to avoid SSH disconnections

Emilio González Montaña

Related Posts

Categories Data bases  Docker  Tecnología Fixing critical PHP RCE vulnerabilities in dockerized WordPress

Recover corrupted Postgres DB WAL

Categories Docker  Linux  Tecnología  Utils Fixing critical PHP RCE vulnerabilities in dockerized WordPress

Install WSL2 + Docker on Windows

Categories Docker  Tecnología  YAML Fixing critical PHP RCE vulnerabilities in dockerized WordPress

Docker swarm Traefik reverse proxy

Recent Posts

  • Fixing critical PHP RCE vulnerabilities in dockerized WordPress
  • Detachable screens to avoid SSH disconnections
  • Expose WSL2 port to the network
  • Rosaleda (parque El Retiro, Madrid)
  • Back to the painting table

Categories

  • Aficiones
  • AI
  • Bricolage
  • Data bases
  • Docker
  • Escenografía
  • Eventos
  • Fotografía
  • Hardware
  • Linux
  • Networking
  • Partidas
  • Proxmox
  • Sin categoría
  • Tecnología
  • Utils
  • Viajes
  • Virtualization
  • Warhammer
  • YAML

Tags

apt (5) autofs (1) Autumn (1) bash (1) bashtop (1) bookworm (1) bullseye (1) ceph (2) Condes Vampiro (1) debian (3) docker (10) docker-compose.yml (4) docker-swarm (5) El Imperio (2) Enanos (2) escenografía (3) fotos (3) fstab (1) Guerreros del Caos (2) Inline (1) KSAT (1) Linux (8) Longyearbyen (1) Madrid (2) maqueta (2) MariaDB (2) miniaturas (4) MySQL (2) NFS (2) North pole (1) Norway (1) override (1) pacific (1) partida (2) proxmox (2) Sony A65 (2) SSH (5) Svalbard (1) Ubuntu (8) update (2) viajes (1) Warhammer (11) Windows (3) WSL (2) WSL2 (2)

Archives

  • October 2026
  • June 2024
  • May 2024
  • April 2024
  • February 2024
  • January 2024
  • September 2023
  • August 2023
  • June 2023
  • December 2021
  • April 2021
  • May 2020
  • April 2020
  • March 2020
  • November 2019
  • July 2018
  • February 2017
  • June 2015
  • April 2014
  • April 2011
  • January 2011
  • July 2010
  • June 2010
  • March 2010
  • November 2009
  • June 2009
  • December 2008
  • November 2008
  • October 2008
  • June 2008
  • May 2008
  • October 2007

Meta

  • Register
  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
Copyright © 2026 OCIO y TECnología - Powered by Nevothemes.
Offcanvas
Offcanvas

  • Register
  • Lost your password ?