What PHP2Shell changes, and what it does not
Two critical remote code execution flaws were disclosed on 21 October 2026. A third issue involving session upload progress was described on 23 October. This page explains the difference between fixing them and proving that nothing happened.
Short answer
CVE-2026-109618 and CVE-2026-109619 are unauthenticated remote code execution flaws in PHP's request handling. PHP fixed them upstream in 8.2.35, 8.3.36, 8.4.27 and 8.5.12. Distributions may ship the fix as a backport with a different version string.
The only complete mitigation is to update and then restart every web worker. Interim settings reduce specific paths but do not remove the vulnerability. A WAF is an additional layer, not a substitute.
What the two critical flaws actually do
Both are rated CVSS v4.0 9.2. They share a theme: PHP's cleanup path can act on request state that is no longer valid. The route to that state differs.
| CVE | Mechanism | Confirmed impact and exposure |
|---|---|---|
| CVE-2026-109618 RCE via OOM corruption | Out-of-memory handling can abort a request while request memory is only partly initialised. Request cleanup may then treat invalid state as valid. | Unauthenticated remote code execution as the web worker account. Validated over HTTP against Apache mod_php with default limits. Highest for mod_php. FPM exits the child when request startup fails, but source analysis indicates exposure after normal startup. FrankenPHP is described as likely susceptible. |
| CVE-2026-109619 RCE via stale global state | A worker can retain global state that points to memory owned by a completed request. A later request can reach the stale pointer before normal initialisation resets it. | Heap use-after-free, memory disclosure and remote code execution with the worker's privileges. Session-lifecycle RCE was validated against mod_php and FPM. Confirmed for mod_php. FPM is conditionally exposed when the frontend supplies per-request INI values that produce a diagnostic before initialisation. LSAPI is described as a conditional candidate. |
| CVE-2026-115560 Session upload progress issue | An application sets session.serialize_handler to php_binary or php_serialize in configuration, then switches it to php at runtime with ini_set() before session_start(). Session upload progress must still be enabled. | PHP describes an unlikely additional RCE vector and recommends disabling session upload progress until the next regular bugfix release. Applications that never change the serialisation handler at runtime can keep the feature enabled, according to PHP. Affects patched releases including 8.5.12. |
The third row in PHP's material is different in kind. CVE-2026-115560 is an informational advisory about session upload progress, published on 23 October with a full advisory promised for the next regular release. It does not change the fixed versions for the two critical CVEs, but it does change the answer to “is this configuration fully patched?”
Why the SAPI matters more than the framework
The advisories distinguish Apache mod_php from PHP-FPM. The demonstrated
mod_php exploit can trigger before application code runs. FPM exits a child when
request startup fails, which blocks one route, but source analysis still indicates exposure
after a normal startup. FrankenPHP is described as likely susceptible because it also runs
request shutdown unconditionally. LSAPI is a conditional candidate.
None of this tells you whether a particular site was attacked. It tells you how much distance exists between an HTTP request and the vulnerable code path. That distance is one reason two sites on the same patch level can carry different practical risk.
What remote code execution means for data
If an attacker reaches code execution, the immediate boundary is the web worker's privileges. Configuration, environment variables and credentials reachable by that account can be exposed. Whether customer data, a database or another service is reachable depends on the worker's identity, network isolation, secrets handling and what the application connects to.
A worker that does not run as root is not automatically safe. Nor is a service “safe” because credentials live in a different language or a managed secret store: if the worker can read them at runtime, the attacker who controls the worker may be able to read them too. The useful question is what this process can reach, not what language the secret is written in.
A vulnerability is not a confirmed breach
This site cannot tell you whether your systems were exploited. The presence of a vulnerable runtime means exposure, not evidence of data loss. Treat intrusion review as a separate question with its own evidence.
What “patched” means in practice
Upstream, the fixed versions are 8.2.35, 8.3.36, 8.4.27, 8.5.12. On a distribution, the package version will look different because the distribution adds its own revision. Ubuntu publishes fixed package versions per release; Debian publishes a DSA for trixie and a DLA for bookworm. Red Hat rated the issue Important but did not show a product impact table or fixed errata when checked, which means the exact RHEL release needs to be checked rather than assumed.
PHP 8.1 and older no longer receive upstream updates. PHP says some distributions and LTS vendors provide backports, and minimal source backports exist for 7.4, 8.0 and 8.1. “The branch is old” is not the same finding as “the package is unpatched”; check the vendor.
PHP 8.2 remains in security-fix-only support until 31 December 2026. A fixed 8.2 package is valid today, but the branch is close to end of life and belongs in a migration plan.
The session upload progress caveat
PHP's 23 October note describes CVE-2026-115560 as an unlikely additional RCE vector. The
condition is unusual: an application must set session.serialize_handler to
php_binary or php_serialize in configuration, then switch it to
php at runtime with ini_set() before calling
session_start(). Session upload progress must also remain enabled.
PHP recommends session.upload_progress.enabled=0 until the next regular bugfix
release. Applications that never change the serialisation handler at runtime can keep the
feature enabled, according to the advisory. If you applied the setting on 21 October, keep
it in place.
Cloudflare's rule #6 covers this issue only when the default
session.upload_progress.name is used. A customised name falls outside that
rule. This is a good example of why a WAF rule list is not the same as a patch inventory.
What a patch does not prove
- That the running service changed. A package on disk and an old FPM master can coexist.
- That every environment changed. Staging, preview and legacy nodes are separate runtimes.
- That nothing happened before the patch. Patch and intrusion review answer different questions.
- That no other vulnerability exists. This kit covers PHP2Shell, not your whole estate.
The next page turns those limits into an inventory you can actually check.