Ecommet
· ·

PHP2Shell Explained: The Critical PHP Flaws Patched on 21 October 2026

Two bugs hid in PHP’s error handling for years. AI models found them, a leak blew the embargo, and admins worldwide got roughly 24 hours’ warning before an emergency patch. Here’s what broke, how it works, and what to do right now.

If you run PHP on anything that serves web traffic, update today to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35. PHP2Shell is a pair of critical memory-safety bugs in the PHP engine itself, CVE-2026-109618 and CVE-2026-109619, that can let an unauthenticated attacker run code on your server. The PHP team shipped emergency fixes on 21 October 2026, a day after details leaked.

CVEsCVE-2026-109618 (OOM corruption), CVE-2026-109619 (stale global state)
SeverityCVSS v4.0 9.2 each (PHP); watchTowr rates it 10.0
AttackRemote, unauthenticated, can fire before app code runs on mod_php
AffectedEvery unpatched PHP serving web requests; reportedly PHP 5.4 onward
Fixed in8.5.12, 8.4.27, 8.3.36, 8.2.35 (released 21 Oct 2026)
End-of-life8.1 and older: no official release; source backports for 7.4, 8.0, 8.1
ExploitationEarly attacks reported by Cloudflare; scale still disputed

What is PHP2Shell?

PHP2Shell is the nickname for two remote code execution flaws in the PHP runtime, not in any framework or CMS. The name says what an attacker gets: a shell on your web server.

That distinction matters. Your WordPress, Laravel, Magento or custom code can be perfectly written and the server is still exposed, because the bug sits in how PHP itself handles requests that fail partway. Online stores on Magento, Shopware or WooCommerce are just as exposed as any hand-rolled site.

There’s a twist in how they were found: AI. Researchers at Calif used OpenAI’s GPT-5.6 Sol, while Google’s Wiz team paired its own Wiz Atlas agent with Gemini 4 Argon and GPT-5.6 Sol to dig the bugs out of code paths that had gone unnoticed for years.

Every PHP installation that serves web requests is at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed alike.

Timeline: found in August, leaked on 20 October, patched on 21 October

The bugs sat under coordinated disclosure for about ten weeks. The plan broke when details leaked a day early, forcing the PHP team to pre-announce and then rush the release.

Date (UTC)Event
1 Aug 2026Calif finds multiple RCE paths
11 Aug 2026Calif reports the first bug to PHP; coordinated disclosure begins
24 Aug 2026Wiz Research reports the vulnerabilities to PHP
20 Oct 2026Details leak; PHP posts an advance notice; watchTowr confirms RCE
21 Oct 2026, 07:43Cloudflare reports early attacks and deploys temporary WAF rules
21 Oct 2026, ~14:00PHP releases fixed versions; Calif, Wiz, OpenAI and PHP publish details
21 Oct 2026CISA and CERT-EU urge immediate patching
22 Oct 2026Sansec revises its outlook: mass exploitation less likely than first feared

Reports differ slightly on the exact release time: the PHP team had pre-announced 14:00 UTC, though some advisories put it at 13:30 UTC.

How it works: two ways a failed request poisons memory

Both flaws live in PHP’s error paths: what happens when a request dies halfway, usually from running out of memory or hitting a fatal error. In each case the result is a classic memory-safety bug, such as a use-after-free (CWE-416) or an uninitialized pointer (CWE-824).

CVE-2026-109618: corruption during out-of-memory handling

PHP enforces memory_limit by jumping out of the request with longjmp() the moment the limit is crossed. That jump can land while PHP is halfway through building internal request data, for example while parsing a multipart file upload into $_POST and $_FILES.

Cleanup then treats the half-built structures as valid and tries to free memory that was never initialized. That memory can still hold leftover bytes the attacker planted earlier in the same request. The confirmed path runs through the session upload-progress feature, and it can leak memory as well as run code.

CVE-2026-109619: stale global state across requests

A PHP worker handles many requests in sequence. Some global state (error backtraces, session data, serializer state, extension state) belongs to one request but can outlive the memory backing it, for instance when a fatal error skips the normal reset.

The next request on the same worker can then touch that stale pointer before initialization clears it. Sansec names a fatal-error backtrace use-after-free and an OPcache type confusion as concrete paths.

Why mod_php is the worst case

The PHP team rates Apache mod_php highest risk because a demonstrated exploit fires from one unauthenticated request before any application code runs. PHP-FPM blocks one of the out-of-memory paths at startup, but it still needs patching: a session-based RCE has been confirmed against FPM under the right application conditions.

Researchers also showed unauthenticated leaks of PHP worker memory, which can expose passwords, session tokens and API keys even where full RCE fails.

Impact: a huge attack surface, but exploitation is harder than first feared

PHP runs a large share of the web, so the exposure is enormous. One scan of enterprise environments found 44 million PHP installs (28%) on supported 8.2–8.5 branches that were still unpatched. Most of the rest sit on end-of-life versions with no official fix at all.

What an attacker gets. Code runs with the PHP process’s permissions. That is usually enough to steal database credentials and customer data, deface the site, plant a web shell or move deeper into the network.

What actually happened in the first 48 hours:

  • Cloudflare reported early attacks before the patch even shipped and pushed temporary WAF rules, while warning they are only a stopgap.
  • Amazon spotted a PHP2Shell exploit attempt on its honeypot network, and exploit code claiming to work universally appeared on GitHub.
  • Many sites flipped to maintenance mode as a precaution, Wikimedia’s Phabricator among them. Some government sites were pulled offline and the NSA issued a warning.
  • CISA and CERT-EU both urged organisations to patch immediately.

The counterpoint. Early predictions had mass attacks starting within 15 minutes of release. By 22 October, researchers were walking that back: a working attack needs specific knowledge of the target and specific conditions on it, and the public exploits fail against a default PHP install. Treat that as a reason for calm, not for delay.

The long tail is the real risk. Abandoned sites, unsupported apps and devices with PHP-based admin panels may never get patched. Check the commercial products you run too, since many embed PHP under the hood.

How to patch

Updating is the only complete fix. The PHP team is clear that no configuration change fully closes these bugs.

Your branchAction
8.5.xUpgrade to 8.5.12
8.4.xUpgrade to 8.4.27
8.3.xUpgrade to 8.3.36
8.2.xUpgrade to 8.2.35
8.1, 8.0, 7.4Move to a supported branch, use a vendor/LTS backport, or apply PHP’s minimal source backports
7.3 and olderUpgrade; no official backport exists
  1. Find every PHP install. Include containers, appliances and forgotten subdomains. Run php -v on servers, but remember the web SAPI can differ from the CLI binary, so also check phpinfo() or your FPM/Apache module version.
  2. Prioritise mod_php and anything internet-facing.
  3. Update the package.
    • Debian/Ubuntu: sudo apt update && sudo apt install --only-upgrade 'php*'
    • RHEL/Alma/Rocky: sudo dnf upgrade 'php*'
    • Distros often backport fixes without bumping the version number, so look for CVE-2026-109618 and CVE-2026-109619 in the package changelog.
    • Remi repository users: updates were not available on release day; switch to distro packages or build from source.
  4. Containers: bump your base image to the patched tag and rebuild and redeploy. A running container never picks up a host update.
  5. Restart every PHP process. Restart PHP-FPM pools and Apache; until workers restart, the old vulnerable code is still in memory.
  6. Verify. Confirm the version the web server actually runs, not just the package manager. External scanners can help, but a clean scan does not prove you are patched.
  7. Managed hosting and SaaS: ask your provider for written confirmation and a patch date.

If you can’t patch today: temporary mitigations

These reduce exposure to the known attack paths but do not make a server safe. Apply both core settings together, because each covers a different CVE. If neither patching nor mitigating is possible, take the site offline or isolate it until you can, as CERT-EU advises.

The two core settings. Put them in php.ini, the FPM pool (php_admin_value) or the Apache config, so applications cannot override them. Then restart every worker.

; CVE-2026-109619: blocks the confirmed session upload-progress paths
session.upload_progress.enabled = 0

; CVE-2026-109618: removes the controllable memory_limit failure
memory_limit = -1

Do not rely on ini_set() or .user.ini for these; they apply too late. Check that no pool, directory or app re-sets a finite memory_limit.

Contain the memory risk of memory_limit = -1. Use a container or cgroup memory limit that kills only the affected worker. Do not use RLIMIT_AS or RLIMIT_DATA instead, because they can trigger the same vulnerable allocation failure.

Shrink the request surface.

  • Set post_max_size = 8M for apps without uploads, or 32M if uploads are needed, with upload_max_filesize below it.
  • If you don’t need file uploads, block multipart/form-data POSTs at the proxy or WAF.
  • Enforce limits at the web server on body size, field count, multipart part count, header count and nesting depth, including requests without a usable Content-Length.

Extra steps for CVE-2026-109619.

  • On PHP 8.5, set fatal_error_backtraces = 0 and restart workers.
  • Remove invalid or deprecated per-request settings that emit warnings early. Hiding errors with display_errors or @ does not help.
  • Fix fatal errors and timeouts an outsider can trigger, such as failing upload or import handlers.

PHP’s official security advisory lists the complete set of mitigations.

After patching: check whether you were already hit

Attacks started before the fix, so a patched server may already be compromised. Review logs from at least 20 October onward.

Signs worth investigating:

  • Unusual multipart POSTs followed by memory-limit errors or bursts of HTTP 500s
  • Oversized or malformed PHPSESSID cookies
  • Unexplained PHP worker crashes or restarts
  • New or modified .php files, especially in upload, cache or temp directories (likely web shells)
  • New admin accounts in your CMS or app
  • Unexpected outbound connections from the web server

Rotate secrets on internet-facing PHP hosts. The memory-disclosure path can leak whatever the worker held, so rotate database passwords, API keys, session secrets and tokens, and invalidate active sessions.

If you find a compromise, isolate the host, preserve logs and disk images, and rebuild from a known-good image rather than cleaning in place.

What PHP2Shell teaches us

  • Runtimes are attack surface. Secure application code cannot save you from a bug in the interpreter beneath it. Track your PHP version like any other dependency.
  • End-of-life is a real cost. Teams on 8.1 or older had no official fix on day one. Keep on a supported branch.
  • Embargoes can break. This one leaked a day early. Know how fast you can find, patch and restart every PHP host before the next one.
  • AI is now finding deep bugs. Both teams used AI models to uncover flaws in decades-old code paths. Expect more disclosures like this, and faster.

Patch, restart, verify, then hunt for signs of compromise. In that order.

Further reading

Have a project in mind?

Tell me what you need, even in a few lines, and I’ll come back with questions or a quote.