PHP2Shell is the nickname for two critical flaws in the PHP engine, CVE-2026-109618 and CVE-2026-109619. To fix PHP2Shell, update every PHP runtime that serves web requests to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your vendor’s patched package), then restart or replace every PHP worker. An updated package on disk is not proof: the fix only counts once the running process has loaded the patched build.
PHP2Shell CVE Vulnerabilities at a glance
| Item | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| PHP advisory title | RCE via OOM corruption | RCE via stale global state |
| GitHub advisory | GHSA-w8hw-w9fx-j79w | GHSA-6wmf-4rv5-p3rp |
| Severity (PHP, CVSS v4.0) | 9.2 Critical | 9.2 Critical |
| Fixed upstream releases | 8.5.12, 8.4.27, 8.3.36, 8.2.35 (October 21, 2026) | Same releases |
| PHP 8.1 and older | No official release; source patches for 7.4, 8.0, 8.1 to help vendors backport | Same |
| CISA KEV | Added October 26, 2026; federal civilian deadline October 29, 2026 | Same |
| Complete fix | Update. PHP’s security team calls updating the only complete mitigation. | Update |
What is the PHP2Shell vulnerability?
PHP2Shell is a researcher-coined name for a pair of remote code execution (RCE) flaws in the PHP runtime itself, not in WordPress, Drupal, Composer packages or any other application code. PHP’s own advisories do not use the name; they title the issues by mechanism.
- CVE-2026-109618, “RCE via OOM corruption”: when PHP runs out of memory (OOM) at the wrong moment, request data can be left half-initialized, and request cleanup may treat that invalid data as valid.
- CVE-2026-109619, “RCE via stale global state”: internal state owned by one request can outlive its memory, and a later request on the same worker may use it before it is reset.
Both were fixed in the same October 21, 2026 releases. Recorded Future attributes the name to Wiz Research, which found the issues alongside Calif and OpenAI.
What PHP2Shell is not. It is not a webshell, and it is not CVE-2026-115560. That third CVE, announced by PHP on October 23, is a separate, configuration-dependent session-handling issue (covered in the FAQ).
How PHP2Shell works
Both flaws live in how PHP aborts and cleans up a web request, so they can be reached before any application code runs.
PHP uses longjmp() to abandon a request when it hits an out-of-memory error. Per the PHP security team, an allocation failure can interrupt initialization while incomplete request state is already reachable, and request shutdown may then touch that invalid state (oss-security). The second flaw is the same family of problem across requests: state left pointing at freed memory survives into the next request handled by that worker.
This guide stops at the mechanism. You do not need exploit detail to patch, mitigate or verify.

