AnalysisOct 23, 20269 min read5 sources

The php2shell fix is a version number, and the tools people will use to check for it can't see it

In one minute

The fix for php2shell is a runtime upgrade. The tools people will reach for first, an edge WAF and a header-based checker, both have gaps, and the most careful operators fall into them most often.

Summary

On October 21, 2026, PHP disclosed two engine-level RCE flaws, CVE-2026-109618 and CVE-2026-109619, together called php2shell. They affect PHP 5.4 and later in default configurations, and working exploits are public. The only real fix is upgrading the runtime to 8.2.35, 8.3.36, 8.4.27 or 8.5.12. Vercel and Cloudflare had WAF rules running before disclosure, and OpenAI published a header-based checker. Read together, the stories show a gap the coverage skips over. Neither of these quick responses can reliably tell you whether a given server is patched.

What happened

According to Vercel's bulletin, specially crafted HTTP requests can lead to remote code execution, leak data from other requests, or cause denial of service. WordPress, Drupal, Laravel and Magento are all affected when they run on a vulnerable runtime. Vercel says that changing application code or plugins does not fix the problem. PHP 8.1 and earlier no longer get regular upstream updates. Vercel's free WAF rules cover PHP functions hosted on Vercel and traffic proxied or rewritten to external PHP backends. Vercel says the rules do not cover requests that bypass its network and are not a substitute for patching.

Simon Willison's report, quoting the PHP Foundation, gives a CVSS score of 9.2, not the 10.0 that circulated early. The CVE IDs began circulating around 15:00 UTC on October 20. A security firm mistakenly published a proof-of-concept video, and copies of it helped others build their own PoCs. PHP moved its pre-announcement to 19:30 UTC that day and brought the release forward from October 22 to October 21 at 14:00 UTC. Wiz says it found the first issue on August 19 using Wiz Atlas, Gemini 4 Argon and GPT-5.6 Sol, and reported it to PHP on August 24.

OpenAI's php2shell-checker (Apache-2.0) has two parts. One reads the X-Powered-By and Server headers. The other runs php -v on a host where you have access. Both compare the reported version against cutoffs dated October 20 that are built into the tool. The checker sends no exploit traffic and does not follow redirects. It returns UNKNOWN when headers are hidden. OpenAI warns that distribution backports can differ from upstream version strings.

What the archive adds

The archive includes Wiz's write-up, titled "PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet." It says the flaws sit at the engine level, so they can affect any PHP application running a vulnerable version, and they execute below the application layer, so application logs may contain little context. Wiz says the WordPress, Drupal and Joomla attack chains are examples, not the full list. Until systems are patched, it tells defenders to watch for unusual multipart requests followed by memory-limit errors or repeated HTTP 500 responses. According to Huntress, the CVE details and a PoC video leaked on October 20, before patches existed. According to Cloudflare, it saw attack traffic during the leak and saw attackers changing their payloads to get around protections. The Cloudflare excerpt does not say when or how Cloudflare learned of the flaws. No source in the pack says how Vercel was notified.

Trend signal

This incident shows a pattern that is likely to repeat: the fastest responses to a runtime-level bug come from intermediaries, while the actual fix stays slow and stays with the operator. Edge platforms can push one rule to every site behind them. AI labs can turn an advisory into a single command within hours. Neither changes the binary running on the server. Disclosure timing is also shaky. In this case a leaked ID and a stray video forced the release a day early. A second thread is that Wiz names two frontier models as part of the discovery. Our inference is that finding engine-level bugs is getting cheaper, which would mean more runtime-level advisories, each followed by the same rush to scan.

Why now

1) Wiz says it found the engine-level flaws, which reach back to PHP 5.4, with help from Wiz Atlas, Gemini 4 Argon and GPT-5.6 Sol (Wiz post, Willison report). 2) According to Huntress and Willison, the CVE IDs and a mistakenly published PoC video circulated on October 20 before any fix existed, and PHP moved its release up a day. 3) Edge platforms answered with signature rules: Vercel had rules live before disclosure, and Cloudflare says it saw attack traffic during the leak and attackers changing payloads (d3). 4) PHP 8.1 and earlier no longer get regular upstream updates, so part of the affected base has no simple patch path, and fixed status for distro builds depends on backports, not version strings (OpenAI checker README).

Connections to other events

The common reading is that the WAF rules and the checker together mean you are covered while you schedule the upgrade. We think that reading is wrong in three specific ways.

First, the checker is least useful for the most careful operators. Hiding X-Powered-By is standard hardening. On those sites the tool returns UNKNOWN, which an inventory spreadsheet can easily record as "no finding." Distribution builds are another problem. Debian, Ubuntu and RHEL often fix vulnerabilities by backporting patches while keeping an older upstream version string. OpenAI says this can make the version comparison wrong, so a patched distro build may be flagged VULNERABLE and an unpatched custom build may pass. Running php -v on the host does not solve this for distro packages either, because it reports the same upstream string. Whether a host is patched depends on the specific package and release, not on the version number.

