PHP2Shell: The PHP Bug That Lets Anyone Run Code on Your Server (Patch Now)

Two critical PHP bugs, CVE-2026-109618 and CVE-2026-109619, give unauthenticated attackers code execution on every SAPI that serves HTTP. Here's how to check your servers, patch to 8.5.12/8.4.27/8.3.36/8.2.35, and what the workarounds really cover.

Ashley Innocent

Ashley Innocent

23 October 2026

PHP2Shell: The PHP Bug That Lets Anyone Run Code on Your Server (Patch Now)

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

On October 21, 2026, the PHP project shipped emergency releases for two critical bugs that let an unauthenticated attacker run code on a web server. The pair is tracked as CVE-2026-109618 and CVE-2026-109619 and goes by the name PHP2Shell. Both score 9.2 on CVSS v4.0, both hit every PHP setup that serves HTTP, and Amazon’s honeypots logged exploitation attempts on October 17, four days before the patch existed.

PHP runs on 69.3% of websites whose server-side language is known (W3Techs). If you run a PHP API, a Laravel or Symfony backend, a WordPress site, or a container image with PHP baked in, this one is yours.

This guide covers what the bugs do, which versions are affected, how to check your servers, what the mitigations really buy you, and how to prove your API still works after you patch.

button

TL;DR

Question Answer
What is it? Two memory-safety bugs in PHP’s request handling, chained into remote code execution
CVEs CVE-2026-109618 (out-of-memory corruption), CVE-2026-109619 (stale state, use-after-free)
Severity CVSS v4.0 9.2 each (early leaked IDs said 10.0; PHP says that was wrong)
Auth needed? No
Affected Every SAPI that serves HTTP: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, LiteSpeed
Fixed versions 8.5.12, 8.4.27, 8.3.36, 8.2.35
PHP 8.1 and older No official release; minimal source backports for 7.4, 8.0, 8.1; 5.4 to 7.3 get nothing
Exploited? Attempts seen from October 17 (Amazon), early attacks reported by Cloudflare
Fix Upgrade, restart every worker. Workarounds reduce risk but don’t close it

What PHP2Shell actually is

Both bugs share one root cause: PHP can leave its memory in a broken state when a request ends abnormally, and the cleanup code then trusts that broken state.

CVE-2026-109618: out-of-memory corruption during request startup. When PHP parses form data into $_POST, the Zend engine’s hash table code bumps its entry counter before it allocates the new key. Datadog’s analysis traces it to _zend_hash_str_add_or_update_i() in zend_hash.c. If that allocation blows past memory_limit, PHP throws a fatal error and abandons the insert. The counter now includes a bucket that was never set up. At shutdown, PHP destroys $_POST and treats every counted bucket as real.

The part that should worry API teams: this happens while PHP is still parsing the request body, before a single line of your code runs. Your auth middleware, your rate limiter and your input validation never see the request. Datadog reproduced it with a plain application/x-www-form-urlencoded body, not a file upload.

CVE-2026-109619: stale global state across requests. PHP keeps some worker-wide state that points at per-request memory. If a fatal error interrupts the reset of that state, or a late shutdown diagnostic recreates it after cleanup, the next request on the same worker reads freed memory. PHP confirmed two paths:

The PHP security team rates mod_php as the highest risk, since the demonstrated exploit fires from one unauthenticated request before any application code loads.

Who found it (and why AI is in the headlines)

The bugs date back to code introduced in PHP 5.4.0, so they sat in the codebase for over a decade. The PHP Foundation credited Calif, OpenAI and Wiz.

Reporting from Decrypt and The Next Web says Calif researcher Ryan Austin found the flaws in August during a source audit assisted by OpenAI’s GPT-5.6 Sol. OpenAI says its own team found a fuller version in September as part of its “Patch the Planet” work. Wiz says it found both bugs on its own using Gemini 4 Argon, Wiz Atlas and GPT-5.6 Sol. The credit is disputed; the takeaway isn’t. AI-assisted audits are now finding decade-old memory bugs in core infrastructure, and attackers have the same models.

Timeline: why the patch came a day early

Date (2026) What happened
August to September Calif, OpenAI and Wiz report the bugs privately
Oct 17 Amazon’s MadPot honeypot records an exploitation attempt
Oct 20 CVE IDs leak on Hacker News and social media; PHP posts an advance notice; CERT-EU issues advisory 2026-018
Oct 21, 14:00 UTC PHP ships fixes, moved up from Oct 22 after the leak; CISA publishes an alert; Cloudflare reports early attacks
Oct 22 Neither CVE is in CISA’s KEV catalog yet

Amazon advises investigating from October 17 (Tenable’s FAQ tracks the full timeline), not the disclosure date. At release, the PHP team said it inspected the proof-of-concept code that appeared after the leak and found no working exploit. watchTowr has since said it reproduced both bugs. Treat any “PoC” repo you find as suspect: unverified exploit code often ships malware.

Are you affected? Check in five minutes

1. Check the runtime that serves traffic, not your laptop. The CLI binary can differ from the FPM or Apache module in version and config.

# On the server or inside the running container
php -v
php-fpm -v
# Apache mod_php: check the loaded module version
apachectl -M 2>/dev/null | grep -i php

Or expose it once from a protected route and remove it after:

<?php echo PHP_VERSION, ' ', PHP_SAPI;

2. Compare against the fixed versions.

Branch Vulnerable Fixed in
8.5 < 8.5.12 8.5.12
8.4 < 8.4.27 8.4.27
8.3 < 8.3.36 8.3.36
8.2 < 8.2.35 8.2.35
7.4 to 8.1 All Source backports only, or vendor LTS
5.4 to 7.3 All No fix

