PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, the two critical unauthenticated remote code execution bugs known as PHP2Shell, which are already being exploited. This guide gives the update, restart and verification steps for each way PHP is commonly installed: distribution packages on Ubuntu, Debian and the Red Hat family, the Ondřej Surý and Remi repositories, cPanel EasyApache and CloudLinux alt-php, Plesk, Docker and Kubernetes, MassiveGRID PaaS, Windows, macOS, and source builds including the official backport branches for PHP 7.4, 8.0 and 8.1. For the background, read what the vulnerabilities are and who is exposed; if a server cannot be patched today, see the alternatives.
Before you start: find every PHP on the server
Most servers that have been around for a while carry more than one PHP, and each one needs updating. Spend two minutes on inventory first.
# which PHP answers on the command line, and which server processes are running
php -v
ps -eo pid,user,lstart,cmd | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp|[f]rankenphp'
# Apache: is mod_php loaded?
apachectl -M 2>/dev/null | grep -i php
# Debian and Ubuntu: every installed PHP package and its version
dpkg -l 'php*' | awk '/^ii/{print $2, $3}'
ls /etc/php/
# RHEL, AlmaLinux, Rocky: packages and the enabled module stream
rpm -qa 'php*' | sort
dnf module list --enabled php 2>/dev/null
# cPanel: EasyApache PHP versions and per-domain assignments
/usr/local/cpanel/bin/rebuild_phpconf --current
ls /opt/cpanel/ | grep ea-php
# CloudLinux alt-php
ls /opt/alt/ | grep php
# Plesk handlers
plesk bin php_handler --list
# Docker
docker ps --format '{{.Names}} {{.Image}}' | grep -i php
Write down each PHP and the server API that runs it. Update Apache with mod_php first, because the PHP advisory rates it the highest risk, then PHP-FPM, LiteSpeed and FrankenPHP.
What "fixed" looks like on each kind of install
Upstream PHP and the repositories that track it (packages.sury.org, Remi, the Docker official images, Homebrew, the Windows builds, cPanel EasyApache, Plesk PHP) move to the new version number, so 8.5.12, 8.4.27, 8.3.36 or 8.2.35 in php -v means you are done. Debian, Ubuntu and Red Hat backport the fix into the version they already ship, so the version string stays the same and only the package release changes. On those systems, verify with the package changelog or the security advisory, never with php -v.
Last verified: 21 October 2026, 15:00 UTC. Vendor status changes hourly in the first days of a release; the modified date on this post moves each time the table is refreshed.
| Platform | Package | Fixed build to look for | Status at the time of writing (21 October, afternoon UTC) |
|---|---|---|---|
| Ubuntu 24.04 | php8.3 | 8.3.6-0ubuntu0.24.04.13 | Published; mirrors may lag by an hour or two |
| Ubuntu 22.04 | php8.1 | 8.1.2-1ubuntu2.28 | Built, awaiting publication |
| Ubuntu 26.04 | php8.5 | 8.5.4-0ubuntu1.5 | Built, awaiting publication |
| Ubuntu 20.04 and 18.04 | php7.4, php7.2 | Through Ubuntu Pro (ESM) only | Depends on Canonical backporting |
| Debian 13 trixie | php8.4 | 8.4.27-1~deb13u1 (trixie-security) | Published, amd64 and arm64 |
| Debian 12 bookworm | php8.2 | Pending | Watch the Debian security tracker |
| Debian 11 bullseye | php7.4 | No free fix (LTS ended 31 August 2026) | Freexian ELTS or source backport |
| packages.sury.org (Debian and Ubuntu) | php5.6 to php8.5 | Builds dated 20261021, e.g. 8.4.27-1+0~20261021… | amd64 published; arm64 and the Launchpad PPA pending |
| RHEL 8, 9, 10 and clones | php module streams | Errata naming the CVEs | Nothing published yet |
| Remi | php, php84-php-* and so on | Upstream version numbers | No update on release day; PHP advises distribution packages or source |
| cPanel EasyApache 4 | ea-php82, ea-php83, ea-php84, ea-php85 | Packages carrying 8.2.35, 8.3.36, 8.4.27, 8.5.12 | Watch the EasyApache 4 changelog |
| CloudLinux | alt-php82 and so on | Upstream numbers; HardenedPHP backports for EOL versions | CloudLinux has said packages are being prepared |
| Docker official images | php:8.x-* | Tags 8.5.12, 8.4.27, 8.3.36, 8.2.35 | Rebuilt within hours of upstream |
These statuses were accurate when this post was written and will be out of date quickly. The rule that stays true: check your own package manager before deciding you are patched.
Ubuntu and Debian
Refresh the package lists, see what is waiting, and upgrade only the PHP packages so you do not pull an unrelated reboot into an emergency change. Run the install line once per PHP version on the server.
sudo apt-get update
apt list --upgradable 2>/dev/null | grep php
# replace 8.3 with each version you found in the inventory
sudo apt-get install --only-upgrade 'php8.3*' libapache2-mod-php8.3
If the new build is not offered yet, apt-cache policy php8.3-fpm shows which mirror you are on and which version it has; a lagging mirror is the usual reason. On Ubuntu, security.ubuntu.com is updated before the country mirrors.
Verify by changelog on Ubuntu, where the entry names the CVEs:
zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.3-fpm/changelog.Debian.gz
On Debian and the sury.org packages the changelog may only say "New upstream version", so compare the installed version from dpkg -l against the table above instead.
Ubuntu 20.04 and 18.04 only receive the fix through Ubuntu Pro, where sudo pro fix CVE-2026-109618 applies it once Canonical has built it. Debian 11 has no free fix, so a bullseye host running PHP 7.4 needs the source backport, Freexian's paid ELTS, or an upgrade to bookworm.
If you use Ondřej Surý's packages, note that packages.sury.org and the Launchpad PPA ppa:ondrej/php are separate sources that were updated at different times on release day. apt-cache policy tells you which one your server is on.
RHEL, AlmaLinux, Rocky Linux and Remi
Red Hat backports fixes into the module stream you have enabled, so check the stream first, then upgrade the PHP packages and confirm with the security metadata.
dnf module list --enabled php
sudo dnf upgrade 'php*'
# verification: the errata list and the package changelog should name the CVEs
dnf updateinfo list --security | grep -i php
rpm -q --changelog php-fpm | grep -E 'CVE-2026-10961[89]'
Two traps on this family. First, a bare dnf install php on RHEL 8 installs the retired 7.2 stream, which gets no fixes at all; if that is what you have, switch streams before you patch (dnf module reset php, dnf module enable php:8.2, dnf distro-sync), and test the application because that is a major version change. Second, Red Hat's errata were not out when this was written, so a server that reports "nothing to do" may simply be waiting. Keep polling dnf check-update 'php*' rather than assuming you are done.
For the Remi repository the PHP project's advice was direct: the volunteer-maintained repository would not have the update on release day, and users should move to distribution packages or build from source so they can apply updates immediately. If you stay on Remi, the Software Collections style packages update with sudo dnf upgrade 'php84-*' (adjust the version) followed by systemctl restart php84-php-fpm, once the builds appear.
Restart the right process, then confirm nothing old is running
A patched binary on disk protects nothing until every worker has been restarted. The table lists what to restart for each setup and the shortcuts that do not work.
| Setup | Command | Note |
|---|---|---|
| PHP-FPM (Debian, Ubuntu) | sudo systemctl restart php8.3-fpm | One service per version. A reload also loads the new binary but can drop in-flight requests unless process_control_timeout is set. |
| PHP-FPM (RHEL family) | sudo systemctl restart php-fpm | Remi SCL packages use php84-php-fpm and similar names. |
| Apache with mod_php | sudo systemctl restart apache2 or httpd | A full restart. apachectl graceful and reload keep the old module in the running children. |
| LiteSpeed and OpenLiteSpeed | Upgrade the lsphpXY packages from LiteSpeed's repository, then sudo pkill lsphp | The server respawns workers with the new binary. |
| FrankenPHP | Install the new release or pull the new image; check frankenphp version | PHP is linked into the binary, so FrankenPHP itself has to be updated. |
| Laravel Octane, Swoole, RoadRunner | Restart the server process | octane:reload reloads workers, not the PHP runtime. |
| Queue workers and Supervisor jobs | php artisan queue:restart, supervisorctl restart all | Long-running CLI processes keep the old engine until restarted. |
Then confirm that no process is still mapping a replaced library. Empty output means every process is on the new files:
sudo grep -lE ' /(usr|lib|opt).*\(deleted\)$' /proc/[0-9]*/maps 2>/dev/null
# Debian and Ubuntu alternative
sudo needrestart -b -r l
Finally, confirm the web path and not just the shell. Drop a temporary file containing <?php echo PHP_VERSION; into the document root, request it, and delete it. On a distribution build it still prints the old version string, which is expected; what you are checking is that the request is served by the process you just restarted. The X-Powered-By header, where expose_php is on, gives the same information without a file.
cPanel, WHM, CloudLinux and LiteSpeed
cPanel builds its own PHP packages (ea-php82, ea-php83, ea-php84, ea-php85) and ships them through the EasyApache 4 repository, so the fix arrives when cPanel publishes rebuilt packages, not when php.net does. The EasyApache 4 changelog in WHM (Software, then EasyApache 4) and cPanel's release notes are the places to watch; at the time of writing the rebuilt packages had not yet appeared.
Once they have, the nightly upcp run applies them automatically if "Automatic Updates" for operating system packages is enabled in WHM under Update Preferences. To apply them immediately:
# AlmaLinux 8/9, Rocky, CloudLinux 8/9 (use yum on older systems)
sudo dnf clean all
sudo dnf update 'ea-php*' 'ea-apache24*'
# restart Apache and every PHP-FPM pool cPanel manages
/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpm
# verify each installed version
for p in /opt/cpanel/ea-php*/root/usr/bin/php; do "$p" -v | head -1; done
cPanel's packages follow the upstream version numbers, so 8.3.36 in that output means the fix is in. The MultiPHP Manager in WHM shows which version each domain uses; a domain pinned to a version you do not update stays vulnerable, so update every installed version or remove the ones nobody uses.
CloudLinux. The PHP Selector versions live in /opt/alt/ and are separate packages from EasyApache. CloudLinux said it was preparing alt-php builds and has historically backported security fixes into its end-of-life versions through HardenedPHP, which is the practical route for cPanel accounts still pinned to PHP 7.4, 8.0 or 8.1. Update with sudo dnf update 'alt-php*', then check /opt/alt/php83/usr/bin/php -v for each version. Accounts using the "native" version in the selector get the EasyApache package instead, so both sets need updating.
Imunify360. While you wait for packages, make sure the WAF ruleset is at 8.83 or later, which carries a signature for the known exploit pattern: check /etc/apache2/conf.d/modsec_vendor_configs/imunify360-full-apache/VERSION, and run imunify360-agent update --force modsec-rules if it is older. This narrows the window; it does not replace the package update.
LiteSpeed Enterprise on cPanel uses the same ea-php packages through LSAPI, so the steps above apply; restart LiteSpeed afterwards with /usr/local/lsws/bin/lswsctrl restart or from the WHM plugin.
Plesk
Plesk can serve PHP from two sources: the Plesk-built packages (plesk-php83 and so on, shown as "8.3.x by Plesk" in the handler list) and the operating system's own packages. The two are updated differently.
# list handlers and the version each one runs
plesk bin php_handler --list
# Plesk-built PHP: update the installed components from the current release
plesk installer --select-release-current --upgrade-installed-components
# OS-vendor PHP: use apt or dnf exactly as in the sections above
# restart the FPM services Plesk manages (one per version)
systemctl restart plesk-php83-fpm
# or re-read all handlers at once
plesk bin php_handler --reread
The same update runs from the panel under Tools and Settings, then Updates, then "Add/Remove Components", and Plesk's own automatic updates install it at the next scheduled run if they are enabled. Plesk-built packages carry the upstream version number, so 8.3.36 in the handler list means done; OS packages need the changelog check described earlier.
Docker, Kubernetes and MassiveGRID PaaS
Containers never update themselves. The official php images were rebuilt with the new versions within hours of the release, but a running container keeps whatever it was started from, and an image you built on top of php:8.3-fpm keeps the base layer it was built with until you rebuild it with a fresh pull.
# confirm the registry has the fixed build
docker run --rm php:8.3-fpm php -v
# images you build yourself: force a fresh base layer, then recreate
docker build --pull --no-cache -t myapp:$(date +%Y%m%d) .
docker compose pull
docker compose up -d --force-recreate
# verify inside the running container
docker exec myapp-php php -v
Pin to the full patch version (php:8.3.36-fpm-alpine) or to a digest in production so that a rollback is explicit and a future rebuild cannot silently reintroduce an old base. Images built on a distribution base with PHP from apt or dnf follow the distribution's timeline instead: rebuild them once the distribution package is published and verify by changelog inside the image.
On Kubernetes, change the image tag or digest in the Deployment and let the rollout replace the pods. kubectl rollout restart alone only helps if the pod spec uses a floating tag with imagePullPolicy: Always, and even then the manifest does not tell you which build you are on. FrankenPHP users pull the new dunglas/frankenphp image the same way and check frankenphp version.
MassiveGRID PaaS. On MassiveGRID PaaS, built on Virtuozzo Application Platform (formerly Jelastic), the PHP engine is part of the application server node (Apache PHP, NGINX PHP or LiteSpeed). To update, open the environment, click the settings icon on the application server layer, choose Redeploy, and select the newest tag of the same PHP branch. Keep the "keep volumes data" option enabled so the mounted data volumes and the files listed for preservation survive the redeploy, and review that list before confirming if you have customised configuration outside those paths. If the patched tag is not yet offered for your stack, open a ticket and we will tell you when it is published. Environments with several application servers behind a load balancer can be redeployed one node at a time to avoid downtime.
Windows and macOS
Windows (IIS, Apache, or a bundle). Download the matching build from windows.php.net: Non Thread Safe (NTS) for IIS with FastCGI, Thread Safe for Apache with mod_php, and the same architecture and compiler tag as the build you have (VS16 for the 8.3 line, VS17 for 8.4 and 8.5), so that your existing extensions keep loading. Then:
- Stop the site:
iisreset /stop, or stop the Apache service. - Copy the current PHP folder aside as a backup, including
php.iniand theextfolder. - Extract the new zip over the folder, keeping your
php.ini. - Check
php -vfrom that folder and thatphp -mlists the extensions you rely on. - Start the site again and request a page that runs PHP.
Bundles such as XAMPP, WampServer and Laragon ship their own PHP folders; replace the folder with the matching build from windows.php.net if the bundle has not updated, and remember that these stacks are for development and should not be internet-facing in the first place.
macOS with Homebrew is a developer setup rather than a server, but the engine is the same:
brew update
brew upgrade php # or php@8.3, php@8.2
brew services restart php # if you run FPM through Homebrew
php -v
Homebrew's bottles can lag the release by some hours; brew info php shows the version the formula currently builds.
Building from source, and the PHP 7.4, 8.0 and 8.1 backport branches
If you compile PHP yourself, fetch the new tarball from php.net and rebuild with the configure options you used before (php -i | grep 'Configure Command' prints them). For the end-of-life branches, the PHP security team published minimal source-only backports of the two fixes, which is the only first-party route for 7.4, 8.0 and 8.1 outside a distribution's own backport:
# one of: PHP-7.4-CVE-2026-109618-109619, PHP-8.0-CVE-2026-109618-109619, PHP-8.1-CVE-2026-109618-109619
git clone --depth 1 --branch PHP-8.1-CVE-2026-109618-109619 https://github.com/php/php-src.git
cd php-src
./buildconf --force
./configure # with the options from your existing build
make -j"$(nproc)"
make test # optional but recommended on a branch like this
sudo make install
Restart the server API as above and check php -v, which on these branches still reports the base version (8.1.33 for example); the commit list on the branch is the evidence that the fixes are in. Understand what you are getting: the branch contains these two fixes and nothing else, so every other vulnerability fixed since that version's end of life is still present, and the branch will not be maintained. It buys time for a migration; it is not a way to stay on 8.1.
After patching
- Undo emergency settings deliberately. If you set
memory_limit = -1as a stopgap, put a real limit back; the patched engine has a hard memory ceiling that terminates a runaway worker safely.session.upload_progress.enabled = 0can stay off if nothing uses upload progress bars, and the PHP team suggests leaving it off. Remove edge rules that block uploads once every PHP behind them is patched. - Review the server if it was internet-facing and unpatched for more than a few hours, since exploitation began on release day. Recently modified PHP files in the document roots, unfamiliar scheduled jobs for the web user, and unexpected processes or connections owned by the web user are the first things to look at. A back door placed before the patch keeps working after it, so a careful review or a restore from a known-good backup is part of patching, not an optional extra.
- Automate the next one. On Ubuntu that is unattended-upgrades for the security pocket; on the Red Hat family it is
dnf-automaticwithupgrade_type = security; on cPanel it is automatic RPM updates in Update Preferences. None of them restart Apache for a mod_php update, so pair them with a reboot window or a post-update hook. - Schedule the version move if you are on 8.1 or older, and start planning for 8.2, which reaches end of life on 31 December 2026. The PHP 7 to 8 upgrade post covers what to test.
Frequently Asked Questions
How do I update PHP for CVE-2026-109618 on Ubuntu or Debian?
Run apt-get update, then apt-get install --only-upgrade for the php8.x packages of each version on the server, restart php8.x-fpm or do a full restart of Apache for mod_php, and confirm the package changelog names the CVE. Ubuntu 24.04 ships the fix as php8.3 8.3.6-0ubuntu0.24.04.13 and Debian 13 as php8.4 8.4.27-1~deb13u1; the version string in php -v does not change.
How do I update PHP for CVE-2026-109618 on RHEL, AlmaLinux or Rocky Linux?
Check the enabled module stream with dnf module list --enabled php, run dnf upgrade for the php packages, restart php-fpm or httpd, and confirm with dnf updateinfo list --security or the php-fpm package changelog. Red Hat backports the fix into the stream you have, so the version number stays the same, and the errata were still pending when this guide was written.
How do I update PHP for CVE-2026-109618 on Plesk?
For Plesk-built PHP, run plesk installer --select-release-current --upgrade-installed-components or use Tools and Settings, Updates, Add/Remove Components, then restart the plesk-php8x-fpm services. For OS-vendor PHP handlers, update with apt or dnf as for the distribution. plesk bin php_handler --list shows which handlers run which version.
How do I update PHP for CVE-2026-109618 on MassiveGRID PaaS?
Open the environment, click the settings icon on the application server layer, choose Redeploy and pick the newest tag of the same PHP branch, keeping the volume data option enabled. If the patched tag is not yet listed for your stack, open a ticket and we will tell you when it is published.
My Ubuntu server still shows PHP 8.3.6 after the update. Did it work?
Yes, if the package release moved. Ubuntu backports the fix into the version it ships, so php -v keeps reporting 8.3.6. Run dpkg -l php8.3-fpm and look for release 0ubuntu0.24.04.13 or later, or zgrep the changelog for CVE-2026-109618. The same applies to Debian and Red Hat.
apt says there is nothing to upgrade. What now?
Either your mirror has not synced yet or your release has not published the build. apt-cache policy php8.3-fpm shows the candidate version and the mirror it comes from; compare it to the fixed build in the table. If the security pocket on the canonical host has it and your mirror does not, point sources at security.ubuntu.com temporarily. If nobody has it yet, apply the interim measures and keep polling.
Is a graceful Apache reload enough after updating mod_php?
No. A graceful reload lets existing children finish their requests and start new ones from the same loaded module. Only a full restart (systemctl restart apache2 or httpd) loads the new PHP module. Verify with the replaced-library check afterwards.
I run PHP in Docker. Do I need to do anything if the official image was rebuilt?
Yes. Pull the new image and recreate the container; a running container never picks up a new image on its own. If you build your own image from php:8.3-fpm, rebuild it with --pull so the base layer is refreshed, then redeploy. Confirm with docker exec php -v inside the new container.
We are on cPanel. Can we just click Update in MultiPHP Manager?
MultiPHP Manager assigns versions to domains; it does not update packages. The update comes from the EasyApache 4 repository through upcp or a manual dnf update of the ea-php packages once cPanel publishes the rebuilt builds. Check the EasyApache changelog for 8.3.36 and the other fixed versions, update every installed ea-php version, restart Apache and PHP-FPM, and confirm with php -v for each version.
Our application only runs on PHP 7.4. What are the options?
In order of preference: a distribution backport (Ubuntu Pro for 20.04, CloudLinux HardenedPHP for cPanel accounts), the PHP security team’s PHP-7.4-CVE-2026-109618-109619 source branch built with your existing configure options, or restricting who can reach the application while you plan the move to a supported version. All three are stopgaps; 7.4 has had no fixes since November 2022 and this will not be the last critical bug in it.
Security patches applied by our engineers, on your schedule
MassiveGRID support plans include operating system updates and security patches, 24/7 monitoring and incident response for cloud servers and VPS, so an advisory like PHP2Shell is handled by people who patch servers for a living, with a change record you can hand to your auditor.
Compare Support PlansFurther Reading
- php.net: Security advisory with the fixed versions, vendor notes and the EOL backport branches
- php.net: downloads for PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35
- windows.php.net: Windows builds (NTS and Thread Safe, VS16 and VS17)
- GitHub: PHP-8.1-CVE-2026-109618-109619 backport branch (the 7.4 and 8.0 branches follow the same naming)
- Ubuntu security tracker: CVE-2026-109618 package status per release
- Debian security tracker: CVE-2026-109618
- Red Hat CVE database: CVE-2026-109618 errata status
- Docker Hub: official php image tags
- Mattias Geniar: how to apply the patches, with per-distribution package status updated through the day
- MassiveGRID: PHP2Shell explained, the vulnerabilities and who is exposed
- MassiveGRID: alternatives for servers that cannot patch yet