PHP2Shell request lifecycle · two flaws, one worker
In both flaws, a request that was cut short leaves memory that PHP later trusts: during cleanup of the same request (CVE-2026-109618) or in the next request on that worker (CVE-2026-109619).
Which setups are at risk. PHP says all installations serving web requests are affected, naming PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, and rates the risk highest for mod_php (LWN quoting php.net).
| Execution model | What PHP’s advisories say | Practical reading |
| Apache mod_php | Unauthenticated RCE demonstrated over HTTP, before application code runs | Patch first |
| PHP-FPM | 109618: susceptible by source analysis, no complete exploit shown. 109619: session path RCE validated | Do not defer |
| php-cgi, FrankenPHP, LiteSpeed | Named as affected | Patch on the same schedule |
| CLI only (cron, workers that never serve HTTP) | Not a web request path | Still update, but lower urgency |
Which PHP versions are affected?
Every upstream PHP release before the fixed version in its branch is affected, and older end-of-life branches are affected too. The trap is that a correctly patched distribution package often reports an older-looking version number.
| Source of PHP | Fixed build | Where to confirm |
| Upstream 8.5 | 8.5.12 or later | PHP 8.4.27 release notes (same advisory) |
| Upstream 8.4 | 8.4.27 or later | php.net advisory, October 21, 2026 |
| Upstream 8.3 | 8.3.36 or later | php.net advisory |
| Upstream 8.2 | 8.2.35 or later (branch support ends December 31, 2026) | php.net advisory |
| Upstream 8.1, 8.0, 7.4 | No official release; PHP published source patches to help backporters | LWN |
| Ubuntu 24.04 LTS | php8.3 8.3.6-0ubuntu0.24.04.13 | USN-8948-1 (computingforgeeks walkthrough) |
| Ubuntu 22.04 LTS | php8.1 8.1.2-1ubuntu2.28 | USN-8948-1 |
| Ubuntu 20.04 | php7.4 7.4.3-4ubuntu2.29+esm5 (Ubuntu Pro only) | USN-8948-2 |
| RHEL, AlmaLinux, Debian, cPanel, CloudLinux, Plesk | Vendor builds that keep the upstream version string | Each vendor’s advisory or package changelog |
| Official Docker php images | Rebuilt October 21 for 8.5.12, 8.4.27, 8.3.36, 8.2.35; no fixed official tag for 8.1 or older | Docker Hub tag and digest |
| Appliances and vendor products (for example Palo Alto Networks PAN-OS and Panorama) | Vendor hotfix, not a PHP update you can apply | The vendor’s own advisory |
Why a fixed package can look vulnerable
Distributions backport the security patch into the PHP version they already ship and keep that version number. A fully patched Ubuntu 24.04 server still reports PHP 8.3.6, which is numerically far below 8.3.36. Judge a distribution build by its package release and changelog, never by comparing php -v against the upstream table. The reverse also holds: a scanner that only reads version strings will flag patched distro servers and can miss an unpatched appliance.
How to fix PHP2Shell
The fix is the patched PHP build, loaded by every process that serves web traffic. Work through these steps in order and keep evidence as you go.
- Inventory every PHP runtime. Hosts, container images, serverless layers, control panels, CI images that ship to production, and appliances or vendor products that embed PHP. Sophos’ Don Smith framed the real challenge as finding every instance where PHP is running, not installing the patch (Cyber Magazine).
- Rank by exposure. Internet-facing first, mod_php before PHP-FPM, management interfaces of appliances before internal tools.
- Identify the serving runtime and execution model. Record which SAPI serves HTTP (mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed) and which package or image provides it. The php CLI on the same host may be a different build.
- Choose the right fix for that source. Upstream builds: the fixed release in the same branch. Distribution packages: the vendor’s security update (Ubuntu recommends a full system update rather than cherry-picking packages). EOL branches: a vendor backport, or a move to 8.2 or later.
- Update packages or rebuild images. For containers, rebuild from the fixed base with a forced pull (docker build –pull), because Docker may otherwise reuse a cached base image.
- Restart or replace every worker. Reload PHP-FPM pools and restart Apache for mod_php. Redeploy containers so pods run the new image digest.
- Handle appliances through their vendor. You cannot patch PHP inside PAN-OS or a NAS yourself; apply the vendor hotfix and restrict management access until it lands.
- Record the evidence (see the verification section) before closing the ticket.

