What the two vulnerabilities are
"php2shell" is the name used in reporting for two vulnerabilities in PHP itself, rather than in any framework or application. The php.net security advisory of 21 October 2026 describes them as follows:
- CVE-2026-109618, remote code execution via out-of-memory corruption. Out-of-memory handling can interrupt PHP while internal request data is only partly initialised, and request cleanup may then treat that invalid data as valid.
- CVE-2026-109619, remote code execution via stale global state. Internal state owned by one request can survive after its memory has been freed, and a later request handled by the same worker may use it.
The PHP project's advance notice of 20 October rated both 9.2 on CVSS v4.0. The advisory says every PHP installation serving web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, and that it considers the risk highest for mod_php, where a demonstrated exploit runs from an unauthenticated request before any application code does.
The advisory lists configuration changes that reduce exposure on some attack paths while an update is prepared, and says plainly that they do not make an installation safe. Updating is the fix.
Which versions get a fix
The PHP project released these four versions on 21 October 2026:
- PHP 8.5.12
- PHP 8.4.27
- PHP 8.3.36
- PHP 8.2.35
PHP 8.1 and older get no release. Security support for PHP 8.1 ended on 31 December 2025, according to both php.net and endoflife.date, and its last release was 8.1.34. PHP 8.0 and 7.4 had already reached the end of security support in 2023 and 2022.
Because of the severity, the PHP security team also published minimal source patches for 8.1, 8.0 and 7.4, for people who build PHP from source or have no vendor to turn to. These are branches of source code, not releases, and nothing else on those versions is being fixed.
One more date matters when choosing where to go: PHP 8.2's security support ends on 31 December 2026. PHP 8.3 is supported until 31 December 2027, 8.4 until 31 December 2028 and 8.5 until 31 December 2029.
If PHP came from your Linux distribution
Many servers run the PHP package their distribution ships rather than a build from php.net, and distributions support those packages on their own timetable. The php.net advisory says Linux distributions and long-term support vendors received the patches in advance, and that some of them provide backported fixes for 8.1 and older.
Ubuntu 22.04 LTS is the common case: it ships PHP 8.1 as the php8.1 package. Ubuntu's tracker for CVE-2026-109618 lists it as fixed in package version 8.1.2-1ubuntu2.28. The tracker also lists fixes for the PHP packages in some older Ubuntu releases, delivered through Ubuntu Pro.
A backport keeps the original version number. A patched Ubuntu 22.04 server still runs PHP 8.1.2, so the PHP version alone does not show whether the fix is in. The package version does. To check on the server:
# Debian and Ubuntu: the installed package version, then the changelog entry for the CVE
apt-cache policy php8.1-common
apt changelog php8.1-common | grep -n CVE-2026-109618
# Red Hat family: the same question of the RPM changelog
rpm -q --changelog php-common | grep -n CVE-2026-109618
Compare the installed package version with the one your distribution's security tracker names as fixed. If the tracker shows no fix for your release, or the server's PHP came from somewhere other than the distribution's own archive, ask that vendor directly. If no one supplies a fix, the remaining route is an upgrade.
Which version a site reports
Many PHP sites send their version in an X-Powered-By response header. Anyone can read it:
curl -sI https://www.example.co.uk/ | grep -i '^x-powered-by'
A reply such as X-Powered-By: PHP/8.1.2-1ubuntu2.28 says the site reports PHP 8.1. Distribution builds often add a package suffix after the PHP version, but treat the whole header as a hint about the PHP version, not as evidence that a backport is installed. Whether the fix is in is settled on the server: check the installed package version with the distribution's own tools, as above, and compare it with the distribution's security tracker.
Two cautions. The header is what the site reports, which is not always what it runs: a proxy or cache can rewrite or pass on stale headers. And no header at all means unknown, not safe. Setting expose_php = Off or stripping the header at the web server only hides the version. To know for certain, run php -v on the server, and check the PHP-FPM or Apache module version as well as the command line, since they can differ.
What an upgrade from 8.1 involves
Moving a bespoke PHP application or a Laravel codebase from 8.1 to 8.2 is usually small. Going to 8.4 takes a little more but buys two more years of security support than 8.2, which ends in December 2026. In practice the work is:
- Dynamic properties. Since 8.2, setting a property a class never declared raises a deprecation notice. Declare the property, or mark the class with
#[\AllowDynamicProperties]. Older bespoke code tends to have a lot of these. - Other 8.2 deprecations.
"${var}"string interpolation, and theutf8_encode()andutf8_decode()functions. - 8.4 deprecations. A typed parameter with a default of
nullmust now say it is nullable (?Foo $x = null), and theE_STRICTconstant is deprecated. - Extensions. PHP 8.4 moved IMAP, OCI8, PDO_OCI and PSpell out of PHP and into PECL. An application that reads mailboxes with
imap_*or talks to Oracle needs those installed separately, or replaced. Every other extension the app uses has to be installed for the new version too. - Dependencies. Each Composer package has its own PHP range. Laravel 10 supports PHP 8.1 to 8.3; Laravel 11 supports 8.2 to 8.4; Laravel 12 supports 8.2 to 8.5. A Laravel 10 app can move to 8.2 or 8.3 without a framework upgrade, but going to 8.4 means Laravel 11 or later, and Laravel 10's own security fixes ended in February 2025.
- The server. Ubuntu 22.04's own archive has only PHP 8.1, so a newer version means a newer release (Ubuntu 24.04 ships 8.3) or a third-party package source. The FPM pool,
php.inisettings and cron jobs all move across to the new version. - Testing. Deprecations are notices, not errors, so the app usually keeps running while the log fills. Run the tests, or the busiest paths by hand, with deprecation notices turned on, and fix what they show before switching production.
The PHP manual's migration guides list every change between versions: 8.1 to 8.2, 8.2 to 8.3 and 8.3 to 8.4.
Keeping PHP on a supported version, and making the changes an upgrade needs, is the kind of work a maintenance subscription exists for.