Debian, Ubuntu, Red Hat and other distros often backport fixes without changing the upstream version string. If php -v shows an older number, read your distro’s advisory before panicking.

3. Inventory the hidden PHP. Containers built FROM php:8.3-fpm months ago, vendor appliances, self-compiled builds, admin panels on forgotten subdomains. Cisco has already opened an advisory to check its own product line. Shodan counts over 1.9 million internet-facing PHP hosts; one researcher estimates 1.3 million or more may be vulnerable.

How to patch

# Debian / Ubuntu (Ondřej Surý PPA or distro packages)
sudo apt update && sudo apt install --only-upgrade 'php8.*'

# RHEL / Rocky / Alma with Remi
sudo dnf upgrade 'php*'

# Official Docker image: rebuild on a fixed tag
docker pull php:8.4.27-fpm
docker build --pull -t my-api:patched .

Then do the step most teams forget: restart or replace every PHP worker. A running FPM pool keeps the old binary in memory. Restart php-fpm, reload Apache, and roll every container. CVE-2026-109619 is about state that lives across requests inside a worker, so an unrestarted worker is still vulnerable.

On 8.1 or older, you have three options: a vendor LTS package, building from PHP’s source backport, or upgrading to 8.2+. CISA recommends taking unpatchable PHP systems offline, and the UK NCSC and FBI said the same.

Mitigations if you can’t patch today

These buy time. Gina Peter Banyard of the PHP core team told BleepingComputer no mitigation fully blocks the attacks.

For CVE-2026-109618:

For CVE-2026-109619:

At the edge: Cloudflare deployed WAF rules for known vectors on every plan, including free. Its CTO called them temporary.

After any php.ini change, restart every worker or it doesn’t take effect.

Signs you were already hit

Datadog’s detection guidance boils down to four signals:

Don’t trust status codes. Datadog’s refined exploit returned HTTP 200 and the worker kept running. Search logs back to October 17.

Prove your API still works after the patch: let your agent run it

Patching PHP in production under pressure is how you find out a minor version bump changed something. Before and after you roll the fix, run your API test suite against staging, and let your coding agent do it with Apidog CLI.

Setup (once):

npm install -g apidog-cli
apidog auth login --with-token <your-access-token>
apidog test-suite list --project <projectId>

One prompt to Claude Code, Codex or Cursor:

We just upgraded PHP to 8.4.27 on staging for PHP2Shell. Use the Apidog CLI to run our regression test suite against the staging environment, write HTML and JUnit reports, and summarize any failing endpoints. Then confirm a POST with a body above our nginx client_max_body_size gets rejected with 413 at the proxy instead of reaching PHP.

What the agent runs:

apidog test-suite run <testSuiteId> --project <projectId> -e <stagingEnvId>

apidog run --test-suite <testSuiteId> --project <projectId> -e <stagingEnvId> \
  -r cli,html,junit --out-dir ./php2shell-reports --upload-report

-r picks the reporters, --out-dir sets where reports land, and --upload-report pushes a summary you can open in the Apidog app. Add --notification-failed-event <targetId> to ping your team only when something breaks. Drop the same apidog run line into CI so every rebuilt PHP image gets tested before it ships. The Claude Code setup guide and the CI/CD pipeline walkthrough cover both in detail.

Run the suite once on the old version to get a baseline, once after the upgrade, and diff. If a test you never expected to fail does, you’ll know before your users do. Download Apidog to build and manage the suites the CLI runs.

FAQ

Is PHP2Shell being exploited? Amazon saw attempts from October 17 and says it’s now broadly exploited; Cloudflare and watchTowr report attacks too. CISA hadn’t confirmed exploitation as of October 22.

Does my framework protect me? No. CVE-2026-109618 fires while PHP parses the body, before Laravel, Symfony or WordPress loads.

I’m on shared hosting. What do I do? Check your host’s status page. SiteGround and others say they’ve patched. If yours hasn’t said anything, ask.

Is session.upload_progress.enabled=0 enough? No. It covers one path of one CVE. Patch.

Do I need to rotate secrets? CVE-2026-109619 allows memory disclosure. If logs show signs of compromise since October 17, rotate database passwords, API keys and session secrets the PHP process could read.

The bottom line

Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Restart every worker. Find the PHP you forgot about. Check logs back to October 17. Then run your API tests so the fix doesn’t become the next outage. If your PHP is on 8.1 or older, this is the week to finally move off it.

Explore more

Gemini 4 Argon Ships to Defenders Without Cyber Guardrails: What It Means for the APIs You Run

Gemini 4 Argon Ships to Defenders Without Cyber Guardrails: What It Means for the APIs You Run

Google released Gemini 4 Argon without cyber guardrails to Fairwind defenders, and since October 13 any team with a paid Gemini API key can call gemini-4-argon. Here are the cyber numbers, both access routes, Google's safeguards, and the API checks to schedule now.

15 October 2026

What Is the OpenAI Decisions API?

What Is the OpenAI Decisions API?

The OpenAI Decisions API returns typed answers (predicate, choice, score) from GPT-6 Luna at $0.10 per 1M input tokens. Anatomy, pricing, when to use it.

10 October 2026

OpenAI Decisions API vs Responses API

OpenAI Decisions API vs Responses API

Decisions API vs Responses API: one ticket routed both ways, what each returns, input-only vs output billing with the math, and a feature matrix.

10 October 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

PHP2Shell: The PHP Bug That Lets Anyone Run Code on Your Server (Patch Now)