PHP2Shell is a pair of critical flaws in PHP itself, tracked as CVE-2026-109618 and CVE-2026-109619. An attacker who can send a web request can run their own code on the server — no login, no bug in your application needed. The fix is simple: upgrade PHP. The hard part is knowing where all your PHP is. So we built a free tool that finds it, and we've made it open source.
Why this one is different
Most security flaws live in an application: a plugin, a framework, a form that forgot to check its input. PHP2Shell lives one layer below. It is triggered while PHP reads the body of a file-upload style request (multipart/form-data), before a single line of your code runs. Your framework, your input validation and your login page never get a say.
It affects every common way of running PHP — PHP-FPM, Apache's mod_php, php-cgi, FrankenPHP and LiteSpeed — and reaches back to at least PHP 5. It is rated CVSS 9.2, which puts it in the "patch this week, not this quarter" bracket.
| PHP branch | Fixed in | 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 |
| 8.1 and older | No fix | End of life — upgrade the branch |
Anything below these versions, without a vendor patch, is exposed.
Why "just check the version" isn't enough
On a laptop, php -v answers the question. On real servers it rarely does:
- There is rarely one PHP. A cPanel or Plesk server can have six side by side. Add Remi or SCL packages, a Docker image or two and a forgotten
/opt/php74, and nobody has the full list. - Linux vendors patch without changing the number. Ubuntu, Debian and Red Hat fix the flaw in their own builds and keep the old version —
8.3.6-0ubuntu0.24.04.13is patched, even though 8.3.6 is "below" 8.3.36. A tool that only compares numbers raises a false alarm, and teams learn to ignore alarms. - Patched on disk isn't patched in memory. After an upgrade, PHP-FPM workers keep running the old program until they are restarted. It is the most common mistake after patching, and nothing on disk shows it.
- Temporary settings are per pool. The interim setting that reduces the risk,
session.upload_progress.enabled=0, only helps if it is switched on in every PHP-FPM pool. One pool without it is enough.
What php2shell-check does
php2shell-check is a single program with nothing to install alongside it, for Linux, macOS, Windows and FreeBSD. You run it once and it:
- Finds every PHP on the machine — on the path, in distro packages, Docker official images, Remi, SCL, cPanel, Plesk, CloudLinux, LiteSpeed, Homebrew, MAMP, Herd, XAMPP, Laragon, Scoop and more.
- Reads the vendor's own changelog for each package, so a back-ported fix shows as patched instead of a false alarm.
- Looks at running processes on Linux and names any PHP worker still running a replaced or deleted program.
- Checks every PHP-FPM pool for the interim setting, including per-pool overrides.
- Says what to do for each finding — upgrade to which version, restart what — and exits with a code a CI pipeline can act on.
Each install gets one clear verdict:
| Verdict | What it means |
|---|---|
| PATCHED | At or above the fixed release |
| PATCHED_BACKPORT | Older number, but the vendor's changelog lists both CVEs as fixed |
| VULNERABLE | Below the fixed release, with no sign of a vendor fix |
| VULNERABLE_EOL | A branch older than 8.2 — no fix will ever ship for it |
| UNVERIFIED | A vendor build whose changelog couldn't be read, so it can't be called safe |
Try it
On a Linux server:
curl -fsSLO https://github.com/AdZoic/php2shell-check/releases/latest/download/php2shell-check_linux_amd64
chmod +x php2shell-check_linux_amd64
sudo ./php2shell-check_linux_amd64 # root sees every worker and pool
For container images, from any machine with Docker or Podman:
php2shell-check image php:8.3-fpm my-registry/app:prod
It exits with 0 when everything is safe, 1 when something is vulnerable, 2 when something needs a person to look, and 3 when a scan couldn't run — so it can stop a deployment on its own. For GitHub, it is also a one-line Action:
- uses: AdZoic/php2shell-check@v1
with:
images: my-registry/app:latest
Builds for every platform, with checksums, are on the releases page.
php2shell-check is a defensive tool. It only asks each PHP for its version and settings, and asks the package manager what it installed. It never runs PHP code, never sends a request to your websites and contains no attack code. Image scans run in a throwaway container with no network, no special permissions and a read-only filesystem, and the container is always removed afterwards. Anything it can't prove is patched is reported as needing attention — never as safe.
What to do today
- Run it on every server, and in CI against every image you ship.
- Upgrade anything marked
VULNERABLEto 8.5.12, 8.4.27, 8.3.36 or 8.2.35 or later — or install your Linux vendor's patched package. - Restart PHP-FPM and the web server, then run it again to confirm no old workers are left.
- Plan the move off anything marked
VULNERABLE_EOL. Interim settings reduce the risk; only upgrading removes it.
Why we built it
We run PHP ourselves, and the first question after the advisory was the obvious one: where, exactly? Answering it by hand across servers, panels and images was slow and easy to get wrong — and the tools we tried either cried wolf on patched Ubuntu builds or said nothing about workers still running old code. A scanner that is honest about what it can and can't prove seemed worth sharing. It is free and MIT-licensed, and pull requests are welcome, especially for PHP install locations it doesn't know yet.
Affected versions, fixed releases and the interim setting follow the PHP project's advisory for CVE-2026-109618 and CVE-2026-109619. How the tool behaves is described from its own source code and test suite, both public on GitHub. This post is general guidance, not advice for your specific setup — check your vendor's advisory for the exact package that fixes your system.
This post also appears on our developer blog, adzoic.github.io, where we write about the open-source tools we publish.