Find every PHP exposed to PHP2Shell on your machines, images, containers and fleet, in one command.
Important
Defensive tool. No exploit code, no attack traffic. It reads PHP version and ini settings from targets you point it at. URL checks send one ordinary HEAD request and read a response header.
npx php2shell-check # the PHP on this machine
npx php2shell-check --containers # every running container
npx php2shell-check --docker my-app:latest --html out.html # an image, plus a dashboardExits 0 when every target is patched and 1 when something needs action, so it drops straight into CI.
- Terminal UI: colour status pills, findings with the exact fix per target, interim-mitigation checklist, summary bar
- Scans everything PHP lives in
- local binaries, auto-discovered:
php,php8.x,php-fpm*,php-cgi*onPATHand sbin dirs - Docker images, before you ship them
- running containers, probing both the CLI and PHP-FPM inside each one (their ini can differ)
- URLs, via a passive
X-Powered-Byfingerprint - inventory files (CSV, TSV, JSON or plain lines) from your CMDB or asset export
- local binaries, auto-discovered:
- HTML dashboard: one self-contained file with summary cards, breakdown donut, filter and search, expandable per-target details, light and dark themes
- CI-ready: meaningful exit codes,
--json,--markdownfor PR comments and tickets, and a GitHub Action that writes a job summary - What-if mode:
--defineapplies ini overrides to a probe, so you can confirm mitigations take effect before rolling them out - Zero dependencies: Node 18.3+, nothing else
npx needs no install. To put it on your PATH instead:
npm install -g php2shell-checkPublished with npm provenance: the tarball carries a signed attestation that it was built from this repository by GitHub Actions, which you can verify with npm audit signatures.
Every recording below is the real CLI, captured by demo/make_gif.py.
Nothing to install and nothing to configure. Pass versions in directly for an offline check:
npx php2shell-check 8.3.30 8.5.12npx php2shell-check --docker php:8.4.26-cli --docker php:8.2-apacheEach container is probed twice, through the CLI and through PHP-FPM, because the two often load different ini files.
npx php2shell-check --container web --container worker
npx php2shell-check --containers # every running container--define applies ini overrides to the probe, so you can confirm a setting really moves the verdict before you push it to a fleet.
npx php2shell-check --docker my-app:latest \
--define memory_limit=-1 --define session.upload_progress.enabled=0npx php2shell-check 8.3.30 8.5.12 --html report.html --opennpx php2shell-check # discover and probe local PHP binaries
npx php2shell-check --url https://example.com
npx php2shell-check --inventory hosts.csv
npx php2shell-check --inventory hosts.csv --json # machine-readable
npx php2shell-check --docker my-app:latest --markdown php2shell.md
npx php2shell-check info # advisory, fixed versions, mitigationsCombine any of these in a single run.
--html report.html writes a single self-contained file: no CDN, safe to attach to a ticket or email.
name,version
web-01,8.3.30
web-02,8.4.27
legacy-billing,7.4.33Also accepted: TSV, one version per line, or JSON [{"name": "api", "version": "8.5.11", "ini": {"memory_limit": "-1"}}].
| Code | Meaning |
|---|---|
0 |
every target is patched |
1 |
at least one target needs action (vulnerable, backport needed, EOL, or unknown) |
2 |
only errors, or nothing was scanned |
Fail the build when an image you are about to ship is exposed. The Markdown report lands in the job summary.
- uses: adityaaravind/php2shell-check@v1
with:
args: --docker my-app:${{ github.sha }}
html: php2shell-report.html # optionalMost PHP2Shell tooling answers "is this one URL vulnerable?", usually by sending probe traffic. This answers "which of my hosts, images and containers are exposed, and what do I change on each?" — without sending attack traffic.
| php2shell-check | Active remote scanners | Version checkers | |
|---|---|---|---|
| Local binaries | auto-discovered | — | one at a time |
| Docker images, before you ship | yes | — | — |
| Running containers | yes, CLI and FPM ini separately | — | — |
| Inventory / CMDB files | CSV, TSV, JSON | host lists | — |
| URLs | passive X-Powered-By hint |
active probes | yes |
| ini-aware verdicts | yes, incl. --define what-if |
— | — |
| Traffic sent per URL | one HEAD |
multi-MiB crafted probes | one request |
| Output | TUI, HTML dashboard, JSON, Markdown | text, JSON | text, JSON |
Reach for an active remote scanner when you need to prove reachability from outside and have authorization to probe. Reach for this when you own the estate and need coverage, mitigation verification and a report you can attach to a ticket.
Two memory-safety bugs in PHP core. Details leaked on Oct 20, 2026 and fixes shipped Oct 21. Both are CVSS v4.0 9.2 and exploitable by an unauthenticated remote attacker. The affected code path dates back to PHP 5.4.
| CVE | Root cause |
|---|---|
| CVE-2026-109618 | Out-of-memory hit while request data is only partly initialized; cleanup then trusts that data as valid. |
| CVE-2026-109619 | Use-after-free: state left over from one request points at freed memory that a later request on the same worker uses. Memory disclosure is also a confirmed impact. |
Every SAPI that serves web requests is in scope: Apache mod_php (highest risk), PHP-FPM, php-cgi, FrankenPHP, LiteSpeed.
| Branch | Fixed in | Verdict |
|---|---|---|
| 8.5 | 8.5.12 | PATCHED / VULNERABLE |
| 8.4 | 8.4.27 | PATCHED / VULNERABLE |
| 8.3 | 8.3.36 | PATCHED / VULNERABLE |
| 8.2 | 8.2.35 | PATCHED / VULNERABLE |
| 7.4 – 8.1 | source backports only, no official release | BACKPORT |
| < 7.4 | end-of-life, no fix | EOL |
Patching is the only complete fix. These reduce exposure while you roll out upgrades:
| CVE | Setting |
|---|---|
| CVE-2026-109618 | memory_limit=-1, set so applications cannot override it |
| CVE-2026-109619 | session.upload_progress.enabled=0 |
| CVE-2026-109619 (8.5 only) | fatal_error_backtraces=0 |
Restart all PHP workers afterwards. Container memory limits and WAF rules are stopgaps, not mitigations.
- Distro packages backport fixes without bumping the version. Ubuntu, Debian, RHEL and others may ship a fixed build that still reports an older version. Confirm against your vendor's advisory.
- URL checks are a hint, not a verdict.
X-Powered-Byis often hidden (good) and can be stale or spoofed. Run the tool on the host for a real answer. - The ini a probe sees is the ini that binary loads.
phpandphp-fpmcan read different files, which is why containers are probed with both. For Apachemod_php, confirm with aphpinfo()served by Apache. - Don't run random "PoC" repos. Unverified exploit code for these CVEs is circulating, and some of it may carry malware.
npm test # node:test, no dependencies
docker run -d --name p2s-demo-fpm php:8.3.30-fpm # demo target
python3 demo/make_gif.py # regenerate demo/*.gif (Pillow)
python3 docs/make_social_card.py # regenerate docs/social-card.png- Upstream advisories, authoritative: GHSA-w8hw-w9fx-j79w (CVE-2026-109618) · GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- Tenable: PHP2Shell FAQ
- Qualys: PHP announces critical security release
- Rapid7 ETR
- Huntress rapid response
- php.net, always the authoritative source for versions
MIT © Aditya Aravind. Provided as-is for defensive use; verify findings against official advisories.







