Reported in 2019, Audited in 2024, Exploited in 2026: What AI Actually Changed About PHP2Shell

We have covered the broken embargo and the release that fixed it. Now the research is public, and it reframes the whole event. Three organisations — Wiz Research, Calif and OpenAI — published on 21 October 2026, and all three describe CVE-2026-109618 and CVE-2026-109619 as a milestone for AI-assisted vulnerability research. Wiz calls it “the AI inflection point.” The headlines followed.

The claim deserves to be taken seriously, and it also deserves to be read precisely, because the public record contains a detail that complicates the shorter version of the story. The out-of-memory condition at the root of PHP2Shell was reported to the PHP project in 2019, closed with a CVE, and rediscovered by a professional audit in 2024. It survived both encounters. What frontier models supplied in August 2026 was not the sighting of an unknown bug. It was proof of exploitability for a condition that had already been seen twice and twice classified as something less dangerous — and that is a sharper, more uncomfortable finding than “AI found a bug.”

The paper trail, read first-hand

Calif’s write-up traces the lineage to 2004, when Stefan Esser published the first PHP memory-limit remote vulnerability, a bug considered serious enough that no public exploit was released and two commercial vendors built private ones. Calif then points at a later report on the PHP bug tracker. We pulled that record directly rather than take the summary on trust, and it is worth quoting accurately.

Sec Bug #78876, titled “Long variables in multipart/form-data cause OOM and temp files are not cleaned,” was submitted on 28 November 2019 at 11:07 UTC by a reporter listed as jr at coredu dot mp, against PHP 7.2.25, assigned to stas, last modified 11 May 2020, status Closed, carrying CVE-2019-11048. The reporter’s own description identifies an integer overflow in main/rfc1867.c during multipart upload handling that crashes PHP and leaves temporary files undeleted, and frames the consequence as “an easy to execute remote denial of service attack.” (Calif’s narrative places this report in 2020 and renders the reporter’s address with a .edu domain; the tracker says 2019 and .mp. Minor, but we correct what we can verify.)

The second encounter is the one that stings. Calif states that in 2024, an OSTIF and Quarkslab audit of PHP rediscovered the same OOM issue — and that because exploitation was not proven, the bug was not fixed. That is Calif’s account of the audit outcome, carried here as their attribution rather than something we reproduced from the audit report, but it is entirely consistent with the 2019 tracker entry: the condition was visible, it was understood as a crash-and-disk-fill problem, and it was triaged accordingly.

So the timeline of the condition is: seen in 2019, CVE’d as a denial of service, closed. Seen again in 2024 by paid auditors, not proven exploitable, left alone. Then, in Calif’s words about starting work in 2026: “We were not expecting to find anything critical — everyone and every lab had already done extensive AI assisted audits of this target.” A few days later they had an RCE chain.

What the models were actually used for

Wiz is specific about tooling and about which model did what. The team used Wiz Atlas, Google’s Gemini 4 Argon and OpenAI’s GPT‑5.6 Sol throughout, and singles out Gemini 4 Argon as having made, in their words, an invaluable contribution to finding the vulnerability, exploit development, attack detection and validation of the patch — four distinct jobs, only one of which is discovery. Raluca Ada Popa, Head of Gemini Security at Google DeepMind, is quoted in the Wiz post framing it as a defensive win. We have covered Argon’s positioning for defenders before, and Sol’s restricted-access history is part of the same story.

Wiz’s own explanation of the uplift is the most useful paragraph in the whole disclosure, because it is about adaptation, not insight. Memory-corruption exploits break when the PHP version, configuration or application behaviour shifts the heap; an attack that works on one deployment historically needed substantial manual rework for the next. With models in the loop, Wiz says, failures can be analysed and adjustments iterated automatically, “significantly lower[ing] the barrier to scaling attacks across different deployments.” Their summary line is that a single researcher completed in a week what previously would have taken a world-class team months.

Read that against the 2019 and 2024 outcomes and the mechanism becomes clear. Both earlier triages turned on the same question — can anyone actually weaponise this? — and both answered no, reasonably, given the cost of finding out. AI did not change the bug. It changed the price of answering that question, and a “not practically exploitable” verdict is only ever as good as the exploitation budget behind it. Every project sitting on a closed-as-DoS memory bug now holds a judgement that was priced in a market that no longer exists.

Four bugs, two CVEs, and the part that is application-agnostic

Wiz reported four exploitable instances, grouped by PHP into two CVEs, and states plainly that other tracked and likely untracked variants of the same pattern exist in the codebase — which is why the fix was written at the core rather than per-path. The four, in Wiz’s own technical terms:

  • Upload-progress unserializer use-after-free. Session decoding during upload-progress handling stores request-owned bookkeeping in BG(unserialize); a fatal allocation failure destroys the request heap while leaving that global published, so a later request on the same worker consumes attacker-reclaimed memory as live unserializer state. Demonstrated as pre-authentication RCE on WordPress, Drupal and Joomla.
  • Remote process-memory disclosure. Multipart parsing happens during request startup, before module initialisation; upload-progress handling can publish a session ID in PS(id), an OOM abort can leave that pointer dangling, and a later multipart request has PHP URL-encode the reclaimed heap contents into a PHPSESSID response cookie. Wiz notes this works even when the application never calls session_start(), which is what makes it genuinely application-agnostic.
  • Fatal-error backtrace use-after-free. EG(last_fatal_error_backtrace) survives the destruction of the request heap; a diagnostic emitted early in the next request follows the dangling pointer. Demonstrated as pre-auth RCE against Drupal.
  • OPcache type confusion. zend_accel_script_persist() advances the process-local CG(map_ptr_last) frontier before publishing the shared one; an allocation failure between those events leaves partially persisted objects pointing at slots the shared state still thinks are free, and another worker reusing a slot resolves stale metadata to a wrong-typed pointer. Cross-worker corruption, demonstrated as pre-auth RCE against WordPress.

