Server patch guide

Patch PHP2Shell on a VPS or in Docker: Packages, Restarts and Proof

If you have a root password, the PHP2Shell fix is yours to apply. It takes three moves: install a patched PHP, restart every process that still holds the old one, and prove it. Most servers that stay exposed this week will have done the first move and skipped the other two.

October 23, 2026 · 11 min read

The short answer

On a VPS, install your distribution's patched PHP packages, or upstream PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12, then restart PHP-FPM or Apache so no worker keeps running the old code. In Docker, pull the patched official php image, rebuild every image built on it, redeploy, and check php -v inside the running container.

On this page
  1. Installed is not the same as running
  2. Debian and Ubuntu: trust the tracker, not the version string
  3. Red Hat, AlmaLinux and Rocky: errata, streams and Remi
  4. Docker: an old image is a time capsule
  5. FrankenPHP and LiteSpeed carry PHP inside the server
  6. Proof beats a package list
  7. When the server is older than the advice

Installed is not the same as running

A package manager replaces files on disk. It does not reach into memory and swap the PHP that is already serving requests. A PHP-FPM pool, an Apache server with mod_php, a FrankenPHP worker: each keeps the old interpreter loaded until it is told to stop. That matters more than usual here, because one of the two bugs, CVE-2026-109619, is about state that survives inside a worker from one request to the next. A server that downloaded the fix on Wednesday and never restarted is still running Tuesday's PHP.

So the job has three parts, and the third is the one people skip. Install the patched build. Restart everything that runs PHP for the web. Then confirm, from the running process and not from a hopeful glance at a package list, that the version serving pages is a fixed one. If you are not sure which version or SAPI you have, start with the vulnerability check and come back.

Who runs your server?

The answer decides who installs the fix and how long it takes.

Shared hosting

Your host builds PHP. Ask for 8.2.35, 8.3.36, 8.4.27 or 8.5.12, in writing, then pick it in the control panel.

Managed WordPress host

The host patches the platform. Get written confirmation of the PHP build your site runs on.

Your own server (VPS)

Update the PHP packages, then restart PHP-FPM or Apache so no worker keeps the old code.

Docker or containers

Rebuild the image on a patched PHP base and redeploy. The old image keeps the old PHP.

Then check for compromise

A patch closes the door. It does not tell you whether someone came in before you closed it.

Four kinds of server, four routes to the same patched PHP, and one shared last step.
  • Take a snapshot first. A VPS snapshot or a full backup costs minutes and turns a bad upgrade into an inconvenience.
  • Find the PHP that serves the web, not the one in your shell. The command line and PHP-FPM can be different builds on the same machine.
  • Note the SAPI. Every way of running PHP for the web is in scope, and the PHP project ranks Apache's built-in mod_php as the most dangerous of them.
  • Plan the restart window in minutes, not days. A graceful reload of PHP-FPM is usually invisible to visitors.

Debian and Ubuntu: trust the tracker, not the version string

Debian and Ubuntu rarely ship a new upstream version to a stable release. They backport the fix into the version they already ship and add a revision number. That is why `php -v` on a patched Ubuntu server can print a number that looks years old. The version string is not the evidence. The CVE ID in the distribution's security tracker and the package changelog is.

As of October 23, Ubuntu's CVE page for CVE-2026-109618 listed fixed packages for every supported LTS release. Ubuntu 24.04 ships php8.3, and the fixed build is numbered 8.3.6 with an Ubuntu revision. Ubuntu 22.04 ships php8.1, which the PHP project no longer patches, and Canonical backported the fix into its own 8.1.2 build anyway. Ubuntu 20.04 and older get their fixes only through ESM, which means an Ubuntu Pro subscription. Debian's security tracker listed fixed php8.4 packages for trixie and fixed php8.2 packages for bookworm, the latter through Debian LTS.

  1. 1

    Refresh and list what is waiting

    Run `sudo apt update`, then `apt list --upgradable | grep php` to see which PHP packages have updates pending.

  2. 2

    Upgrade the PHP packages

    Run `sudo apt upgrade`, or upgrade only the PHP packages if you must keep the rest of the system still today. Install whatever the security repository offers for php, php-fpm, libapache2-mod-php and the extensions.

  3. 3

    Read the changelog for the CVE

    Run `apt changelog php8.3-fpm` (use your own version) and look for CVE-2026-109618 and CVE-2026-109619. If they are listed, the build is patched, whatever `php -v` says.

  4. 4

    Restart the services that run PHP

    Run `sudo systemctl restart php8.3-fpm` for each FPM version installed, and `sudo systemctl restart apache2` if Apache loads mod_php.

  5. 5

    Check the running version

    Run `php-fpm8.3 -v` and load a phpinfo page behind a password, as described further down this page.

Many Ubuntu and Debian servers run PHP from the long-standing ondrej PPA, which its own page says is being merged into packages.sury.org. On October 21 it published php8.4 builds of 8.4.27 for Ubuntu 22.04 and 24.04. If your PHP came from there, the update comes from there too, and the version number will match upstream. Check the PPA's package list for the branch you run before you assume it is ready.

Red Hat, AlmaLinux and Rocky: errata, streams and Remi

Red Hat's security bulletin RHSB-2026-013 says RHEL 8, 9 and 10 are affected by both CVEs, that RHEL 7 is affected only by CVE-2026-109619, and that the company is expediting fixes, with some already out when it published. Red Hat rates the issue Important and notes that standard RHEL deployments use PHP-FPM rather than mod_php. AlmaLinux and Rocky Linux rebuild the same packages and publish their own errata, so the method is the same: ask dnf about the CVE, not about the version.

Where the fix comes from on each kind of Linux server, and how to confirm it
Where the fix comes fromHow to confirm it
DebianThe security repository (bookworm through Debian LTS)`apt changelog` shows the CVE IDs; the Debian tracker lists the fixed version
Ubuntu 22.04, 24.04 and newerThe standard security pocketUbuntu's CVE page lists the fixed revision; the changelog names the CVEs
Ubuntu 20.04 and olderESM, through Ubuntu Pro`pro status` shows ESM enabled, then the same changelog check
Ondrej PPA or packages.sury.orgThe repository maintainer's buildsThe version matches upstream: 8.4.27 or another fixed release
RHEL, AlmaLinux, RockyVendor errata for the php packages or module stream`dnf updateinfo list --cve CVE-2026-109618` and the package changelog
Remi's repositoryremi-modular, or Software Collections in remi-safeThe version matches upstream: 8.2.35, 8.3.36, 8.4.27 or 8.5.12

Remi's repository, which many RHEL-family servers use for newer PHP branches, announced on October 22 that 8.2.35, 8.3.36, 8.4.27 and 8.5.12 were available in remi-modular for Fedora 43 and later and Enterprise Linux 8 and later, and as Software Collections in remi-safe. Run `sudo dnf upgrade 'php*'`, confirm with `rpm -q --changelog php-fpm | grep CVE-2026`, then `sudo systemctl restart php-fpm` and `sudo systemctl restart httpd` if Apache loads PHP as a module.

Docker: an old image is a time capsule

A container carries its own PHP. Patching the host does nothing for it. The official php image is rebuilt on the fixed releases, and the official image library file now lists tags such as `php:8.4.27-fpm`, `php:8.3.36-apache-bookworm` and `php:8.5.12-fpm-alpine`, on Debian trixie, Debian bookworm and Alpine bases. There is no 8.1 line in the library. A container is patched only when its image is rebuilt from the new base and the running container is replaced.

A crane lifts a rusty, bandaged shipping container out of a stack while a fresh blue container hangs ready to take its place, collage on orange
Docker patching in one picture: you do not bandage the old container, you swap it for a new one.

Floating tags such as `php:8.4-fpm` or `wordpress:php8.3-apache` move to the new build on the registry, but the copy cached on your build server does not move with them. That is how a team rebuilds on Thursday and ships Tuesday's PHP. Wiz Research demonstrated its exploit against the official latest WordPress, Drupal and Joomla images, which is a fair hint that application images built on the php base need the same treatment as your own.

  1. 1

    Pin the base to a patched tag

    Change the first line of the Dockerfile to an exact fixed release, for example `FROM php:8.3.36-fpm-bookworm`. Pinning by digest as well stops a tag from moving under you later.

  2. 2

    Rebuild without the cache

    Run `docker build --pull --no-cache -t yourapp:patched .` so Docker fetches the new base instead of reusing layers that hold the old PHP.

  3. 3

    Refresh images you did not build

    For stacks that run an official application image directly, run `docker compose pull`, then `docker compose up -d` to replace the containers.

  4. 4

    Verify inside the container

    Run `docker exec <container> php -v` against the container that serves traffic, not a fresh one you started for testing.

  5. 5

    Remove the old images

    Run `docker image ls` to find the old builds and `docker image prune` to clear dangling ones, so nothing redeploys them by accident during a rollback.

FrankenPHP and LiteSpeed carry PHP inside the server

Both run PHP as part of the web server build, so the patch arrives with a new server build rather than a new PHP package. FrankenPHP's release notes for v1.13.2, published October 21, say its Docker images are built with PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12 and its static binaries with 8.5.12, and that the release fixes both CVEs. Replace the binary or rebuild on the new image, then restart. If you use worker mode, where one process serves many requests, the restart is not optional.