PHP2Shell remediation decision tree · five PHP sources
The right fix depends on where the PHP came from, but every path ends the same way: restart the workers and verify the running build.
PHP2Shell mitigation if you cannot patch immediately
Temporary mitigations reduce risk on known paths; none of them fixes PHP2Shell. PHP’s security team states that updating is the only complete mitigation (oss-security). Use these only to bridge a short gap, and patch anyway.
| Mitigation | Path it targets | Where it must be set | Limitations | How to verify | Source |
| session.upload_progress.enabled=0, then restart every worker | CVE-2026-109619 confirmed session paths; also CVE-2026-115560 | php.ini, FPM pool or server config applied before request parsing. Not ini_set() or FPM .user.ini | Blocks confirmed session paths, not other variants | Read the effective value from the serving SAPI after restart | PHP advisory text for GHSA-6wmf-4rv5-p3rp |
| fatal_error_backtraces=0 (PHP 8.5 only), then restart | CVE-2026-109619 fatal backtrace path | Same administrative config layers | Covers that one path only | Effective value per SAPI | GHSA-6wmf-4rv5-p3rp |
| memory_limit=-1, set so apps cannot override it (for example php_admin_value) | CVE-2026-109618 controllable memory-limit failure | FPM pool or Apache config; confirm no pool, directory or app restores a limit | A real allocation failure can still reach the bug; unbounded memory is an availability risk | Effective value per pool and vhost | GHSA-w8hw-w9fx-j79w |
| Low post_max_size (8M without uploads, 32M with), upload_max_filesize below it | CVE-2026-109618 multipart routes to OOM | Administrative config | Hardening only | Effective values per SAPI | GHSA-w8hw-w9fx-j79w |
| Container or cgroup memory limits | Availability boundary | Orchestrator or cgroup | Not a mitigation; do not use RLIMIT_AS or RLIMIT_DATA, which can trigger the same path | Pod spec or cgroup settings | GHSA-w8hw-w9fx-j79w |
| WAF rules (for example Cloudflare, AWS WAF) | Known exploit request patterns | Edge or load balancer | Stopgap; vendors report evasive variants | Rule in blocking mode, logs show matches | The Hacker News |
| Remove from the internet or isolate | All paths | Network | Service impact | External reachability test | CERT-EU advice, via The Hacker News |
Keep session.upload_progress.enabled=0 in place after patching unless an application needs the feature: PHP’s October 23 notice says it also protects against CVE-2026-115560 until the next regular release (oss-security).
How to verify the PHP2Shell fix in production
A PHP2Shell fix is verified when, for every asset, you can show that the process serving HTTP was started from a patched build after the patch landed. A version command alone does not show that.
The commands below are illustrative for Debian and Ubuntu with systemd. Package names, service names and paths differ on other platforms; follow your vendor’s documentation.
| # | Check | Why it matters | Evidence to keep | A failed check means |
| 1 | Every PHP runtime is in the inventory, including images and appliances | Unlisted runtimes are where unpatched PHP survives | Inventory export with owner per asset | Scope is incomplete; the ticket cannot close |
| 2 | The version checked is the serving runtime, not the CLI | The php CLI can differ from the binary FPM or Apache loads | SAPI name plus build for each serving process (for example php-fpm8.3 -v, apache2ctl -M showing a php module) | You verified the wrong binary |
| 3 | Distro builds are judged by package release and changelog | Backports keep old upstream version numbers | Package version (dpkg -l ‘php*’) and a changelog line naming both CVEs | Re-check against the vendor advisory before calling it vulnerable or fixed |
| 4 | Serving processes started after the update | Running workers keep the old code in memory | Service start time later than the package install time (systemctl show php8.3-fpm -p ActiveEnterTimestamp) | Restart or reload, then re-check |
| 5 | Containers run the rebuilt image digest | A pulled image changes nothing until containers are recreated | Image digest in the registry matches the digest of running containers | Redeploy |
| 6 | Appliances and vendor products are on the vendor’s fixed release | You cannot verify embedded PHP with host tools | Firmware or hotfix version against the vendor advisory | Apply the hotfix; restrict management access meanwhile |
| 7 | Interim settings are still effective where you rely on them | Settings in the wrong layer are silently ignored | Effective values read from the serving SAPI | Move the setting to php.ini, the pool or server config |
| 8 | Evidence is recorded per asset | KEV reporting and audit need proof, not intent | Ticket with the items above, timestamped | Not closed |
PHP2Shell verification evidence chain · six checks
Work through the chain per asset; a gap at any link means the asset is not yet verified.
Two cautions. Vulnerability databases and scanners can lag new advisories, so a clean scan is not proof of a fix (ITNEXT). And do not run public exploit code against production to test a fix; the checks above prove the fix without attacking your own systems.
How to investigate possible PHP2Shell exploitation
Start your investigation window on October 17, 2026, not on the October 21 patch date. Amazon Threat Intelligence recorded a PHP2Shell exploitation attempt in its MadPot honeypots that day and advised defenders to look back at least that far (Security Affairs).
What is confirmed so far (as of October 29, 2026)
| Date | Finding | Source |
| October 27 | Wiz saw no successful end-to-end exploitation in its own telemetry and no public proof of concept that works against arbitrary targets | Wiz Research |
| October 26 | CISA added both CVEs to the Known Exploited Vulnerabilities catalog | BleepingComputer |
| October 24 | Successful RCE confirmed against honeypot systems by Adel Karimi (Perplexity) | The Hacker News |
| After October 23 | Unit 42 retracted its October 23 update linking a compromise to PHP2Shell (retraction date not stated) | Unit 42 |
| October 21 | Multiple proof-of-concept attempts from anonymized infrastructure, suggesting several actors | Amazon Threat Intelligence, via The Hacker News |
| October 17 | First recorded attempt, four days before disclosure | Amazon Threat Intelligence |
Reading these together: exploitation attempts are widespread and successful RCE has been shown in controlled conditions, but reliable exploitation at scale against real systems has not been publicly established. Attribution claims to specific threat actors come from single vendors and are not repeated here.
Triage levels
| Level | What you see | What to do |
| Internet scanning | Requests probing for PHP endpoints or versions | Note it; confirm the host is patched |
| Exploitation attempt | Requests matching published detection logic, such as CISA’s SIGMA rule or WAF matches | Confirm the host was patched at that time; review worker crashes and errors around the timestamps |
| Successful exploitation | Evidence that attacker code ran: unexpected child processes of the web worker, new files in web roots, outbound connections from PHP workers | Isolate the host and start incident response |
| Confirmed compromise | Persistence, data access or lateral movement | Full incident response; rebuild rather than clean |
One caution from the research: application logs may show little, because exploitation happens below the application layer (Recorded Future). Look at web server logs, process telemetry and network flows too. Wiz also reported that the bugs can expose worker memory, including credentials and API keys, without full code execution; if an exposed host was unpatched in the window, rotating secrets that lived in PHP memory is a sensible precaution.
PHP2Shell remediation checklist
- ☐ Inventory complete: hosts, images, appliances, vendor products, with an owner each
- ☐ Serving SAPI and PHP source recorded per asset
- ☐ Correct fix chosen: upstream release, distro security update, vendor backport or vendor hotfix
- ☐ Packages updated or images rebuilt with a forced base pull
- ☐ Workers restarted; containers redeployed on the new digest
- ☐ Appliance hotfixes applied; management access restricted until then
- ☐ Runtime verified per asset (serving build, start time, digest, changelog)
- ☐ session.upload_progress.enabled=0 kept unless the feature is needed
- ☐ Logs and telemetry reviewed from October 17, 2026
- ☐ Secrets rotated on hosts that were exposed and unpatched
- ☐ Evidence attached; ticket closed
Frequently asked questions
What is PHP2Shell? PHP2Shell is the nickname for CVE-2026-109618 and CVE-2026-109619, two critical remote code execution flaws in the PHP engine fixed on October 21, 2026.
Which PHP versions contain the fix? PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, or later releases in the same branch. Distribution packages carry the fix under their own version numbers.
Are end-of-life PHP versions affected? Yes. The PHP project ships no release for 8.1 or older; it published source patches for 7.4, 8.0 and 8.1 to help vendors backport. Use a vendor backport or move to a supported branch.
Do distribution backports count as fixes? Yes, when the vendor’s advisory or package changelog lists both CVEs. A patched Ubuntu 24.04 server still reports PHP 8.3.6.
How can I check that production is patched? Check the build loaded by the process serving HTTP, confirm it started after the update, and for containers confirm the running image digest is the rebuilt one. php -v on the host is not enough.
Does disabling session.upload_progress fix PHP2Shell? No. It blocks the confirmed session paths of CVE-2026-109619 only; CVE-2026-109618 is untouched. Only updating is a complete fix.
Does a WAF replace patching? No. WAF vendors describe their rules as a stopgap, and evasive request variants have been reported.
Is PHP2Shell exploited in the wild? CISA lists both CVEs as known exploited (added October 26, 2026), and successful RCE was confirmed on honeypots. Reliable exploitation at scale has not been publicly shown.
Is CVE-2026-115560 part of PHP2Shell? No. It is a separate, unlikely session-handling issue that needs an application to switch session.serialize_handler to php at runtime. PHP will fix it in the next regular release; session.upload_progress.enabled=0 mitigates it meanwhile.
Does updating WordPress, Drupal or Joomla fix it? No. The flaw is in PHP itself, so the PHP runtime must be updated by you or your host.
Conclusion
Patch every PHP runtime that serves web traffic, then prove it: the serving process, its start time, its image digest and its vendor changelog. Teams that already keep a software inventory, such as an SBOM for each container image, can answer “where is PHP running?” in minutes rather than days. Start with that inventory, then work the checklist above.