· 8 min read
PHP2Shell (Part 1): When the hotel keycard encoder fails, room locks don't save you
PHP shipped emergency fixes on 21 Oct for PHP2Shell, two unauthenticated RCE bugs in the engine. Part 1 covers which layer broke, which versions are affected, and what AI actually did in finding them.
One analogy up front — and it's a simplification; we'll map it back to the real mechanics below.
A hotel's front-desk keycard encoder is usually strict: one card, one room. Someone finds that if you keep feeding it weird cards until it overloads, it crashes mid-write. After the restart, the half-written permissions from the last card were never cleared. The next card that comes out can open rooms it shouldn't — including the control room.
Two things matter. You don't need to be a guest, and you don't need a password; standing at the front desk is enough. And no matter how strong each room's lock is, it doesn't help — the problem is the encoder itself.
On 21 October 2026, the PHP project shipped an emergency security release. Two bugs, bundled in public discussion as PHP2Shell (CVE-2026-109618 and CVE-2026-109619), both scored CVSS v4.0 9.2. In the analogy, the encoder is the PHP engine. Your site's own application code is just the room locks. Fancy locks won't stop a machine that prints the wrong access onto every card.
This part covers what broke, why the root cause sits below your app, and how domain knowledge plus AI assistance changed the path to finding and weaponizing it. Part 2 covers the broken embargo, in-the-wild activity, the Taiwan numbers, and a concrete checklist.
What happened
PHP is the runtime behind a huge share of the web — WordPress, Drupal, Laravel, and countless custom stacks. Per W3Techs (26 Oct 2026), about 69% (69.2%) of sites with an identifiable server-side language run PHP. That figure is language market share, not "how many boxes are still unpatched." Treating market share as victim count inflates the story.
The two issues, in short:
- CVE-2026-109618 — remote code execution via out-of-memory (OOM) corruption
- CVE-2026-109619 — remote code execution via stale global state
Both are unauthenticated RCE: no login to your admin panel required. Calif traces the earliest affected path to PHP 5.4.0 — roughly fourteen years of releases. Official fixed builds are 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35. PHP 8.1 and earlier are out of regular project support; slim source-only backports exist for 7.4, 8.0, and 8.1 (no formal releases); 7.3 and older, including PHP 5, have no upstream fix. PHP 8.2 reaches EOL on 31 Dec 2026. Scores: official CVSS v4.0 9.2 for both; under CVSS 3.x, NVD-style figures commonly cited are 9.8 (109618) and 8.1 (109619); pre-disclosure leaks wrongly claimed 10.0. After updating, restart every PHP worker — new firmware does nothing if the desk machine never reboots. PHP is explicit: config-only mitigations do not make you safe; updating is the only complete fix.
The name "PHP2Shell" was already circulating about a day before the public drop; PHP Foundation, Wiz, OpenAI, CISA, Cloudflare, and others later used it too.
Root cause: half-written state that never got cleared
Map the analogy back to the engine (again: simplification).
Normally PHP finishes an HTTP request, tears down that request's memory and internal state, and takes the next one. The failure mode is the "abort halfway" path. Historically, when allocation blows past memory_limit or a fatal error hits, PHP may bail out with a longjmp-style jump. That can leave:
- Half-initialized memory — counters bumped, payload never finished; cleanup still treats it as live (roughly 109618).
- Global state that outlives the request — a pointer still aims at freed heap; a long-lived worker (especially PHP-FPM) is like the same encoder serving the next guest without a reset, so the next request may reuse leftover state before normal init (roughly 109619).
In the analogy: the machine gets overloaded, crashes mid-write, and leaves half-written permissions behind — the next card can open the control room. Readers do not need the request-crafting details; the point is the engine itself can leave unfinished state after a bad abort.
Official guidance flags Apache mod_php as highest risk. Think of it as the encoder built into the front desk itself: a visitor interacts with it directly, and cleanup can still run even when startup fails — before any of your application code runs. PHP-FPM is more like a separate window behind the desk: a failed startup usually kills the worker, so you don't get the same "same process consumes the half-finished card" path as easily. Fatals after a successful start can still leave a living worker — parts of 109619 are validated or source-supported on FPM. For 109618, the GitHub advisory says RCE was demonstrated over HTTP under mod_php with default limits; FPM is "source-affected" but a full FPM exploit has not been shown.
Hardening your app, updating plugins, rewriting controllers — those are better room locks. They do not reflash the encoder. The complete fix is updating PHP. The ini knobs PHP lists only shrink some paths, and the project says so explicitly.
Discovery: human instinct steered it; AI cheapened the exploit path
PHP2Shell is also a case study in how AI changes security tempo — but not in the way some headlines imply.
Timeline (clock times in Taipei, UTC+8, where a time is given; date-only items keep the source's UTC date or stated publish day):
- 2004 / 2020 / 2024: Stefan Esser's early "memory limit" class of issues (Calif's historical framing, not this CVE itself); bug #78876; an OSTIF / Quarkslab audit (with Sovereign Tech Agency and other funding) resurfaced related OOM issues — theoretically exploitable, not demonstrated, fix stalled. The PHP Foundation later called that a structural failure.
- From May 2026: a dedicated ecosystem security effort; tools in the broader narrative include Anthropic Claude Mythos (via Alpha-Omega) and OpenAI Daybreak Red for scanning or validation.
- From 30 July: security firm Calif audited PHP under OpenAI's "Patch the Planet" program.
- Calif's account (primary): first paths around 1 Aug; researcher Ryan Austin (@lcfr_hax) posted a discovery hash on X on 5 Aug; 11 Aug first bug reported to PHP; 14–15 Aug a reproducible RCE PoC submitted and confirmed; 21 Aug second bug. The framing that matters: discovery rode on knowing PHP's vuln history and codebase ("know your target"); no private super-model. LLMs helped explore edge cases and generalize the pattern into a searchable skill, but they are not "prompt once, dump every bug." Direct quote: "No model is simply capable of unearthing 'all bugs' with simple prompts. At least for now." TechCrunch's read matches: AI mainly helped turn the bug into a working exploit path; the bulk was prior researcher knowledge.
- Wiz: found 19 Aug; RCE on Drupal / WordPress 20–21 Aug; formal report 24 Aug. Their write-up mentions Gemini 4 Argon, GPT-5.6 Sol, and related tooling.
- OpenAI: publicly says Calif found one version with GPT-5.6 Sol in August, and OpenAI's own team found a more complete version in September; the PHP Foundation says OpenAI reported the same root cause and filed another attack path on 18 Sep. The exact date of OpenAI's first independent report disagrees across primary sources — we keep that hedge rather than pick a winner.
- 16–17 Oct: Chainguard CEO Dan Lorenc says that after learning a disclosure was coming, his team independently reproduced overnight with their AI harness and frontier models, and joined the coordination channel on 17 Oct.
Same class of bug, found several times in weeks, often with AI nearby — but humans steered where to look; what got cheaper is the step from "theoretically broken" to "reliable exploit." Axios leaned on "OpenAI's technology helped find the bugs"; OpenAI's own post stresses frontier AI beating attackers to the punch — marketing is stronger than Calif's primary write-up. Program name per OpenAI and Calif: "Patch the Planet" (TechCrunch's "Hack the Planet" does not match those primaries). That still compresses the quiet patch window. Part 2 covers how the 20–21 Oct embargo broke. One note: cheaper weaponization does not mean every public "one-click PoC" is real — many are hallucinations; Marcus Hutchins on fake guides returns in Part 2.
OpenAI president Greg Brockman framed the effort as a roughly two-month coalition and admitted the end of disclosure did not go as planned (paraphrase: release was aimed at 22 Oct; details leaked early; PHP maintainers moved to 21 Oct). Policy chatter about authorizing defensive scanning — and, in extreme cases, remote patching — is a larger debate. Flag only this: PHP2Shell is already being used as an "AI security new normal" exhibit.
Takeaways from Part 1
- Encoder = PHP engine; room locks = your application. When the engine is wrong, changing locks is not enough.
- Two CVEs, CVSS 9.2, unauthenticated RCE; fixed in 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35.
- Root cause is half-finished state after OOM / fatals; mod_php is the hottest SAPI.
- "~69% of sites with a known server-side language run PHP" is language share, not unpatched inventory.
- Reach back to PHP 5.4; formal fixes only on 8.2–8.5; restart every worker after updating.
- Domain knowledge steered discovery; AI cheapened exploit-building — not "AI one-prompt RCE." Multi-party finds still shortened disclosure.
Next: From 20 Oct the CVE IDs leaked, Calif briefly exposed a demo video, and Chainguard shipped patched images early. AWS honeypots saw attempts four days before disclosure; a researcher honeypot on 24 Oct confirmed successful in-the-wild shells. Taiwan's cyber agency counted on the order of 28,000 exposed PHP sites and about 200 government ones. Part 2 is the checklist and the lessons.
Read on: PHP2Shell (Part 2)
Clock times are given in Taipei time (UTC+8) with UTC noted on first use where helpful. Date-only items keep the source UTC date or the official publish date. Public disclosure time disagrees by about half an hour across documents; Part 2 notes that.
Sources
- PHP archive / security announcements, 2026-10-20–21: https://www.php.net/archive/2026.php
- GitHub Security Advisories: GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp (php/php-src)
- PHP Foundation, "Today's PHP Security Release, and How We're Strengthening PHP Security", 2026-10-21: https://thephp.foundation/blog/2026/10/21/todays-php-security-release-and-how-were-strengthening-php-security/
- Calif, "PHP2Shell: A tale of two PHP remote vulnerabilities": https://calif.io/php2shell/
- Wiz, "PHP2Shell", 2026-10-21: https://wiz.io/blog/php2shell-php-rce
- OpenAI, "Coordinated disclosure of critical vulnerabilities", 2026-10-21: https://openai.com/index/coordinated-disclosure-of-critical-vulnerabilities/
- Greg Brockman (@gdb) X long-form / Article, 2026-10-21