
PHP2Shell: Patching CVE-2026-109618 & CVE-2026-109619 Before Someone Else Does It For You
Key Takeaways
- CVE-2026-109618 and CVE-2026-109619 are two unauthenticated RCE vulnerabilities in PHP rated CVSS 9.2, collectively dubbed PHP2Shell by Palo Alto Unit 42.
- Every PHP version from 5.4 through 8.5.11 is affected. Patched releases: 8.5.12, 8.4.27, 8.3.36, 8.2.35.
- PHP 8.1 and earlier are end-of-life with no official patch. Backporting is not a safe substitute for upgrading.
- Set
session.upload_progress.enabled=0as an interim control for CVE-2026-109619 and CVE-2026-115560 while you prepare the patch. - If you run PHP applications and don't have a patching SOP, now is the moment to build one.
On October 21, 2026, the PHP project and Wiz Research disclosed two critical vulnerabilities in PHP's core request handling. Both carry a CVSS score of 9.2. Both allow unauthenticated remote code execution. Both affect every PHP version released in the last decade-plus. Palo Alto Unit 42 named the pair PHP2Shell.
This is not a theoretical edge case. PHP powers roughly 77% of web servers with a known server-side language. WordPress, Laravel, Symfony, Magento, and the vast majority of custom web applications built in the last fifteen years run on it. If you ship PHP code or operate infrastructure that runs it, this affects you.
Here is what the vulnerabilities actually do, who is exposed, and what you need to do today.
What CVE-2026-109618 and CVE-2026-109619 Actually Do
CVE-2026-109618 — RCE via Out-of-Memory Corruption (CVSS 9.2)
PHP initializes internal request data structures when handling each incoming request. If the process runs out of memory partway through that initialization, the OOM handler fires and the process begins cleanup. The bug: cleanup code treats the partially initialized data as fully valid. It follows pointers that don't point to what they claim to point to.
An attacker does not need to find a memory corruption bug elsewhere in your application. They need to reliably trigger an out-of-memory condition during PHP's own request startup — which is predictable, and in many deployment configurations, controllable from the outside. Once OOM fires at the right moment, the corrupted state enables arbitrary code execution. No authentication required.
CVE-2026-109619 — RCE via Stale Global State (CVSS 9.2)
PHP workers in FPM or other persistent-process models handle multiple requests over their lifetime. After a fatal error terminates one request, PHP performs cleanup. The bug: certain request-owned internal state — data that should be torn down with the request — survives in memory after the backing allocation is freed. The memory is gone, but the pointers remain.
When the same worker picks up the next request, it reads that stale state before normal initialization has a chance to reset it. An attacker who can trigger a fatal error on one request and send a crafted second request to the same worker can exploit that window to execute arbitrary code.
CVE-2026-115560 is a separate RCE vulnerability in PHP's session upload progress handling that shares the same class of root cause and is mitigated by the same configuration change (covered below).
Both CVE-2026-109619 and CVE-2026-115560 were disclosed the same day as part of the same coordinated release.
Who Is Affected
The scope here is unusually wide. Affected versions span PHP 5.4 through 8.5.11 — essentially the entire history of modern PHP. That includes:
- WordPress sites (43% of the public web) running any PHP version
- Laravel and Symfony applications on any unpatched PHP 8.x build
- Magento and other ecommerce platforms running on shared or managed PHP hosting
- Custom applications built on any PHP version in the affected range
- Shared hosting environments where your host controls the PHP version and you may not know what they're running
If you're on a managed host, check their security bulletins now. Many shared hosts run older PHP versions for compatibility reasons, and patch cycles on shared infrastructure are not always fast.
If you manage your own servers, the version is on you.
Immediate Action Plan
Step 1 — Audit Every PHP Version in Your Stack
Before you patch anything, know what you're running. On each server:
php -v
php-fpm -v # if using FPM
If you manage multiple applications across different servers or containers, run this across all of them. A single unpatched FPM worker handling untrusted HTTP input is sufficient exposure.
Step 2 — Patch to a Fixed Version
The patched releases are:
- PHP 8.5 → 8.5.12
- PHP 8.4 → 8.4.27
- PHP 8.3 → 8.3.36
- PHP 8.2 → 8.2.35
If you're on 8.2, 8.3, 8.4, or 8.5, upgrade to the corresponding fixed version. Use your package manager, or pull from php.net. Verify the version after upgrade:
php -v
Confirm the output shows the patched version before you consider this step done.
Step 3 — If You're on PHP 8.1 or Earlier, Upgrade the Branch
PHP 8.1 reached end-of-life in November 2024. PHP 8.0 and 7.x have been EOL for longer. There is no official patch for any of these versions.
Minimal source backports exist for 7.4, 8.0, and 8.1, but relying on unofficial backports to patch a CVSS 9.2 vulnerability in a production application is not a sound strategy. The right path is upgrading to PHP 8.2 or later, then applying the fix.
Yes, that may require compatibility work on your application. That compatibility work is overdue regardless of this vulnerability. EOL PHP is a sustained security liability, not a version preference.
Step 4 — Apply the Interim Configuration Mitigation
While you're preparing the patch and testing it, apply this configuration change to reduce exposure from CVE-2026-109619 and CVE-2026-115560:
; php.ini
session.upload_progress.enabled = 0
This disables session upload progress tracking, which is the attack surface exploited by CVE-2026-115560 and reduces one vector for CVE-2026-109619. It is not a substitute for patching CVE-2026-109618, but it removes a meaningful attack surface while you work through the upgrade.
Apply this to your php.ini or the relevant conf.d drop-in, then reload:
# For PHP-FPM
systemctl reload php8.X-fpm
# Verify the setting took effect
php -r "echo ini_get('session.upload_progress.enabled');"
# Should output: 0 or empty string
Step 5 — Test in Staging Before Pushing to Production
PHP version upgrades can carry behavioral changes unrelated to these CVEs. Run your test suite against the patched version in a staging environment before deploying to production. Pay attention to:
- Extension compatibility (particularly older PECL extensions)
- Deprecated function usage in application code
- Any framework-specific version requirements
The patch is small and targeted, but a full PHP minor/patch version bump warrants a validation pass.
Step 6 — Check Your Hosting Provider
If any of your applications run on managed or shared hosting, check whether your host has already patched. Most major providers will issue a security bulletin. If you're on shared hosting and your host has not patched, the exposure is real and you have limited direct control. Your options: push the host to patch, or migrate to a provider that has already done so.
What This Exposes About PHP Security Posture
Beyond the immediate patch, PHP2Shell surfaces a few structural points worth taking seriously.
EOL software in production is not a minor risk. PHP 8.1 reached EOL roughly two years ago. Applications still running it have been accumulating unpatched vulnerabilities since then, and PHP2Shell is the most severe example yet of what that accumulation looks like. If your engineering team doesn't have a policy that triggers a version upgrade before EOL, now is the time to write one.
Dependency audits need to cover the runtime, not just packages. Most teams run composer audit or equivalent dependency scanning. Fewer have automated checks on the PHP binary version itself. The runtime is as much a part of your attack surface as any library you install.
Patch SOPs exist for a reason. When a CVSS 9.2 RCE drops, the question shouldn't be "where do we even start?" It should be a known procedure that a senior engineer can execute in hours. That means maintained runbooks, staging environments that mirror production closely enough to be useful, and clear ownership of who patches what.
Runtime protection adds a layer, but doesn't replace patching. WAF rules and runtime application self-protection can raise the cost of exploitation for some attack paths. They don't fix the vulnerability. Patch first, then layer on controls.
Verify You're Protected
After patching, confirm your exposure is actually closed:
# Confirm patched PHP version
php -v
# Confirm upload progress is disabled (if applied as interim mitigation)
php -r "echo ini_get('session.upload_progress.enabled') === '' ? 'disabled' : ini_get('session.upload_progress.enabled');"
# Check all running FPM pools are on the patched binary
php-fpm -v
Monitor your application logs for anomalous OOM events or fatal errors in FPM workers in the days following the patch. If you see patterns that look like probing, treat it seriously.
Summary
CVE-2026-109618 and CVE-2026-109619 are as serious as they look on paper. Unauthenticated RCE with a 9.2 CVSS across a decade of PHP releases is not something to park in a backlog. Patch to 8.2.35, 8.3.36, 8.4.27, or 8.5.12. Apply the session upload progress mitigation while you prepare. Upgrade any application still on EOL PHP.
If your team runs PHP applications and you're not certain of your current exposure — or you want an engineering partner who patches before it becomes a crisis rather than after — that's what ZycoSoft does. We build and maintain production PHP systems for founders, SMEs, and enterprise teams, and security patching is part of how we work, not an afterthought.
Book a consultation at zycosoft.com/consultation to talk through your PHP stack and security posture.
Frequently Asked Questions
CVE-2026-109618 is a CVSS 9.2 remote code execution vulnerability in PHP's core request handling. It arises from a use-after-free condition during out-of-memory cleanup: when PHP runs out of memory partway through request initialization, the cleanup code follows stale pointers, enabling an attacker to execute arbitrary code without authentication.
Both CVEs affect PHP 5.4 through 8.5.11. The patched releases are PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35. PHP 8.1 and earlier are end-of-life with no official patch available; upgrading to a supported branch is the only safe path for those versions.
Run `php -v` and `php-fpm -v` on each server. Compare the output against the fixed versions: 8.5.12, 8.4.27, 8.3.36, 8.2.35. If you manage multiple applications, search for all composer.lock files and cross-reference the PHP runtime version used by each application environment.
Add `session.upload_progress.enabled = 0` to your php.ini. This disables the attack surface exploited by CVE-2026-115560 and reduces one vector for CVE-2026-109619. It does not mitigate CVE-2026-109618. Treat it as a temporary measure only — patch as soon as your release process allows.
PHP2Shell is the name given by Palo Alto Unit 42 to the combination of CVE-2026-109618 and CVE-2026-109619. The name reflects the vulnerability class: unauthenticated remote code execution in PHP itself, not in any application layer. It is not a separate library or tool.
Yes. WordPress runs on PHP, so any WordPress installation using PHP 5.4 through 8.5.11 is vulnerable. The fix is upgrading the PHP runtime, not updating WordPress core or plugins. Contact your hosting provider if you do not control the PHP version directly.
Patch PHP first to close the active vulnerability. Then check for recently modified PHP files in your web root, review access logs for anomalous patterns, audit running cron jobs, and scan listening network services for unexpected entries. If the exposure window was more than a few hours on a public-facing server, a full incident response review is warranted before trusting the system again.
