On 21 October 2026 the PHP project shipped fixes for two critical flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619, now known together as PHP2Shell. An unauthenticated request can run code on the web server or read worker memory that holds passwords, tokens and API keys. Details leaked a day early, and Amazon's honeypots logged an exploitation attempt on 17 October, four days before the patch existed.
This post is for the person who has to answer for it inside a Dutch or Flemish organisation of 250 to 5,000 people: the IT manager, informatiemanager or security officer. Crux Digits does not host, patch or run servers; your ICT partner or internal IT team does that. What we add is the part of PHP2Shell that a patch cannot reach: applications whose code is too old to run on a PHP version that still gets fixes.
What PHP2Shell is
Both flaws sit in the PHP engine, below the application, so it does not matter whether the site runs WordPress, Drupal, Magento, Laravel or something written in house. The first corrupts request data when PHP runs out of memory halfway through setting a request up; the second leaves request state behind after its memory is freed, so the next request on the same worker uses it. Both are rated 9.2 on CVSS v4.0. The PHP security release names every installation that serves web requests as at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The risk is highest on mod_php, where PHP has a working exploit that fires before any application code runs.
The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older get no release. The project published minimal source backports for 7.4, 8.0 and 8.1 and says to ask your distribution or vendor, or to upgrade to a supported version. The finder, Wiz, writes that one researcher working with AI models found and weaponised the bugs in about a week. That is their account, but it fits the direction of travel: flaws in old, widely deployed code are getting faster to find, for attackers as well as for defenders.
"Patch PHP" is three jobs with three owners
The advisories all end with the same instruction: update. Inside an estate of a few hundred applications, that instruction splits into three jobs that belong to three different parties, and only the first is quick.
The first job is the runtime on PHP 8.2 or newer that your ICT partner or cloud platform runs. That is a package update, and then a step that is easy to forget: NCSC-NL points out that workers which were already running keep executing the vulnerable code until they are restarted. Containers are the same story one layer up. Google's guidance is blunt that self-built images are the customer's responsibility: they have to be rebuilt on a patched base image and redeployed, not just scanned.
The second job is PHP that arrived inside something you bought: an appliance, a hosting control panel such as cPanel or Plesk, a Windows product that ships its own php-cgi.exe. Huntress lists exactly these as the installs people miss. Here the vendor patches and you track the vendor. NCSC-NL keeps an inventory of software products with a PHP dependency in the same repository, and it is worth checking your contract list against it this week.
The third job is your own PHP applications on 8.1 or older: the supplier portal built in 2017, the intranet module nobody has touched since the developer left, the Laravel or Symfony application pinned to PHP 7.4 because the framework version it uses never supported PHP 8. No upstream fix exists for these. Your ICT partner cannot simply upgrade the runtime, because the application stops working on PHP 8.2, and they do not own or change your code. This is where PHP2Shell turns from a patch into a project, and where it usually sits without an owner.
Why the version number in your inventory can mislead

Most inventories record the upstream version string, and for this advisory that string can be wrong in both directions. Distributions backport security fixes into the version they shipped, so a patched package can still report an older upstream number. Qualys says this explicitly for PHP2Shell: follow the vendor advisory, because a backported fix may keep the old version. A scanner that reads only the string will flag a patched distribution build as vulnerable and, worse, let an unpatched hand-compiled 8.3 pass if nobody checks the patch level.
Ask for four fields per PHP install instead of one: the upstream version, the package release or build source, the SAPI (FPM, mod_php, CGI, FrankenPHP or LiteSpeed), and whether it is reachable from the internet. With those four you can sort the estate into the three jobs above in an afternoon, and you can see which mod_php hosts facing the internet to treat first.
What breaks when old PHP code moves to 8.2
An upgrade from 7.4 or 8.1 is rarely a rewrite, but it is never a version bump either. PHP 8.0 removed functions that older code leans on, such as each() and create_function(), and changed how strings compare with numbers, so a comparison like 0 == "abc" now returns false where it used to return true. PHP 8.1 deprecated passing null to built-in functions that expect a string, which produces a flood of warnings in code that was written loosely. PHP 8.2 deprecated dynamic properties, which many older codebases create everywhere. On top of the language sits the framework: a framework release from before PHP 8 typically declares in its composer.json that it does not support PHP 8, so the framework has to move too, and its own breaking changes come along.
Most of this is mechanical, and good tooling exists for it. Rector applies refactoring rules per PHP version, PHPCompatibility flags code that will not run on a target version, and static analysis with PHPStan finds the type errors the new versions expose. What decides the time and the risk is whether there are tests. An application with a test suite can be upgraded step by step with each change proven; one without has to get characterisation tests first, written against its current behaviour, so that the upgrade can show it changed nothing.
A plan for this week, by owner
Today, ask your ICT partner for the four-field list above, and ask them to confirm that every worker was restarted after the update and that every container image was rebuilt. Ask each vendor on the NCSC-NL list you run for its advisory and date. These are questions, not tasks for you, and they make the first two jobs visible.
For every internet-facing install on PHP 8.1 or older, apply PHP's interim measures now: set session.upload_progress.enabled to 0 in php.ini or the FPM pool and restart every worker, keep post_max_size low, and enforce request-size limits at the web server or proxy. PHP is explicit that these measures do not make an installation safe; they buy time. Where you can, put the application behind a VPN or restrict it to known addresses until the code has moved.
Check the logs back to at least mid-October, because the first recorded attempt predates the leak. Huntress advises looking for PHP worker processes (php-fpm, httpd, apache2, php-cgi) that start shells or download tools, and for reconnaissance commands such as whoami or uname run from a web server. Wiz adds repeated HTTP 500 responses after multipart requests, memory-limit errors and unusually large PHPSESSID cookies. If you are in scope of the Cyberbeveiligingswet, a confirmed compromise may be a significant incident with an early warning due within 24 hours; our post on the supply-chain duty covers who in the chain carries that duty.
Within a month, decide for each application on PHP 8.1 or older: upgrade it, replace it, or retire it. Write the decision down with a date and an owner. An application that cannot move to a supported runtime within one sprint is a standing exposure, and the question of who holds a component's version number is the same one we raised for AI gateways two days ago.
Where Crux Digits fits
We take the third job and leave the first two where they belong. Your ICT partner keeps running the servers, applying the packages and restarting the workers. We work on the application: a code audit that shows what breaks on PHP 8.2 or 8.4, how much of it the tooling can fix, what test coverage exists and what the framework upgrade involves, followed by a fixed-scope upgrade. AI models do the bulk of the mechanical refactoring and draft the missing characterisation tests; an engineer reviews every change before it merges, and nothing ships that the tests have not proven.
What your ICT partner receives at the end is a deployable application on a supported PHP version, the test suite that proves its behaviour, and a short runbook for the next upgrade. The code stays yours. If an application turns out to cost less to replace than to upgrade, the audit says so; that is a decision for you, not a sale for us.
If you want the third job looked at, our custom software development page explains how we work with fixed steps.
Last updated: 22 October 2026.
Software built around your process and data, with AI where it changes the outcome. Something working every week, and the code is yours.
Custom software development in the Netherlands →


