PHP still shows as vulnerable after you updated it
You updated PHP but Site Health still shows the old, PHP2Shell-vulnerable version. Six common reasons — unrestarted workers, CLI vs web SAPI, Docker containers, the backport number trap and multiple PHP versions — and how to fix each.
By the Presscomet teamPublished 12 min read
On this page
You updated PHP. So why is it still the old version?
You switched the PHP version, or ran the update command, or your host said it was done — and Tools › Site Health › Info › Server still shows the old, PHP2Shell-vulnerable number. This is one of the most common and most alarming moments in patching this flaw, because it looks like the fix failed. Usually it didn’t: the new PHP is installed, but something is keeping the old one in front of your visitors.
There are six usual culprits, and they’re all fixable in minutes once you know which one you’re looking at. In rough order of how often they bite:
- #1 cause
- Workers not restarted
- #2 cause
- Checked CLI, not web SAPI
- #3 cause
- Docker not recreated
- Not a bug
- Backport keeps old number
- Also check
- Multiple PHP versions
- Read this value
- Site Health › Server
One rule governs all six: the version that matters is the one serving web requests, and the only place that reliably reports it from inside WordPress is Site Health. Here’s what you’re reading — the PHP version and the PHP SAPI rows:
Site Health
Server ▴
| Server architecture | Linux 6.8.0 x86_64 |
| Web server | nginx/1.26.2 |
| PHP version | 8.3.14 (Supports 64bit values) |
| PHP SAPI | fpm-fcgi |
| PHP max input variables | 1000 |
| PHP time limit | 30 |
| PHP memory limit | 256M |
Other panels: WordPress, Directories and Sizes, Drop-ins, Active Plugins, Database…
The SAPI value is the clue to everything below: fpm-fcgi means PHP-FPM, apache2handler means Apache mod_php, litespeed means LiteSpeed. That tells you which service has to restart. If you haven’t yet confirmed which PHP version is even the fixed one, keep the check-and-update-PHP guide open alongside this; here we assume you updated and are stuck on “it didn’t take”.
Cause 1: the workers never restarted
This is the big one. PHP doesn’t re-read itself on every request — for speed, the server loads PHP once into long-lived worker processes and keeps it there. Install a new build and those running workers still hold the old code in memory until the service restarts. The package manager says “done”; Site Health, truthfully, still shows the old version.
Restart the service that matches your SAPI. Pick the tab:
For fpm-fcgi. Restart the FPM service for your version (there may be more than one installed — restart the one serving the site):
# See which php-fpm services exist and which are running$ systemctl list-units 'php*fpm*'# Restart the one that serves your site$ sudo systemctl restart php8.3-fpm# On RHEL/Alma/Rocky the service is usually just php-fpm$ sudo systemctl restart php-fpmA graceful reload also works, but when you’re patching a critical flaw a full restart removes any doubt that old workers are gone.
For apache2handler, PHP lives inside Apache, so you restart Apache itself:
$ sudo systemctl restart apache2# or, on RHEL / AlmaLinux / Rocky$ sudo systemctl restart httpdA plain graceful can let old child processes linger; use restart so every worker reloads the patched module.
For litespeed, restart the LiteSpeed server (which also recycles its LSPHP processes):
$ sudo /usr/local/lsws/bin/lswsctrl restart# OpenLiteSpeed via systemd$ sudo systemctl restart lswsIn the LiteSpeed web admin you can also restart from the dashboard; either way confirm the external application (LSPHP) actually recycled.
On a panel server, use the panel’s own restart so it rebuilds configs correctly:
# cPanel: restart the PHP-FPM service for EasyApache$ sudo /scripts/restartsrv_apache_php_fpm$ sudo /scripts/restartsrv_httpd# Plesk: reread config and restart the PHP-FPM service$ sudo plesk bin service_node --restart-serviceAs a hosting customer without shell access, use the “Restart PHP” control in your panel if it has one, or ask support to restart PHP for your account.
On managed WordPress hosting you don’t restart PHP yourself; the host does. Many dashboards have a “Restart PHP” button. If Site Health still shows the old version after the host says they patched:
- Use any “Restart PHP” or “Flush” control in the dashboard.
- Clear the host’s object/page cache — a cached Site Health response can show stale data briefly.
- If it’s still wrong, ask support to confirm the patched PHP is live and restarted on your specific server. Our host email template asks exactly that.
After restarting, hard-reload Site Health
Cause 2: you checked the command line, not the web PHP
A classic false alarm in the other direction: you run php -v over SSH, it shows a patched version, and you assume the site is safe — or it shows an old version and you panic. Both can be misleading, because php -v reports the command-line PHP (the CLI SAPI), which is frequently a different version from the one serving your pages.
A server commonly has several PHP builds installed at once. The CLI might be 8.1 while your site runs on 8.3 via FPM, or the reverse. WP-CLI also uses the CLI PHP, so wp --info reflects the command line too — not your visitors’ PHP.
# This is the CLI PHP — NOT necessarily what serves the site$ php -v$ wp --info# The FPM binary that actually serves requests (adjust the version)$ php-fpm8.3 -v# Which php packages are installed, and their exact builds (Debian/Ubuntu)$ dpkg -l | grep -E 'php[0-9.]+-(fpm|cgi)|libapache2-mod-php'# RHEL / AlmaLinux / Rocky$ rpm -q php php-fpmThe tie-breaker
phpinfo() page shows the serving version and its build date — just delete the file immediately afterward.Cause 3: Docker image pulled, container not recreated
In a container setup, “update PHP” means moving to a fixed image tag — the official php images publish 8.5.12-*, 8.4.27-*, 8.3.36-* and 8.2.35-* (there are no maintained tags for 8.1 or older). But here’s the trap that catches everyone: pulling a new image doesn’t touch a running container. The container keeps running the old image until you recreate it.
# What is the RUNNING container actually on?$ docker exec <container> php -v# If you build your own image, pin a fixed tag (e.g. FROM php:8.4.27-fpm) then rebuild:$ docker compose build --pull# The step people forget — recreate the container from the new image:$ docker compose up -d --force-recreate# Plain docker: pull then recreate$ docker pull php:8.4.27-fpmTwo more gotchas. The official wordpress image is built on top of the php image, so it needs re-pulling or rebuilding too — updating only your own layer isn’t enough. And FrankenPHP users should move to v1.13.2 or later, which bundles the fixed PHP; again, the running process has to be recreated, not just the binary replaced on disk.
Cause 4 (not really a bug): the backport number trap
Sometimes the version genuinely didn’t change — and that’s fine. Linux distributions and several hosts fix security bugs by backporting the patch into their existing package without raising the upstream version number. So a site can be fully protected while Site Health still reads a number below the “fixed” one.
Concrete examples from the PHP2Shell rollout:
- A site was reported protected while still showing PHP 8.4.26 — lower than the upstream fixed
8.4.27— because its host applied a backport. - Ubuntu 24.04’s patched package still reports
8.3.6(build8.3.6-0ubuntu0.24.04.13, via USN-8948-1). - Plesk’s fixed 7.4/8.0/8.1 builds keep their old version numbers but carry an October 21, 2026 build date.
So a “low” number does not always mean unpatched. What you verify instead is the package revision and the CVEs, not the three-part version:
# Does the package changelog mention BOTH CVEs? (RHEL family)$ rpm -q --changelog php | grep -E 'CVE-2026-10961[89]'# Debian/Ubuntu: confirm the package revision matches the advisory$ dpkg -l | grep -E 'php[0-9.]+-fpm'# Check the installed build date against the advisory (adjust the version)$ php-fpm8.3 -vOn managed hosting, get it in writing
Cause 5: several PHP versions, and the site points at the wrong one
If the restart worked and it isn’t a backport, the update probably landed on a different PHP version or domain than the one serving your site. Multi-version setups make this easy to do:
Step 1: Per-domain MultiPHP (cPanel)
In MultiPHP Manager each domain can run a different branch (ea-php81,ea-php83…). Updating the server’s packages doesn’t move a domain that’s pinned to an old branch — change the domain’s version, or confirm the branch it’s on was itself patched.Step 2: The web server points at a specific socket
An Nginx/Apache vhost often targets one FPM socket, e.g.php8.1-fpm.sock. If you installed and restartedphp8.3-fpmbut the vhost still proxies to the 8.1 socket, your site is still on 8.1. Repoint the vhost and reload the web server.Step 3: You restarted the wrong FPM service
With severalphpX.Y-fpmservices installed, restartingphp8.2-fpmdoes nothing for a site served byphp8.3-fpm. Match the restart to the SAPI/version Site Health reports.
The quick way to untangle it: read the serving version in Site Health, find which socket or handler your vhost uses, and make sure the thing you updated and restarted is that exact one. Our guide to checking and updating PHP walks through installing versions side by side and repointing cleanly.
Confirm you’re actually fixed
Once Site Health shows the version you expect, sanity-check it. The checker below runs entirely in your browser — it takes the version, SAPI and hosting type you give it and tells you whether that combination still looks exposed, including the backport nuance. It can’t see your server, so it’s a guide, not a guarantee; your host’s or distro’s advisory is always the final word.
Interactive checker
Am I affected by PHP2Shell?
Runs in your browser · nothing is sent
- 1. PHP version
- 2. Server API
- 3. Hosting
- 4. Verdict
Then run this short close-out:
Step 1: Web-facing version matches a fix
Site Health shows 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 or a vendor-backported build you’ve verified covers both CVEs.Step 2: You confirmed, not assumed, for backports
If the number is lower because of a backport, you checked the changelog or got written confirmation that both CVEs are addressed.Step 3: Workers were restarted
The version changed after a restart, not just after an install — proof the running workers use the patched code.Step 4: You checked exposure during the window
If the site was online and unpatched between 17 and 21 October, run the “was I hacked?” checklist — a patch doesn’t remove anything already planted.
Tired of chasing PHP versions? Presscomet doesn't have one
Every one of the traps on this page — unrestarted workers, CLI-versus-web confusion, backport numbers, per-domain versions — exists because there’s a PHP interpreter in front of every request. Presscomet runs the WordPress admin, block editor, URLs and REST API on Node.js with a single SQLite file and no PHP runtime at all, so there’s no PHP version to track and the PHP-runtime class of bugs (PHP2Shell included) doesn’t apply. It’s not “unhackable”: Node.js, its npm dependencies, its own login and the host OS still get patched like anything else. It also doesn’t run PHP plugins (the common ones are built in) and doesn’t support WooCommerce.
If a stack with no PHP version to babysit sounds better than this, check your site against a migration — it only reads your public site and changes nothing on your server. For the patch-first path, keep our WordPress security guide and the full PHP2Shell guide handy. Either way, the finish line is the same: the web-facing PHP shows a fixed build, and you’ve proven it rather than hoped it.
Sources
Facts checked against these sources on October 24, 2026. Things change quickly; the vendor advisory always wins.
- [1]PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 security releases — PHP.net
- [2]PHP2Shell for WordPress: checking, restarting and the backport trap — Meow Apps
- [3]PHP2Shell: detection and verification guidance — Sophos
- [4]Two critical PHP flaws: find, mitigate and patch PHP2Shell — Qualys
- [5]PHP2Shell fixes by distro, control panel and PHP version — Digital Applied
- [6]USN-8948-1: PHP vulnerabilities (backported package versions) — Ubuntu
- [7]Debian security tracker: CVE-2026-109618 — Debian
- [8]Supported versions — PHP.net
Frequently asked questions
Why does Site Health still show the old PHP version after I updated?
Almost always because the PHP workers weren't restarted. PHP-FPM, Apache mod_php and LiteSpeed load PHP once and keep it resident, so a newly installed version isn't used until you restart the service. Other causes are checking the command-line PHP instead of the web one, a Docker container that was never recreated, or the version change being applied to a different PHP version or domain than the one serving your site.
Do I have to restart PHP-FPM after updating PHP?
Yes. Installing or upgrading the package puts the new files on disk, but the running FPM master and its worker processes keep the old code in memory until they restart. Run a restart such as systemctl restart php8.3-fpm (and your web server if it uses mod_php), then reload Site Health to confirm the new version is live.
Why does php -v show a different version than Site Health?
A server can have several PHP versions installed, each with its own SAPI. php -v reports the command-line PHP (the CLI SAPI, also what WP-CLI uses). Site Health reports the PHP that answers web requests for your site (fpm-fcgi, apache2handler or litespeed). For security that web-facing version is the one that matters, so trust Site Health over php -v.
My host shows PHP 8.4.26 — am I still vulnerable to PHP2Shell?
Not necessarily. Linux distributions and some hosts backport the security fix without bumping the version number, so a build reading 8.4.26 can be patched while 8.4.27 is the upstream fixed number. A site was reported protected while still showing 8.4.26. Don't judge by the number alone — confirm with your host or the distro advisory that both CVE-2026-109618 and CVE-2026-109619 are fixed, with a date.
I pulled a new Docker image but the PHP version didn't change. Why?
Pulling an image only downloads it. The running container keeps using the old image until you recreate it, for example with docker compose up -d --force-recreate (after docker compose build --pull if you build your own image). Check the running container with docker exec <container> php -v, and remember the official wordpress image is built on the php image, so it needs rebuilding or re-pulling too.
How do I confirm PHP2Shell is actually fixed on my site?
Read the web-facing version in Tools › Site Health › Info › Server and compare it with the fixed releases (8.5.12, 8.4.27, 8.3.36, 8.2.35) or a vendor-backported build. If the number is lower because of a backport, confirm against the vendor advisory or the package changelog that both CVEs are addressed. On managed hosting, ask support to confirm the patch and restart in writing.
Presscomet keeps your wp-admin, editor, URLs and content, and serves pages without PHP or MySQL. Check your site for free, then migrate in one click — your old site is only ever read.
Keep reading
- SecurityPHP2Shell and WordPress: are you affected, and how do you fix it?
Two critical bugs in PHP itself put almost every WordPress site on an affected runtime until the host patches it. Here’s what happened in plain English, a checker that tells you whether you’re affected, and step-by-step fixes for every kind of hosting.
- SecurityHow to check and update your PHP version in WordPress (2026)
Your PHP version decides whether your WordPress site still gets security fixes. Here’s how to find it in under a minute, what’s still supported, and a safe way to upgrade without breaking anything.
- HostingIs your WordPress host patched for PHP2Shell? What to ask (with an email template)
On most WordPress sites you can’t patch PHP yourself — your host has to. Here’s who is responsible on each kind of hosting, the four questions that get you a real answer, and a ready-to-send email.