Second, the WAF only protects traffic that passes through it. Vercel says its rules miss requests that bypass its network. A site whose origin IP is reachable directly, which is common after a DNS migration or on leftover staging hosts, gets no protection.

Third, attackers are already working around the signatures. Cloudflare says payloads were being changed during the leak window. Wiz says the bug runs below the application layer and leaves little in the logs. Together, this suggests a WAF bypass would be hard to notice.

So the cluster reverses who looks safe. A hardened, CDN-fronted site on a distro build can look "unknown, protected" while still being exploitable through its origin. A sloppy site that advertises its PHP version is easier to triage correctly.

Why it matters

For operators, the useful output is a list of hosts with package-level patch status, checked against your distribution's security tracker. A URL scan does not give you that. Use the checker's UNKNOWN as a to-do item, never as a pass. For anyone fronting PHP with a CDN, this week is the time to lock origins so they accept traffic only from the edge provider. Otherwise the free WAF covers only part of your exposure. Hosting buyers who do not control the runtime should ask their provider for the exact package build they are on, not a general statement that it has been "patched." For tool builders, there is a clear opening: checkers that read distribution package changelogs and advisory feeds, not just version strings. That is harder to package as a single skill, which is likely why the first tool to ship did not do it.

What happens next

  • CISA adds at least one of CVE-2026-109618 or CVE-2026-109619 to its Known Exploited Vulnerabilities catalog. (3 months, 75%). Watch for: A KEV entry naming either CVE with a remediation due date.
  • A security vendor publishes a report attributing a mass-compromise campaign against WordPress, Drupal or Magento sites to php2shell, including hosts reached by bypassing a CDN or WAF. (3 months, 45%). Watch for: An incident write-up from a firm such as Huntress, Wiz or Cloudflare with host counts tied to these CVEs and mention of direct-to-origin or WAF-evading requests.
  • OpenAI's php2shell-checker or a widely used fork adds package-manager or distribution-advisory checks to handle backports, beyond header and php -v comparison. (6 months, 35%). Watch for: A commit or release in the repository that queries dpkg/rpm or a distribution security tracker.

Limits and uncertainty

No source counts compromised systems or measures attack volume, and Vercel says its bulletin does not establish either. Wiz's "70% of the Internet" appears in its headline, and our excerpt does not explain how it was calculated. We do not know how well the WAF rules hold up against changed payloads, how many origins can be reached directly, or how quickly distributions shipped backports. If most hosts take patched packages through automatic updates, the checker's errors matter less in practice. We also do not know how Cloudflare and Vercel learned of the flaws before disclosure. Cloudflare seeing traffic during the leak fits a reaction to the leak just as well as a private notice. A separate Vercel AI Gateway report in the cluster describes falling token prices and growing open-weight share. Any link from that to cheaper vulnerability hunting is our speculation, and those figures cover gateway traffic only.

Skill to build now

Practise checking patch status at the package level. This week, write a script that connects to each PHP host and records the installed php package version and its changelog entry for these CVEs. Run OpenAI's checker against the same hosts from outside and compare. Every host that comes back UNKNOWN, or that the checker flags VULNERABLE while the package changelog shows the fix, is a place where a scan alone would have misled you. Add one more check: try to reach each origin directly, bypassing the CDN, to see which hosts the WAF never sees.

Reader takeaway

Today, list every host running PHP and record the installed package version from the system package manager, not from headers or php -v. Check each one against your distribution's security advisory or the upstream fixed releases (8.2.35, 8.3.36, 8.4.27, 8.5.12). Treat UNKNOWN and anything on 8.1 or earlier as exposed. Then restrict each origin to accept traffic only from your CDN's IP ranges, so the WAF rules actually see every request until the upgrade lands.

Open question

Edge WAF rules arrived before or alongside disclosure, and the first triage tool reads only headers. Does that kind of fast response actually speed up patching, or does it give operators a reason to put off the slow runtime upgrade that is the only real fix?

Evidence / sources

  1. 1vercel.com/kb/bulletin/php2shell-security-bulletin
  2. 2simonwillison.net/2026/Oct/21/php-security-release
  3. 3github.com/openai/php2shell-checker
  4. 4vercel.com/blog/ai-gateway-production-index-october-2026
  5. 5wiz.io/blog/php2shell-php-rce
All Analysis

Next reads

Read next

Open the graph
  1. 01topicToolsExplore the tools topic hub.
  2. 02archiveAnalysisOpen the latest authorial analysis.
  3. 03source ledgerSource LedgerInspect the public source evidence graph.
Who read this page?Machine requests, hidden until opened

Loading the privacy-safe route aggregate...

Open the JSON contract