The second item is the one defenders under-rate. An unauthenticated attacker reading live worker memory containing data from other people’s requests — passwords, tokens, API keys, certificates, per Wiz — does not need code execution to ruin you, and leaves a far quieter trace. This is the Heartbleed half of PHP2Shell, and it is the half that keeps paying out after you patch, because anything that sat in a worker’s memory before the update is potentially already gone.

Calif’s contribution sharpens the scope. They describe two general OOM/memory_limit fatal producers and three interruptible points in the interpreter, say the earliest affected path they found dates to PHP 5.4.0, and — the line to internalise — that the available paths vary by version and SAPI but are “always exploitable under default configurations.” Their confirmed pre-auth RCE list runs well past the three CMSes Wiz demonstrated: WordPress 7.1.2, Drupal 11.4.3, Joomla 6.1.4, MediaWiki 1.46.2, Roundcube 1.7.4, Magento 2.4.9, phpMyAdmin 5.2.3, Nextcloud 35.0.1, Laravel 13.11, Symfony 8.1 and WHMCS. If you were waiting to see whether your stack was “really” affected, that list is the answer.

OpenAI’s framing, and the claim worth holding loosely

OpenAI’s post is a process document as much as a research one. It says Calif identified a critical flaw using GPT‑5.6 Sol under the Patch the Planet initiative, with Wiz independently discovering and reporting both issues; it proposes a five-stage coordination framework for AI-found vulnerabilities in widely used software; it records engagement with CISA, the Office of the National Cyber Director and the White House’s Super Intelligence Force; it ships a PHP version checker as a Codex skill; and it commits $1 billion in subsidised Daybreak access for under-resourced defenders. It also states, candidly, that OpenAI is calibrating additional blocking classifiers for Daybreak while acknowledging that safeguards against misuse also block legitimate security work — a tradeoff this site has watched play out repeatedly, and a rare on-the-record admission that the dial has two bad directions.

One sentence should be held loosely: “To our knowledge, frontier AI found these vulnerabilities before attackers did, opening a Defender’s Window.” It is carefully hedged, and it may well be right. But Amazon Threat Intelligence recorded a PHP2Shell exploitation attempt against its MadPot honeypots on 17 October — four days before disclosure, while the embargo held — and says it remains unclear how that actor obtained exploit information. A defender’s window exists only for as long as the coordination holds, and this one leaked twice: once to a honeypot, once to a Hacker News post. The framework OpenAI proposes is the right shape; this instance is also a demonstration of its failure mode.

The other sentence worth marking is OpenAI’s forecast that similar findings will “increase sharply in the coming months.” Taken with Wiz’s economics argument, it is a capacity warning aimed at maintainers. PHP had a funded foundation, an ecosystem security team and two months of coordinated help from three well-resourced organisations, and still shipped under an exposed embargo. Most of the projects holding the next PHP2Shell have none of that.

What to do with this

  • Patch first; this analysis changes nothing about urgency. PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your vendor’s backport. Both researchers state the engine-level fix eliminates the variants; nothing at the application layer substitutes for it.
  • Re-open your “not exploitable” pile. The single most actionable lesson here is that a 2019 DoS triage and a 2024 audit both looked at this condition and stopped. Go back through memory-safety bugs your organisation closed as crash-only, unreachable, or impractical — especially those where the reasoning was cost of exploitation rather than absence of a primitive — and re-rank them. That verdict was priced against human effort.
  • Hunt the disclosure half, not just the execution half. Per Wiz’s detection guidance: unusual multipart requests followed by memory-limit errors or repeated HTTP 500s, unexpectedly large or malformed PHPSESSID response cookies, and unexplained PHP worker churn. These fire below the application layer, so your app logs will be thin — look at the web server and the workers. Treat any secret that lived in a pre-patch worker’s memory as potentially read.
  • Count your PHP, including the copies you do not administer. Appliances, management interfaces and embedded runtimes ship PHP you cannot apt upgrade. The Netherlands NCSC repository tracking affected software is the fastest public inventory aid, and the vendor-status question is now the long pole for most estates.
  • Do not generalise “AI found it” into “AI will find ours.” Three well-funded teams with frontier access, a named target and months of coordination produced this. The transferable part is the economics — cheaper exploitability proofs, on both sides — not a promise that your dependencies are being audited by someone friendly.

This is analysis of published research. We read the Wiz, Calif, OpenAI and PHP disclosures first-hand, and pulled PHP bug #78876 directly from bugs.php.net to verify the 2019 provenance, its CVE assignment and its denial-of-service framing. The 2024 OSTIF/Quarkslab audit outcome is Calif’s account, attributed and not independently reproduced. We did not write, run, or test any exploit, did not send malformed requests to any system, and did not attempt to reproduce the memory-disclosure or RCE chains. Model-attribution statements are the researchers’ own characterisations of their workflow.

Sources: