PHP2Shell is two remote code execution bugs in the PHP runtime: CVE-2026-109618 and CVE-2026-109619, both rated CVSS 9.2. PHP fixed them on October 21, 2026, in 8.5.12, 8.4.27, 8.3.36, and 8.2.35. The bugs are in PHP itself, so updating WordPress, Drupal, or your own code does not fix them. You must update the runtime.
This post merges seven primary reports into one timeline and one fix plan. The sources are the PHP Foundation post-mortem, the incident reports from Cloudflare, Fastly, and Amazon, the research from Wiz and CrowdStrike, and the OpenAI and CrowdStrike webinar. We transcribed the 48-minute webinar ourselves. Timestamps below point to the recording.
The short version: AI models found a bug class that had survived about 13 years of PHP releases. The disclosure process then broke under leaks. Attackers scanned within hours, but turning a crash into a working shell stayed hard. That gap will close, so the lesson is to build the ability to patch fast.
What PHP2Shell Is
Both bugs come from the same place. When PHP hits a fatal error during a request, such as running out of memory, it jumps out of the current work without cleaning up. Data that was half-built, or memory that was already freed, stays behind. A later step, or a later request on the same worker, then trusts that data.
| CVE | Short name | What goes wrong |
|---|---|---|
| CVE-2026-109618 | Out-of-memory corruption | Running out of memory interrupts request setup. Cleanup then treats half-built data as valid. |
| CVE-2026-109619 | Stale global state | A fatal error leaves internal state that points to freed memory. The next request on the same worker uses it. |
The PHP advisory lists every server mode as affected: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP, and LiteSpeed. Risk is highest on mod_php. There, a single unauthenticated request can trigger the attack before any application code runs.
Wiz showed pre-authentication code execution against the latest WordPress, Drupal, and Joomla container images. Wiz also showed a memory leak path. A crafted multipart request can return reclaimed heap memory inside a PHPSESSID cookie, even when the application never calls session_start(). That memory can hold passwords, tokens, and API keys.
CrowdStrike's lab work shows why default installs are harder to hit. The one-request memory path needs roughly memory_limit < 4 × post_max_size. Stock defaults (memory_limit = 128M, post_max_size = 8M) do not meet that condition. Many real sites raise post_max_size for uploads, for example to 64M with a 128M memory limit. Those sites do meet it.
PHP 8.1 and older get no upstream fix. The advisory links minimal source backports for 7.4, 8.0, and 8.1, and some vendors ship their own.
How AI Found a 13-Year-Old Bug Class
The bug class was not new to everyone. The PHP Foundation says a 2024 external audit by Quarkslab, funded by the Sovereign Tech Agency, led a core developer to the first signs of the out-of-memory problem. The team theorized an exploit but found no concrete attack path. Other issues with clearer impact went first.
In 2026, AI-assisted research supplied the missing proof:
- July 30: Calif starts an audit of PHP under OpenAI's Patch the Planet program.
- August 11: Ryan A of Calif reports an unconditional remote code execution with the out-of-memory root cause. PHP makes the fix its top priority.
- August 19 to 21: Wiz finds its first PHP bug and confirms unauthenticated code execution on Drupal, then WordPress. Wiz used Gemini 4 Argon, GPT-5.6 Sol, and its Wiz Atlas system.
- August 24: Wiz reports more attack paths to PHP.
- September 18: OpenAI reports more attack paths. OpenAI had also found the same root cause on its own.
- October 21: Coordinated release and public disclosure.
In the webinar, OpenAI's cybersecurity research lead Clint Gibler said the patch changed over 200 files (04:32). His team also used models to list candidate mitigations and to try to bypass each one. He said that work took a day or a few hours, where it would have taken a week or more by hand (12:19).
That second use matters. Past fixes often needed follow-up patches because the first fix missed a variant. Adversarial testing of the patch before release is a defender gain, not only an attacker gain.
The Disclosure Timeline: 23 Hours of Leaks
PHP planned to release on October 22 at 14:00 UTC. It released one day early because the embargo kept breaking. The chart counts back from the actual release time.
The leaks, in order:
- October 17: Amazon's MadPot honeypots log an exploit attempt from a commercial anonymization network. Amazon has not found how the actor got the details.
- October 20, about 15:00 UTC: CVE IDs circulate on forums and social media with a wrong release time and a wrong CVSS score of 10.0. No technical details leak yet.
- October 20, 19:30 UTC: PHP moves its pre-announcement and the release forward by one day.
- October 20, about 20:00 UTC: Calif publishes a proof-of-concept video by mistake. It shows the exploit against several targets. Copies spread and speed up public exploit work.
- October 21, 03:02 UTC: Cloudflare turns on WAF rules for all plans, including Free. It had built them since early October.
- October 21, 07:41 UTC: Chainguard publishes built images with the fix. The PHP Foundation says this "disregarded weeks of work by many parties toward a coordinated disclosure."
- October 21, 14:00 UTC: PHP ships the four fixed releases.
Amazon's advice follows from this timeline. Start your log review on October 17, not on the disclosure date.
Why the Fix Took Ten Weeks
The PHP Foundation's post-mortem is direct about its own part. It calls the delay "a structural failure, caused by both the security team's decision process and its lack of resources."
Three causes stand out:
- Consensus decisions. Several competing fixes each had trade-offs. A team that needs full agreement could not pick one fast.
- A small team. Few core developers know the engine well enough to fix it. Security work depends on "a small group of foundation-funded developers and a little volunteer help."
- Report volume. The team published 15 CVEs since July 1. It also worked through more than 100 reports that were invalid, duplicates, or not reproducible.
The Foundation is changing four things. It moves from consensus to majority decisions. It brings leadership in sooner on contested, serious bugs. It formed an Ecosystem Security Team in May and added security staff in July and September. It added OpenAI's Daybreak Red to validate incoming reports and exploits, next to sanitizer builds and reproduction environments.
The report-volume problem is the one to watch. AI makes it cheap to file a plausible report. Maintainers now need AI to sort the real reports from the noise.
What the Edge Saw: Cloudflare, Fastly, and AWS
The three large edge providers each published their own view. Together they show what a WAF can and cannot do here.
| Provider | What it shipped | What it reported | Limit it stated |
|---|---|---|---|
| Cloudflare | Seven managed rules on all plans, live 03:02 UTC Oct 21. A new response-side firewall that inspects the origin's reply too. | Attack traffic after the leak and before disclosure. Attackers changed payloads to get past rules. | Sites that changed session.upload_progress.name are not covered for CVE-2026-115560. Rules are not a substitute for patching. |
| Fastly | An opt-in templated rule that works as a virtual patch. | About 250,000 requests from PHP2Shell-named tools and 3,200 IPs by midday Oct 22. One tool went from version 4.0 to 7.2 in about 11 hours. | A failed and a successful attempt can look the same at the edge. Confirm at the origin. |
| AWS | PHP2Shell_BODY and PHP2Shell_BODY_Extended in the PHP managed rule group. |
A honeypot hit on Oct 17. Proofs of concept around 02:00 UTC on Oct 21, then varied payloads from what looked like several actors. | The rules reduce exposure but do not close the bugs. |
Fastly's report has the most useful detail for a detection team. About one third of the PHP2Shell-tool traffic called itself defensive, such as "authorized exposure check". Two signatures that other teams shared matched mostly a different attack. In the hour Fastly measured, 98.6% and 99.9% of their matches were React2Shell, an older React bug. Fastly also had to exclude wp2shell, a WordPress exploit from July 2026.
Fastly's conclusion: the exploit has no payload string to match. It is a condition, "make the request fail at the wrong moment." Hunt on multipart boundary strings, not User-Agent or IP. Signatures based on User-Agent went stale within a day.
Was Anyone Actually Breached?
Attempts were many. Confirmed breaches were few, and the reports conflict on timing.
- CrowdStrike, webinar recorded the week after disclosure: "We haven't seen any real RCE exploitation," said Adam Meyers (08:41). CrowdStrike saw denial of service and honeypot probes of the session upload progress feature.
- Wiz, October 27: No successful end-to-end exploitation in its own telemetry. Attackers sent the first stages of the current chain. The memory-leak stage failed in every captured run, and no source sent the final stage.
- Independent researcher, October 24: Adel Karimi of Perplexity showed honeypot evidence of a successful attack on Apache mod_php with PHP 8.4.26, as reported by BleepingComputer. An 800 KiB memory leak gave the attacker the address it needed for the final payload.
- CISA, October 26: Both CVEs added to the Known Exploited Vulnerabilities catalog.
Why so few successes? Meyers explained that each exploit path depends on the exact target. An attacker hitting WordPress in a Docker container needs to know that environment in detail (09:11). Gibler expects that gap to close. Frontier models are getting better at taking one crash and making it work reliably across many target setups (19:52).
The quiet week was luck plus hard engineering on the attacker side. Do not plan the next response on that basis.
Mitigations Ranked by What They Actually Block
The PHP advisory states it plainly: these mitigations "do not make an installation safe." Use them only to cover the hours before a patch lands.
| Action | What it blocks | What it does not block |
|---|---|---|
| Upgrade to 8.5.12, 8.4.27, 8.3.36, or 8.2.35 | Both CVEs | CVE-2026-115560, which needs the next regular release |
session.upload_progress.enabled=0 in php.ini or the FPM pool, then restart workers |
The confirmed session paths for CVE-2026-109619, and CVE-2026-115560 | Other fatal-error paths. Setting it with ini_set() or .user.ini does nothing. |
memory_limit=-1 with php_admin_value, plus a low post_max_size (8M, or 32M with uploads) |
The out-of-memory trigger for CVE-2026-109618 | Workers can now use much more memory. Never use RLIMIT_AS or RLIMIT_DATA to cap it, as these trigger the same failure. |
fatal_error_backtraces=0 on PHP 8.5 |
The confirmed backtrace path | Other fatal-error paths |
| WAF managed rules | Known exploit shapes on proxied traffic | Mutated payloads, direct-to-origin traffic, custom field names |
| Block internet access to appliance admin pages | Remote attacks on unsupported PHP appliances | Attackers already inside the network |
A third issue, CVE-2026-115560, affects fully patched releases. It needs a rare setup: the app sets session.serialize_handler to php_binary or php_serialize, then switches it to php at runtime before session_start(). If you turned off upload progress on October 21, keep it off.
Check Your Servers
Use these steps for each host that serves PHP. The command line PHP and the web server PHP can be different builds with different settings, so check both.
- List every PHP install: package-managed, container images, appliances, and hand-built binaries. CrowdStrike notes that PHP outside the package manager is the common miss.
- Run the script below with the web server's ini file, for example
php -c /etc/php/8.3/fpm/php.ini php2shell_check.php. - Search FPM pool files, Apache virtual hosts, and
.htaccessfor per-sitememory_limitandpost_max_sizeoverrides. One site on shared hosting can make the whole host reachable. - Search error logs back to October 17 for the startup memory error shown below.
- Upgrade, restart every worker, and run the script again.
<?php
// php2shell_check.php - run with the same php.ini your web server uses.
// Vendor backports keep older version strings, so confirm with your vendor if this reports "vulnerable".
$fixed = ['8.6' => '8.6.0RC4', '8.5' => '8.5.12', '8.4' => '8.4.27', '8.3' => '8.3.36', '8.2' => '8.2.35'];
$branch = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
function to_bytes(string $value): int {
$value = trim($value);
if ($value === '-1') {
return -1;
}
$bytes = (int) $value;
switch (strtolower(substr($value, -1))) {
case 'g': $bytes *= 1024; // fall through
case 'm': $bytes *= 1024; // fall through
case 'k': $bytes *= 1024;
}
return $bytes;
}
if (!isset($fixed[$branch])) {
echo "PHP $branch gets no upstream fix. Upgrade, or use a vendor backport.\n";
} elseif (version_compare(PHP_VERSION, $fixed[$branch], '<')) {
echo "PHP " . PHP_VERSION . " is vulnerable. Upgrade to {$fixed[$branch]} or later.\n";
} else {
echo "PHP " . PHP_VERSION . " has the October 21 fix.\n";
}
$memory = to_bytes((string) ini_get('memory_limit'));
$post = to_bytes((string) ini_get('post_max_size'));
if ($memory !== -1 && ($post === 0 || $memory < 4 * $post)) {
echo "memory_limit is under 4 x post_max_size. The one-request memory path is reachable.\n";
}
if (ini_get('session.upload_progress.enabled')) {
echo "session.upload_progress.enabled is on. Turn it off until the next PHP release.\n";
}
The log line comes from CrowdStrike's research. The phrase in Unknown on line 0 means PHP failed before it ran any script file. Normal memory errors name a file and a line.
grep -E "Allowed memory size of [0-9]+ bytes exhausted.*in Unknown on line 0" \
/var/log/apache2/error.log* /var/log/php*-fpm.log* 2>/dev/null
Also look for Apache worker crashes (AH00051), PHP workers that open outbound connections, and web server processes that start shells. Amazon adds one more check: POST bodies that contain PHP_SESSION_UPLOAD_PROGRESS.
The Bigger Pattern: Bug Volume Has Changed
PHP2Shell is one bug in a much larger wave. Meyers gave the numbers in the webinar. NVD recorded about 48,200 CVEs in 2025. By late October 2026 the count had passed 87,000 (06:27).
He said monthly CVE counts went from 3,000 to 4,000 in 2025 to 12,000 to 15,000 in recent months. His team used to advise 30-day patch windows. Now he puts the window closer to 30 hours (07:00).
Attackers also use agents inside networks now. CrowdStrike tracked an intrusion into South Korean financial firms by an actor it describes as unskilled. The actor used ARTEX, a Chinese agentic penetration-testing framework, and then asked an AI model how to sell the stolen data (22:41). Meyers compared the pace: a human operator types a couple of dozen commands an hour, while an agentic attacker can pass a thousand (24:24).
His point is that the attacks are not new. They are the old weaknesses, run at machine speed. Every unpatched server and every over-privileged account now gets found.
What to Build Now
The three speakers gave the same answer from three angles: the fundamentals now pay off faster. These are the items that cut response time the most.
- An asset inventory you can query in minutes. You cannot patch PHP you do not know about. Gibler notes that coding agents now let a security team build a company-specific inventory service in a weekend instead of a quarter.
- A fast, tested path to production. If a runtime upgrade takes three weeks of change review, a 30-hour window is lost. High test coverage and fast deploys are security controls.
- Disposable test environments. Gibler asks for the ability to spin up a copy of an application on demand. Then agents can test a fix and check for regressions before you ship it.
- Telemetry across endpoint, identity, cloud, and network. Meyers says identity is the gap he sees most. Agentic attackers move fast once inside, and you need to see them move.
- Least privilege for agents. Treat each AI agent like an employee account. If a compromised agent can reach production, that is the same insider risk as a compromised laptop.
- A rehearsed incident plan. Know who to call, when to use your incident response retainer, and which tools to use. Run a tabletop with PHP2Shell as the scenario.
These match what we wrote about making coding agents prove their work. The same evidence pipeline that lets you trust an agent's pull request lets you ship a security patch the same day.
Turn Patch Speed Into a Business Advantage
The companies that came through PHP2Shell well could answer three questions fast: where is PHP, what version is it, and how quickly can we ship a new one. OpenNash puts forward-deployed engineers on your team and works with Fortune 2000 companies to build that capability with AI agents. A typical engagement follows these steps:
- Build an agent-maintained inventory of runtimes, dependencies, and exposed services across your estate.
- Connect vulnerability feeds to that inventory, so a new CVE produces a ranked list of affected systems within an hour.
- Add agents that draft the patch or config change, run it in a disposable environment, and attach test evidence.
- Put least-privilege controls and audit logs on every agent that touches production.
- Run a tabletop exercise against a real incident like PHP2Shell, and measure time to patch.
At the end, you own the inventory, the agents, the test harness, and the runbooks.
Book a call with an OpenNash forward-deployed engineer or email us at hello@opennash.com. In the first session, we review your top AI use cases and your data, and show which ones give the highest business value and the fastest ROI.