PHP 8.5.12 is the newest release not affected by PHP2Shell (CVE-2026-109618, CVE-2026-109619). If you'd rather stay on your current branch, these releases are also fixed:
Uses Ondřej Surý's PPA. Pick the block that matches how PHP is wired into your web server.
sudo add-apt-repository -y ppa:ondrej/php sudo apt update sudo apt install -y php8.5 php8.5-cli php8.5-common php8.5-curl php8.5-gd \ php8.5-mbstring php8.5-mysql php8.5-xml php8.5-zip
Apache with mod_php (highest risk): switch the module over.
sudo apt install -y libapache2-mod-php8.5 sudo a2dismod php8.1 php8.2 php8.3 php8.4 2>/dev/null sudo a2enmod php8.5 sudo systemctl restart apache2
PHP-FPM (nginx or Apache with proxy_fcgi): point your pool and web server at the 8.5 socket, /run/php/php8.5-fpm.sock.
sudo apt install -y php8.5-fpm sudo systemctl enable --now php8.5-fpm # then update fastcgi_pass / SetHandler to /run/php/php8.5-fpm.sock and reload the web server
Make the command line use 8.5 too:
sudo update-alternatives --set php /usr/bin/php8.5
Can't change branch today? Staying on 8.2, 8.3 or 8.4 from the same PPA also fixes it: sudo apt update && sudo apt install --only-upgrade 'php8.3*' libapache2-mod-php8.3 (swap in your version), then restart Apache or PHP-FPM.
The patch takes effect only once every running PHP process has been replaced. Restart whatever runs PHP for you:
# Apache with mod_php: a full restart is required to load the new module sudo apachectl configtest && sudo systemctl restart apache2 # PHP-FPM: restart the new pool, stop and disable the old one, reload the web server sudo systemctl restart php8.5-fpm sudo systemctl disable --now php8.3-fpm # swap in your old version sudo nginx -t && sudo systemctl reload nginx # or: sudo systemctl reload apache2 # List anything else still running old code (needrestart ships with Ubuntu) sudo needrestart -r l
A full reboot is only needed if the system says so, usually because the same upgrade brought in a new kernel or libc:
[ -f /var/run/reboot-required ] && cat /var/run/reboot-required.pkgs || echo "No reboot needed" sudo systemctl reboot
Warning: restart apache2 drops requests in flight, and every site on the server is unavailable for a few seconds. Always run apachectl configtest first, because a config error stops Apache from coming back. Don't use reload or graceful after a mod_php upgrade, because they can leave old workers serving requests.
Warning: before rebooting a remote server, make sure you have console access (your provider's web console) in case SSH doesn't come back. Take a snapshot first, and check that the database and other services are enabled to start at boot: systemctl is-enabled apache2 php8.5-fpm mariadb.
Uses packages.sury.org. After adding the repository, install the packages and switch the module exactly as in the Ubuntu section.
sudo apt update && sudo apt install -y lsb-release ca-certificates curl curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" \ | sudo tee /etc/apt/sources.list.d/php.list sudo apt update sudo apt install -y php8.5 php8.5-cli php8.5-fpm
# Apache with mod_php sudo apachectl configtest && sudo systemctl restart apache2 # PHP-FPM sudo systemctl restart php8.5-fpm sudo systemctl disable --now php8.2-fpm # swap in your old version sudo nginx -t && sudo systemctl reload nginx # Find services still running old code (install it with: sudo apt install needrestart) sudo needrestart -r l # Reboot only if a kernel or libc update asks for it [ -f /var/run/reboot-required ] && cat /var/run/reboot-required.pkgs || echo "No reboot needed" sudo systemctl reboot
Warning: if you use Debian's own packages (apt install --only-upgrade php8.2 on bookworm, or php8.4 on trixie) instead of sury.org, the fixed versions are 8.2.35-1~deb12u1 and 8.4.27-1~deb13u1. You still need to restart Apache or PHP-FPM afterwards. Installing the package doesn't replace running workers.
Warning: restarting Apache or PHP-FPM drops requests in flight. On a remote server, make sure you have console access before you reboot.
Uses the Remi repository and needs EPEL. Swap 9 for 8 or 10 to match your release.
On 21 October, Remi did not yet have the fixed build. Run dnf info php after updating and confirm it shows 8.5.12 before you rely on it.
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm sudo dnf module reset -y php sudo dnf module enable -y php:remi-8.5 sudo dnf update -y 'php*'
RHEL-family systems run PHP through PHP-FPM by default. Restart it, then the web server:
sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart httpd # or, for nginx: sudo nginx -t && sudo systemctl reload nginx # Which services still run old code? (needs dnf-utils / yum-utils) sudo needs-restarting -s # Does the whole system need a reboot? Exit code 1 means yes sudo needs-restarting -r; echo "exit=$?" sudo systemctl reboot
Warning: Red Hat's own php packages keep their old version numbers when they backport fixes, so php -v can't tell you whether you're patched. Check the errata with dnf updateinfo list --cve CVE-2026-109618. As of 21 October, Red Hat had not published one.
Warning: dnf module reset php changes which PHP stream the server follows. Test your applications on 8.5 before doing this in production. Restarting httpd drops requests in flight, and on a remote server you need console access before rebooting.
SLES 15 SP7 has a fixed php8 package (8.3.36). Install just the PHP2Shell patches, or everything pending:
sudo zypper refresh sudo zypper list-patches --cve=CVE-2026-109618,CVE-2026-109619 sudo zypper patch --cve=CVE-2026-109618,CVE-2026-109619 # or update the PHP packages directly sudo zypper update 'php8*' 'apache2-mod_php8' php -v
# PHP-FPM and/or Apache with mod_php8 sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart apache2 # Processes still using deleted (old) files, grouped by service sudo zypper ps -s # Does the system need a reboot? Exit code 102 means yes sudo zypper needs-rebooting; echo "exit=$?" sudo systemctl reboot
Warning: as of 21 October, php7, the SLES 15 SP4–SP6 LTSS channels, openSUSE Leap and the BCI container images were still listed as affected. If zypper list-patches shows nothing for you, use the temporary mitigations below and a WAF until a patch lands.
Warning: restarting Apache drops requests in flight. On a remote server, make sure you have console access before rebooting.
Fedora ships recent PHP branches in its own repositories. Pull the updates once they reach updates; updates-testing often has them earlier.
sudo dnf upgrade --refresh 'php*' # not there yet? try the testing repo sudo dnf upgrade --refresh --enablerepo=updates-testing 'php*' php -v
sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart httpd # or: sudo nginx -t && sudo systemctl reload nginx # Reboot check (exit code 1 means a reboot is needed) sudo dnf needs-restarting -r; echo "exit=$?" sudo systemctl reboot
Warning: packages from updates-testing haven't finished Fedora's QA. Disable the repo again after the PHP update. Restarting httpd drops requests in flight.
AL2023 pins packages to a repository release. Moving to the newest release picks up fixed PHP once Amazon publishes it:
sudo dnf check-release-update sudo dnf upgrade --releasever=latest 'php*' php -v
sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart httpd sudo needs-restarting -r; echo "exit=$?" sudo systemctl reboot
Warning: as of 21 October, Amazon had not published a fixed PHP package (check the ALAS bulletins). Until php -v shows a fixed version, apply the temporary mitigations below and put the instance behind AWS WAF or another WAF with PHP2Shell rules.
Warning: --releasever=latest upgrades every package you name to the newest release, not just PHP. On EC2, check that the instance is behind a load balancer or has a recent AMI snapshot before rebooting. Instances in an Auto Scaling group should be replaced by rolling the launch template, not patched in place.
Package names include the branch (php84, php83, …). Upgrade the branch you use and check the version it reports:
apk update apk policy php84 # shows available versions; swap in your branch apk upgrade 'php84*' php84 -v
rc-service php-fpm84 restart rc-service nginx reload # or: rc-service apache2 restart reboot # only after a kernel (linux-lts / linux-virt) upgrade
Warning: Alpine hadn't published an advisory as of 21 October. If apk policy doesn't show a fixed version for your branch, use the temporary mitigations below. Most Alpine PHP runs in containers. There, rebuild the image and recreate the container (see Docker) instead of patching a running container.
Arch tracks the latest PHP. Always upgrade the whole system:
sudo pacman -Syu php -v
sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart httpd # or: sudo nginx -t && sudo systemctl reload nginx # Reboot if the kernel was upgraded (running kernel no longer installed) pacman -Q linux; uname -r sudo systemctl reboot
Warning: never run pacman -Sy php on its own. Partial upgrades are unsupported on Arch and can break the system. A full -Syu may also bring in a new kernel, which needs a reboot before kernel modules load correctly.
EasyApache 4 builds ea-php74 through ea-php85 carry the fix in the 21 October release. CloudLinux alt-php builds are rolling out.
# EasyApache 4 PHP versions sudo yum update 'ea-php*' # CloudLinux alt-php versions sudo yum update 'alt-php*' # Which PHP versions are installed and assigned /usr/local/cpanel/bin/rebuild_phpconf --current
/scripts/restartsrv_apache_php_fpm /scripts/restartsrv_httpd # Reboot check (CloudLinux/AlmaLinux base) sudo needs-restarting -r; echo "exit=$?" sudo reboot
Warning: on shared servers, each account can be set to a different PHP version. Update every installed ea-php and alt-php version, not just the default. Restarting httpd briefly interrupts every hosted site. Do it outside peak hours, and announce it if you have SLAs.
Pin the patched tag in your Dockerfile, then rebuild with --pull so you don't reuse a cached vulnerable layer.
# Dockerfile: pick the variant you use FROM php:8.5.12-apache # FROM php:8.5.12-fpm # FROM php:8.5.12-cli
docker build --pull --no-cache -t myapp .
Containers have to be recreated from the new image. Restarting an existing container keeps the old, vulnerable PHP.
# Docker Compose docker compose up -d --force-recreate # Plain Docker docker stop myapp && docker rm myapp docker run -d --name myapp [your previous flags] myapp # Kubernetes: roll out the new image and wait for it to finish kubectl set image deployment/myapp app=registry.example.com/myapp:php-8.5.12 kubectl rollout status deployment/myapp # Confirm what is actually running docker exec myapp php -v
Warning: docker restart and docker compose restart do NOT pick up a new image. Recreating a container drops anything written inside it that isn't on a volume, so check your volumes first. Rebuild every image that uses FROM php:…, including base images other teams maintain.
Warning: the host only needs a reboot if its own kernel was updated. The PHP fix lives entirely inside the image.
brew update brew upgrade php php -v
# PHP-FPM managed by Homebrew brew services restart php # Homebrew Apache or nginx, if they serve PHP brew services restart httpd brew services restart nginx # Local dev servers (php -S, Laravel Valet/Herd, etc.): stop and start them again valet restart
Warning: a versioned formula such as php@8.3 doesn't move to 8.5 on its own. Run brew upgrade php@8.3 to get 8.3.36, or switch with brew unlink php@8.3 && brew link php. No reboot is needed.
Download the 8.5.12 zip from windows.php.net/download. Choose Thread Safe for Apache's mod_php and Non Thread Safe for IIS or FastCGI. Stop the web server before extracting, otherwise running php-cgi.exe processes keep the old DLLs locked. Then extract over your existing PHP folder, keeping your php.ini.
# IIS iisreset /stop # ...extract PHP 8.5.12 over C:\PHP, keep php.ini... iisreset /start # Or recycle a single site's app pool instead of all of IIS Import-Module WebAdministration Restart-WebAppPool -Name "MySitePool" # Apache service Stop-Service Apache2.4 # ...extract PHP 8.5.12... Start-Service Apache2.4 # Make sure no old PHP is still running Get-Process php-cgi, php -ErrorAction SilentlyContinue # Reboot only if Windows itself asks for it Restart-Computer -Confirm
Warning: iisreset takes every site on the server offline until IIS starts again. Recycling a single app pool doesn't. If files are still locked after IIS stops, check for leftover php-cgi.exe processes before replacing anything.
Warning: before restarting a remote Windows server, make sure you can reach it over RDP or an out-of-band console, and that IIS and Apache are set to start automatically.
Rebuild with the same ./configure flags you used before. php -i | grep "Configure Command" prints them.
curl -LO https://www.php.net/distributions/php-8.5.12.tar.xz tar xf php-8.5.12.tar.xz && cd php-8.5.12 ./configure --prefix=/usr/local/php85 [your previous flags] make -j"$(nproc)" && sudo make install
# Restart the services that load your custom build (names vary by setup) sudo systemctl restart php-fpm sudo apachectl configtest && sudo systemctl restart apache2 # Confirm the running FPM master was started from the new binary ps -o pid,lstart,cmd -C php-fpm | head -3 /usr/local/php85/sbin/php-fpm -v
Warning: make install overwrites the binary, but processes that were already running keep the old code in memory until they're restarted. If you installed under a new prefix, update your service unit, Apache LoadModule line or PATH to point at it. Otherwise you'll restart into the old version.
Check the version the web server runs, not just the command line. They are often different binaries.
php -v php-fpm8.5 -v 2>/dev/null # what the web server actually runs (delete the file afterwards): echo '<?php echo PHP_VERSION;' | sudo tee /var/www/html/v.php curl -s http://localhost/v.php; echo; sudo rm /var/www/html/v.php
Then stop advertising your version. Set this in the php.ini your web server loads, and restart:
expose_php = Off
These branches are end-of-life, and there are no official fixed binaries for them. Upgrade to 8.5.12 using the steps above. If you can't upgrade right away, PHP published source-only backports for 7.4, 8.0 and 8.1, and your distro or LTS vendor may ship them. Until then, take the site offline or put it behind a WAF that has PHP2Shell rules.
php.net's temporary mitigations reduce exposure but are not a fix. Put them in php.ini or your FPM pool, not in .user.ini or ini_set(), then restart every worker:
memory_limit = -1 ; enforce with php_admin_value so apps can't override it post_max_size = 8M ; 32M if you need uploads; keep upload_max_filesize below it session.upload_progress.enabled = 0 fatal_error_backtraces = 0 ; PHP 8.5 only
Remove memory_limit = -1 once you're patched. It lets a single request use all of the server's memory.