LiteSpeed servers usually run LiteSpeed's own PHP builds, called lsphp, installed from LiteSpeed's package repository or through a control panel such as CyberPanel. We could not confirm from LiteSpeed's own pages when patched lsphp builds shipped for each branch, so check the repository for your branch, install the update, restart the web server so the PHP processes are replaced, and confirm the version from phpinfo. If the repository still offers an unpatched build, apply the interim settings while you wait and say so to whoever owns the server.

PHP-FPM

Upgrade the package, then restart each pool's service. A reload replaces workers gracefully on most setups.

Apache with mod_php

PHP lives inside Apache. Upgrade the module package and restart Apache itself. Highest risk, so do it first.

FrankenPHP

New binary or new image, then restart. Worker mode keeps processes alive for a long time.

LiteSpeed

Update the lsphp build for your branch, restart the server, and confirm in phpinfo.

Proof beats a package list

The server is patched when the PHP answering web requests is a fixed build. Checking that takes two minutes. `php -v` over SSH tells you about the command line. `php-fpm8.3 -v` on Debian and Ubuntu, or `php-fpm -v` on RHEL-family servers, tells you about the FPM binary. Neither proves the running workers were replaced. A phpinfo page served through the web does.

  1. 1.Create a file with `<?php phpinfo();` in a directory protected by a password or an IP allowlist, never in the open web root.
  2. 2.Load it in a browser and read the PHP version and Server API lines at the top.
  3. 3.On a distribution build, match the package version against the tracker entry for CVE-2026-109618 rather than against upstream numbers.
  4. 4.Delete the file the moment you have read it. A forgotten phpinfo page hands strangers a complete inventory of the machine.
  5. 5.Do not trust the X-Powered-By response header. Many servers hide it, and some report the wrong thing.

Then check the site itself: the home page, a form, a login, a checkout if there is one. A 500 error after the restart usually means a missing extension package. A 502 Bad Gateway usually means the web server is pointing at an FPM socket that changed name. Last, look for the signs of compromise. Patching closes the door. It does not tell you who came in while it was open.

When the server is older than the advice

Some servers cannot simply update. The distribution is past support, the app only runs on PHP 7.4, or the person who built it left a note that says do not touch. The PHP project published source backports for 7.4, 8.0 and 8.1 for people who compile their own PHP, and some vendors offer paid backports. Neither is a weekend project for an office manager. The longer view is on the end-of-life PHP page.

Jumping branches is where sites break. Plugins and themes written for PHP 7 often fail on 8.2 and later, which is how a security patch becomes a white screen or a page full of theme PHP errors. Test on a copy first when you can. When you cannot, have someone ready to fix what breaks.

Afterward, decide who owns the next one. With one of our hosting and maintenance plans, PHP updates are tested before they go live, backups sit on another server, and someone watches the site for you. Or take PHP off the public internet entirely with a Next.js front end. The PHP2Shell hub maps the rest of the section.

Questions owners ask about PHP2Shell

Yes. The package upgrade replaces files on disk, but running PHP-FPM workers keep the old code in memory until the service restarts. Restart each FPM service on the machine, and Apache too if it loads mod_php. Then confirm the version from a password-protected phpinfo page, which reports what the web server is actually running.

Ubuntu and Debian backport security fixes into the version they already ship and add a revision number. Ubuntu 24.04's fixed php8.3 build still reports 8.3.6, for example. Check the package changelog with apt changelog for CVE-2026-109618 and CVE-2026-109619, or look up the CVE on Ubuntu's or Debian's security tracker.

No. Each container carries its own PHP inside its image. Rebuild the image on a patched base such as php:8.3.36-fpm, pull fresh copies of any official application images you use, replace the running containers, and run php -v inside the live container to confirm. Then remove the old images so a rollback cannot bring them back.

The official image library lists 8.5.12, 8.4.27, 8.3.36 and 8.2.35 tags in cli, apache, fpm and zts variants on Debian trixie, Debian bookworm and Alpine bases. Pin to one of those exact versions. There is no 8.1 line in the official library, so an 8.1 image needs a branch upgrade.

Not necessarily. The PHP project does not patch 8.1, but Ubuntu's CVE page lists a fixed php8.1 package for 22.04 in the standard security updates. Run apt upgrade, check the changelog for the CVE IDs and restart PHP-FPM. Plan the move to a supported branch anyway; see end-of-life PHP.

Yes. We update PHP to a fixed release, restart and verify the running version, test the site and check for signs of compromise. WordPress sites that break after the update fall under our fixed-price Fix It Now tiers. Custom apps, older servers and fleets are quoted after a free check. Start at the emergency fix page.

Keep reading

Free · No obligation

Get the patch applied and proven

Tell us what runs the server and what you have tried. We reply with the fastest safe route, and a fixed price where one applies.

Which of these sounds like you? (pick any)

Rather talk now? Call (210) 346-0848.

CallGet a quote