PHP2Shell (CVE-2026-109618 and CVE-2026-109619): Critical PHP Flaws and How to Patch Your VPS
Two critical PHP flaws, CVE-2026-109618 and CVE-2026-109619 (PHP2Shell), allow unauthenticated remote code execution. Here is what they are and how to patch your VPS or server.
What is PHP2Shell?
PHP2Shell is the nickname for two separate vulnerabilities in the PHP runtime, published together on 21 October 2026 with a coordinated security advisory from the PHP project. PHP's own advisories refer to them only by CVE number:
- CVE-2026-109618: remote code execution via out-of-memory corruption.
- CVE-2026-109619: remote code execution via stale global state.
Both were rated Critical, 9.2 on CVSS v4.0, and PHP confirmed that both can be exploited without logging in. The advisories credit the researchers who reported the flaws, and the fixes were developed by PHP contributors Arnaud Le Blanc, Ilija Tovilo, Jakub Zelenka and Nora Dossche. Wiz Research was among the disclosing parties and said the underlying weaknesses had existed for a long time, but that exploiting them needed an unusually complex chain of steps. In Wiz's account, frontier AI models lowered that barrier considerably.
The disclosure was not a complete surprise. CERT-EU published an advisory naming both CVE IDs on 20 October, and PHP sent an advance notice to the oss-security mailing list the same day. Linux distributions and long-term support vendors received the patches ahead of the public release.
How the two bugs work
You do not need to read PHP's source code to follow the idea. Both bugs come down to the same theme: PHP can be left holding a pointer to memory that has already been thrown away, and later code trusts it.
CVE-2026-109618: out-of-memory corruption
Every PHP request has a memory limit. When a request crosses it, PHP aborts by jumping straight out of whatever it was doing. In a few places, PHP has request data that is only half set up at that moment, and the abrupt exit leaves it in a broken state. The cleanup code that runs at the end of the request then reads that broken data as though it were valid, which corrupts memory.
An attacker can force the out-of-memory condition on purpose with a crafted file-upload (multipart) request, for example one with a huge number of headers or many empty file fields, while staying inside PHP's normal upload limits. PHP demonstrated full remote code execution over HTTP against Apache's built-in PHP module (mod_php) with default limits, before any application code runs at all. The upstream fix stops PHP from aborting mid-operation when memory runs out and ends the request at the next safe point instead.
CVE-2026-109619: stale state between requests
A PHP worker handles many requests one after another and keeps some global state (about errors, sessions and extensions) that points into the current request's memory. That state must be cleared before the memory is freed. If a request is cut short by a fatal error, including running out of memory, some of it is never cleared. On the next request handled by the same worker, a few things run before PHP's normal setup and can use that stale state after its memory has been freed.
PHP confirmed two of these early paths:
- Warnings raised while applying per-directory or per-request PHP settings, such as
.htaccesssettings under mod_php, orPHP_VALUEsettings that nginx or Apache pass to PHP-FPM. Turning off error display or logging, or using the@operator, does not prevent it. - Session upload progress, a feature that is on by default and works even if the application never uses sessions.
PHP validated remote code execution through the upload-progress path against both mod_php and PHP-FPM. For PHP-FPM, success depends on the application offering an operation that an attacker can make fail.
A note on terminology: different security vendors have described the exact technical chains in slightly different words. We follow PHP's advisories and the AlmaLinux analysis here. If you need the low-level detail, read the two GitHub advisories listed in the sources.
Who is affected
PHP's advisory says every installation that serves web requests is at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. Risk is highest for mod_php, where a single unauthenticated request can trigger the attack before any application code runs.
What that means in practice:
- The application does not have to be vulnerable. The flaws are in the PHP engine, so WordPress, Magento, Laravel and every other framework are exposed even when their own code is clean. Sansec reports that researchers confirmed unauthenticated code execution against Magento 2.4.9 and ten other PHP applications, including WordPress, Drupal and Joomla.
- PHP-FPM is not a safe harbour. PHP confirmed remote code execution against PHP-FPM through CVE-2026-109619. For CVE-2026-109618, PHP's analysis says FPM is susceptible, but no complete exploit against it has been shown. Red Hat notes that standard RHEL deployments use PHP-FPM and that exploiting CVE-2026-109618 there is difficult in practice, typically needing non-default behaviour.
- It reaches back a long way. Sansec says the vulnerable code dates to PHP 5.4.0 (2012), and watchTowr's FAQ says every release from PHP 5 onward is affected, though watchTowr notes that last point has not been confirmed by an official vendor advisory.
- The exposure is huge. Palo Alto Networks' Unit 42 said its Cortex Xpanse telemetry found more than 22.6 million internet-exposed instances potentially vulnerable.
The code runs as whatever account PHP runs under (for example the web server user, or a hosting account's user). That account's files, databases and credentials are what an attacker gets first.
Severity and exploitation status
- CVSS v4.0 score: 9.2 (Critical) for each CVE, per the PHP project and as relayed by CERT-EU, Unit 42 and others.
- Red Hat rates CVE-2026-109618 Important and classifies it as a use-after-free (CWE-416).
- Working exploits exist at least inside the research community. PHP's advisory describes a demonstrated exploit against Apache with mod_php, and watchTowr says it has reproduced CVE-2026-109618.
- Reports of real-world attacks conflict. Contabo's customer notice states that active exploitation has been reported, and watchTowr's FAQ lists both CVEs as exploited. SOCRadar, by contrast, wrote on 21 October that PHP had not reported in-the-wild exploitation and that CISA had not added either CVE to its Known Exploited Vulnerabilities catalog. We cannot settle that from here, so treat it as urgent: unpatched, internet-facing PHP should be assumed to be a target.
- Authorities are alarmed. The UK's National Cyber Security Centre urged organisations to consider taking offline any system that cannot be fixed right away. Cloudflare says it has already deployed initial WAF rules for the known exploit vectors, available to all customers including free plans. That reduces exposure but is not a fix.
What hosting providers are telling customers
Providers are emailing customers about this, and the message is worth understanding because it applies to almost every unmanaged VPS. Contabo's notice is a good example. Its main points:
- The provider has no access inside your VPS, VDS or dedicated server and cannot apply the update for you. If you manage the operating system, you own the PHP patch.
- Customers are asked to install the update as soon as patched packages are available for their system.
- Both flaws are rated 9.2 on CVSS v4.0, and the notice says active exploitation has been reported.
- Customers are told to take a snapshot or backup first, update through the package manager or control panel, restart PHP-FPM or the web server, and verify the version actually in use.
- Interim measures from PHP's advisory reduce exposure but do not make an installation safe. Updating is the only complete fix.
If you are a VPS customer, this is the opposite of the kernel-level flaw we covered recently: here your provider cannot fix it and the responsibility is yours. If you use a managed plan, a managed hosting panel or a platform that handles PHP for you, ask your provider when their PHP builds were updated and do not assume it has happened.
Fixed PHP versions and end-of-life releases
PHP branch | Fixed release | Status |
|---|---|---|
8.5 | 8.5.12 | Supported |
8.4 | 8.4.27 | Supported |
8.3 | 8.3.36 | Supported |
8.2 | 8.2.35 | Security fixes only; end of life on 31 December 2026, so plan an upgrade |
8.1 and older | No upstream fix | End of life |
If you run PHP 8.1 or older, the PHP project is not releasing regular fixes. Your options are to upgrade to a supported branch, or to get backported fixes from your distribution or a long-term support vendor. As an exception, the PHP security team released minimal source-code backports for PHP 7.4, 8.0 and 8.1, but they are meant for people who build PHP from source or have no LTS vendor, and they are not packaged builds. Applications on PHP 5.5, 7.2, 7.3, 7.4 or 8.1 that rely on no backport remain vulnerable.
If you use the Remi repository (rpms.remirepo.net), note that this volunteer-maintained repository was not going to have updates on release day. The PHP project recommends switching to distribution packages or building from source if you need to patch immediately.
How to fix it, panel by panel and distro by distro
Before you start on any server: take a snapshot or backup, then update, then restart (an update does not affect a running worker until it restarts), then verify.
cPanel/WHM and EasyApache 4
Contabo's notice says updates for EasyApache 4 are already available. Run the cPanel update from WHM or on the command line, then restart PHP-FPM or Apache and confirm every PHP version in use:
/scripts/upcpcPanel's announcements and release notes are at docs.cpanel.net.
Plesk Obsidian
Contabo's notice says updates for Plesk Obsidian are already available. Update through the Plesk panel, then check each PHP handler you have enabled for your subscriptions.
CloudLinux (Alt-PHP)
Follow the CloudLinux status page and the CloudLinux blog for Alt-PHP builds. CloudLinux also offers extended support for PHP versions that are no longer maintained, which is the realistic route if you are stuck on an old branch.
AlmaLinux 8, 9 and 10
AlmaLinux says all three releases ship affected PHP versions. Its team is backporting the fixes ahead of Red Hat and expected patched packages in the testing repository on 21 October, followed by production after community verification. Check the AlmaLinux post for the exact package versions and testing instructions rather than guessing them. The streams being patched are:
- AlmaLinux 8:
php:7.4andphp:8.2 - AlmaLinux 9: the default PHP 8.0, plus
php:8.2andphp:8.3 - AlmaLinux 10: the default PHP 8.3, plus PHP 8.4 (
php8.4packages) - Kitten 10: the fix arrives in the next regular PHP update
Once packages reach your repository:
sudo dnf update 'php*'
sudo systemctl restart php-fpmThe retired streams (php:7.2, php:7.3 and php:8.0 on AlmaLinux 8, and php:8.1 on AlmaLinux 9) are not in the first round. php:7.2 is still the default stream on AlmaLinux 8, so if you installed PHP there without choosing one, that is what you have. Check which stream is enabled (marked [e]) and move to a supported one after testing your applications:
dnf module list php
sudo dnf module reset php
sudo dnf module enable php:8.2
sudo dnf distro-sync 'php*'AlmaLinux 8 can also run PHP through Apache's mod_php if Apache uses the prefork MPM, which is the highest-risk setup. To check:
httpd -M 2>/dev/null | grep -E 'mpm_|php'If the output includes mpm_prefork_module and a php_module, you are running mod_php. AlmaLinux 9 and 10 do not ship mod_php, and the AlmaLinux packages use PHP-FPM by default. Note that AlmaLinux's packages only update PHP installed from AlmaLinux's own repositories, not PHP from a control panel or a third-party repository.
RHEL, Rocky Linux, Oracle Linux and other RHEL-family systems
Red Hat's CVE page rates CVE-2026-109618 Important and tracks it in Bugzilla 2553995. At the time AlmaLinux published, Red Hat had not released fixed PHP packages. Rebuilds such as Rocky Linux normally follow Red Hat's release. Check regularly:
sudo dnf check-update 'php*'When packages appear, update and restart PHP-FPM or httpd.
Ubuntu and Debian
We did not find a published fix status for either at the time of writing. Check Canonical's CVE pages and the Debian Security Tracker for CVE-2026-109618 and CVE-2026-109619 and the fixed package version for your release. When a fix is listed, a normal system update applies it, and you then need to restart the PHP service. On servers with several PHP versions installed, restart each one:
sudo apt update
sudo apt upgrade
sudo systemctl restart php8.3-fpm # adjust to your PHP version
sudo systemctl restart apache2 # if you use Apache with mod_phpBuilding from source, containers and everything else
Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 from php.net, or to the matching official image if you run containers, then rebuild and redeploy. A running container keeps the old PHP until it is replaced.
8. Mitigations if you cannot update yet
The PHP project's advisory lists configuration measures that reduce exposure to specific attack paths. None of them make an installation safe, and several break features. Treat them as stopgaps for hosts you cannot patch within hours. After changing a PHP setting, restart every PHP worker. Apply these in php.ini, a file in your conf.d directory or a PHP-FPM pool, not with ini_set() or a .user.ini file, which take effect too late.
Measure | Targets | What it costs |
|---|---|---|
| CVE-2026-109619 (the confirmed upload-progress path on mod_php and PHP-FPM) | Upload progress bars stop working. PHP suggests keeping it off after patching if you do not need it |
Remove invalid or deprecated PHP settings applied per directory or per request that produce warnings ( | CVE-2026-109619 (warnings are one of two confirmed triggers) | Configuration work. Hiding warnings with |
Set | CVE-2026-109618 | PHP stops capping per-request memory, so you need a container or cgroup memory limit as a backstop |
Low | CVE-2026-109618 | Large forms and uploads fail |
| CVE-2026-109619 (stops one request leaving state for the next on the same worker) | Slower, because every worker is recycled after one request |
| CVE-2026-109619 | Less detail in fatal-error output |
Fix fatal errors and timeouts an attacker can trigger, including in callbacks, import and cleanup code | CVE-2026-109619 (the confirmed PHP-FPM path starts with a failure in your application) | Developer time |
A basic example for session upload progress, from AlmaLinux's guidance (use your distribution's conf.d path):
echo 'session.upload_progress.enabled = 0' | sudo tee /etc/php.d/99-php2shell.ini
sudo systemctl restart php-fpmTwo cautions from the AlmaLinux write-up. First, use a container or cgroup memory limit that kills only the affected worker. Do not use RLIMIT_AS or RLIMIT_DATA instead, as they can trigger the vulnerable path. Second, if you run mod_php, which PHP considers the highest-risk setup, switching to the event MPM with PHP-FPM removes the paths PHP confirmed against mod_php that do not depend on the application.
Edge protection. Cloudflare has deployed WAF rules for the known exploit vectors, including for free plans. Sansec also suggests blocking multipart/form-data requests at the web server if you cannot patch within the hour, which breaks every upload, and in the worst case making the site read-only or taking it offline. Those measures buy time. They do not repair PHP.
9. How to verify the fix and check for compromise
Verify the version.
- Restart, then check. An updated package does not affect a running PHP-FPM or Apache worker until it restarts. Without a restart, the old code keeps running.
- Check the command-line version with
php -v, but remember the command line and your web server can use different PHP builds. - Check what your web server really runs. Load a
phpinfo()page through the web server, then delete it. On servers with several PHP versions (common on control panels), check every installed version, not just the default. - Mind backports. Distribution packages often keep an older-looking version number. Check the package changelog instead, for example:
rpm -q --changelog php | grep -i CVE-2026-10961
apt changelog php8.3-fpm | grep -i CVE-2026-10961Look for signs of compromise, especially if the server ran an unpatched, internet-facing PHP site after the disclosure:
- Unknown or recently modified PHP files in web directories.
- New cron jobs for the web user or hosting accounts.
- Unfamiliar processes, and spikes in CPU load or outgoing traffic.
- New administrator accounts or unexpected plugins in your CMS.
# PHP files modified in the last 2 days (adjust the path)
find /var/www -name '*.php' -mtime -2 -ls
# cron jobs for the web user (adjust the user)
sudo crontab -l -u www-dataBecause the attacker's code runs as the PHP account, rotate database passwords, API keys and any credentials stored in configuration files if you suspect a compromise, and restore from a known-good backup rather than trusting a cleaned-up copy.
Best practices going forward
- Turn on automatic security updates where possible, and review your control panel's update settings.
- Remove PHP versions and applications you no longer use. Every extra PHP version on a server is another thing to patch and verify.
- Plan the move off PHP 8.2 before it reaches end of life on 31 December 2026, and off anything older now.
- Keep your CMS, plugins and themes up to date. This flaw is in PHP, but the next one may be in a plugin.
- Put a web application firewall in front of the site and restrict access to administrative interfaces.
- Take snapshots before every major update, so a bad update is a five-minute rollback.
- Subscribe to your distribution's and panel's security announcements, so you hear about patches on day one.
Sources
- PHP project security advisory, 21 October 2026 (php.net archive 2026)
- PHP GitHub advisories: GHSA-w8hw-w9fx-j79w (CVE-2026-109618) and GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- PHP advance notice on the oss-security mailing list, 20 October 2026
- AlmaLinux blog: php2shell (CVE-2026-109618, CVE-2026-109619): patches in progress (21 October 2026)
- Red Hat Customer Portal: CVE-2026-109618
- Help Net Security: PHP2Shell, critical PHP vulnerabilities patched, update now (21 October 2026)
- Wiz Research: PHP2Shell write-up
- Sansec Research: PHP2Shell, critical PHP RCE
- Palo Alto Networks Unit 42: threat brief on CVE-2026-109618 and CVE-2026-109619
- watchTowr Intelligence: PHP remote code execution FAQ
- SOCRadar: PHP2Shell analysis
- Brandefense: PHP2Shell analysis
- ma.ttias.be: early mitigation steps
- UK NCSC: critical security issue affecting PHP
Security advisories change quickly. This post reflects what vendors and researchers had published as of 21 October 2026. If you spot something out of date, tell us and we will update it.
Ruby