On October 20, 2026, two CVE identifiers leaked on social media. They belonged to two critical remote code execution bugs in PHP itself — not in WordPress, not in Laravel, not in any plugin. The PHP project moved its emergency release forward by one day. Patches landed October 21, 2026 at 14:00 UTC.

The short version: update PHP to 8.5.12, 8.4.27, 8.3.36, or 8.2.35, then restart every PHP worker. If you run an end-of-life branch, upgrade or take the backport from your distribution. Configuration tweaks reduce risk. They do not fix the bug.

Affected: every PHP version from 5.4 onward — around 69% of websites whose server-side language is known.

# Check what version your server actually serves (not just the CLI)
php -v
curl -sI https://your-site.example | grep -i '^server'
# Then confirm the package changelog, not just the version number
zgrep CVE-2026-109618 /usr/share/doc/php8.3-common/changelog.Debian.gz

If that command finds nothing and your PHP is below the fixed versions, you are exposed. Keep reading.


What Actually Happened

This was not a quiet patch Tuesday.

  • August 1, 2026 — Calif researcher Ryan Austin discovers the first flaw while auditing PHP's source with help from OpenAI's GPT-5.6 Sol model. Root cause traces back to an out-of-memory issue first spotted during PHP's 2024 external security audit.
  • August 11 — Calif reports an unconditional RCE to the PHP security team; OpenAI independently reports the same root cause the same day.
  • August 19–24 — Wiz Research, using its own Atlas tooling plus Gemini 4 Argon and GPT-5.6 Sol, independently finds the first vulnerability, confirms RCE against Drupal and WordPress, and reports to PHP's security team on August 24.
  • September 18 — OpenAI reports additional attack vectors.
  • October 20, ~15:00 UTC — Both CVE IDs leak on forums and social media, with a wrong CVSS score of 10.0 and a wrong release time. No technical details leak.
  • October 20, 19:30 UTC — PHP publishes an advance notice, pulling the release forward from its planned date.
  • October 21, 07:41 UTC — Chainguard publishes built images containing the fix, more than six hours before the coordinated release.
  • October 21, 07:43 UTC — Cloudflare reports early attack traffic.
  • October 21, 14:00 UTC — PHP releases fixed versions. The release had originally been scheduled for October 22.

Worth calling out: all three organizations involved — Calif, Wiz, and OpenAI — used AI models (GPT-5.6 Sol, Gemini 4 Argon) as part of the auditing process that surfaced these bugs. The underlying weakness had been sitting in PHP's source since version 5.4 (2012) and a PHP Foundation developer had flagged something suspicious in that same area back in 2024, but nobody had a concrete attack path. AI-assisted auditing found one. OpenAI used the moment to launch a "Patch the Planet" push, committing $1 billion in subsidized model access for defenders. Expect this pattern — AI tooling surfacing exploitable bugs in codebases that have been "safe enough" for over a decade — to show up more, not less.

The PHP Foundation was blunt about the delay in fixing the underlying issue: competing fixes each broke backward compatibility, added denial-of-service risk, or required coordinated changes across many third-party extensions. The security team works by consensus, and consensus stalled. That is a structural failure, and the Foundation says so in its own post.

Separately, Amazon Threat Intelligence observed a php2shell exploitation attempt against its MadPot honeypot network on October 17 — four days before public disclosure, from an IP tied to a commercial anonymization network. It is unclear how the attacker got exploit information.


The Two Bugs in Plain Language

PHP does not start a fresh process for every request. It reuses worker processes to stay fast. Both bugs corrupt the memory of a reused worker.

CVE-2026-109618 — Out-of-memory corruption

What it does: A request hits PHP's memory_limit at exactly the wrong moment. PHP bails out mid-operation and leaves internal request data half-initialized. Later cleanup code treats that garbage as valid and corrupts memory.

Analogy: A chef gets interrupted halfway through prep and leaves the knife on the counter. The next cook grabs it without looking.

Worst case: Apache with mod_php. The trigger fires before your application code runs, so no login, no plugin, no framework router, no WAF rule inside the app can stop it. Full RCE was demonstrated with default settings.

CVE-2026-109619 — Stale global state

What it does: A fatal error leaves global state pointing at memory that belonged to a previous request. The worker does not reset it properly. A later request handled by the same worker reads that freed memory — a use-after-free.

Analogy: A hotel reuses a room key. Guest A checks out, the lock is not rekeyed, and guest B's key opens a room still holding guest A's luggage.

Confirmed: use-after-free, worker crash, and RCE against a real-world application on Apache mod_php. Also confirmed on PHP-FPM through application-level code paths.

There is a data leak too

Researchers demonstrated unauthenticated disclosure of PHP worker memory. CVE-2026-109618's upload-progress handler can return freed worker memory to the client inside a PHPSESSID response cookie. That memory can contain passwords, session tokens, API keys, and TLS private keys from other requests. The handler runs before application code, so it works even when the app never calls session_start().

If you ran unpatched PHP on a shared worker pool, assume credentials that passed through it may have leaked.

Severity

CVE Title CVSS v4.0 Class
CVE-2026-109618 RCE via OOM corruption 9.2 Use of uninitialized memory, use-after-free
CVE-2026-109619 RCE via stale global state 9.2 Heap use-after-free, memory disclosure

Both are AV:N/AC:H/AT:P/PR:N/UI:N — network reachable, no privileges, no user interaction. Attack complexity is High because exploitation depends on allocator layout, build flags, and worker scheduling. That is the one piece of good news.


Affected Deployments

PHP considers every installation that serves web requests at risk:

  • Apache mod_php — highest priority. Demonstrated exploit runs before application code.
  • PHP-FPM — affected. FPM startup blocks one specific OOM path, but PHP validated session-lifecycle RCE against FPM under suitable application conditions.
  • php-cgi, FrankenPHP, LiteSpeed — affected.
  • Shared hosting — you probably cannot patch this yourself. Your provider must.

The vulnerable code dates to PHP 5.4.0, released in 2012.


Every PHP Framework and CMS Is Affected

This is the part people get wrong. The bug is in the interpreter, below your framework. No WordPress update, Laravel update, or plugin update fixes it. Patching the app while leaving PHP old changes nothing.

Calif confirmed pre-authentication RCE — no login required — against these specific versions:

Application Version tested by Calif
WordPress 7.1.2
Drupal 11.4.3
Joomla 6.1.4
MediaWiki 1.46.2
Magento 2 / Adobe Commerce 2.4.9
Laravel 13.11
Symfony 8.1
Nextcloud 35.0.1
Roundcube 1.7.4
phpMyAdmin 5.2.3
WHMCS —

Same engine-level exposure applies to everything else running on PHP 5.4+: CodeIgniter, CakePHP, Yii, Zend/Laminas, Slim, PrestaShop, Shopware, WooCommerce, OpenCart, Sylius, phpBB, Moodle, Matomo, ownCloud, SuiteCRM, Cacti, e107, and the long tail of custom PHP applications.

Two consequences worth stating plainly:

  1. WooCommerce stores are Magento/Shopware-class targets. Store code being clean means nothing here. Sansec's guidance to merchants was direct: update PHP, and if you do not manage the server, ask your host which build they run.
  2. Multi-tenant control panels need attention. cPanel/CloudLinux, Plesk, and DirectAdmin users should check panel changelogs for the CVE. cPanel on CloudLinux shipped fixes for ea-php52 through ea-php85.

Reality check on exploitation

Sansec's follow-up coverage walked back some of the worst-case framing, and it is worth quoting the substance rather than the panic:

  • Public PoCs do not work against a default PHP installation.
  • Most published exploits need the target application to already have a local file inclusion bug — a severe flaw on its own.
  • Nobody has shown a single request that works against any vulnerable server the way Log4Shell did.
  • Several Dutch sites went offline as a precaution. You do not need to take your site offline.

This is not a reason to wait. Amazon observed exploitation attempts before disclosure, and attack traffic continues. It is a reason to patch in the correct order instead of panicking.


Fix It: Update PHP

PHP branch Fixed version
PHP 8.5 8.5.12
PHP 8.4 8.4.27
PHP 8.3 8.3.36
PHP 8.2 8.2.35

Distribution packages may keep an older version number and still contain the backported fix. Check the advisory and the package changelog, not just php -v.

End-of-life branches

PHP 8.1 and earlier are outside upstream support. The PHP security team published minimal source backports for 7.4, 8.0, and 8.1. Get a fixed build from your vendor:

Environment Source Fixed versions
Debian, Ubuntu deb.sury.org / ppa:ondrej/php 5.6, 7.4, 8.0, 8.1
Ubuntu 22.04 Ubuntu security 8.1
Ubuntu 14.04–20.04 Ubuntu Pro (+ Legacy add-on) 7.4 / 7.2 / 7.0 / 5.5 by release
Debian 9–11 Freexian ELTS (paid) 7.4 / 7.3 / 7.0
RHEL, AlmaLinux, Rocky, Fedora Remi's repository 7.4, 8.0, 8.1
AlmaLinux 8–10 AlmaLinux every PHP stream shipped
RHEL 8, 9 Red Hat some streams, others in progress
cPanel on CloudLinux CloudLinux ea-php52 to ea-php85
Any TuxCare ELS / ZendPHP LTS (paid) 5.x to 8.1

The official Docker php image gets no fix for 8.1 or older. Build from the php-src security branches, or upgrade.

Restart every worker

Installing the package is step one. Code already loaded in a running worker stays vulnerable until that worker restarts.

# Debian/Ubuntu with FPM — adjust version
sudo apt update && sudo apt install --only-upgrade php8.3-fpm php8.3-cli
sudo systemctl restart php8.3-fpm

# Apache with mod_php
sudo systemctl restart apache2

# Containers: rebuild the image, redeploy, do not just restart
docker compose build --pull app && docker compose up -d app

Then verify the fix is really in place:

php -v
php -r 'echo PHP_VERSION, PHP_EOL;'
# Debian/Ubuntu
zgrep CVE-2026-109618 /usr/share/doc/php8.3-common/changelog.Debian.gz
# RHEL family (Remi parallel packages: php83-php-common)
rpm -q --changelog php-common | grep CVE-2026-109618

For a web request, check the PHP version served by the web server, not the CLI. Parallel installs are common: php -v may report a patched binary while Apache loads a different, older module.


Temporary Mitigations While You Schedule the Patch

These are partial. PHP says updating is the only complete fix.

1. Block multipart/form-data at the web server

Every known trigger is a multipart/form-data request. PHP parses that body before your application runs. Reject it at the edge.

nginx — add inside every server block that passes requests to PHP:

if ($http_content_type ~* "multipart/form-data") {
    return 403;
}
sudo nginx -t && sudo systemctl reload nginx

Apache — add inside every <VirtualHost> that serves PHP:

RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart/form-data [NC]
RewriteRule ^ - [F]

This breaks file uploads, including product images in admin panels. Some carts and checkout forms submit as multipart, so place a test order after adding the rule. Remove the rule once PHP is patched.

2. PHP settings

Calif published two partial mitigations. PHP core developer Gina Peter Banyard warned that disabling session upload progress alone is not enough — combine these with the multipart block.

For Apache mod_php, in php.ini or a drop-in under conf.d:

session.upload_progress.enabled = 0
memory_limit = -1
fatal_error_backtraces = 0

For PHP-FPM, set them in every pool file — FPM reads pool config, not the CLI php.ini:

; /etc/php/8.3/fpm/pool.d/www.conf
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[memory_limit] = -1
php_admin_value[fatal_error_backtraces] = 0
sudo systemctl reload php8.3-fpm

Then confirm the values from a PHP-FPM-served request. A CLI check proves nothing.

Warnings on memory_limit = -1: you are removing PHP's per-request memory cap. One request can now consume all server memory. Watch memory use, keep a container or cgroup limit as an availability boundary, and restore a finite limit after patching. Do not use RLIMIT_AS or RLIMIT_DATA — they can force allocation failures that trigger the vulnerable path.

3. Reduce request surface

  • Lower post_max_size to 8M without uploads, or 32M with uploads. Keep upload_max_filesize below it.
  • Lower max_input_nesting_level from its default 64.
  • Bound max_file_uploads, multipart parts, and header counts at the proxy.
  • For FPM, pm.max_requests = 1 limits each worker to one request. Only if the performance cost is acceptable.
  • Remove invalid or deprecated per-request INI settings (php_value in Apache config or .htaccess). They generate diagnostics before initialization.

4. Edge protection is a stopgap only

Cloudflare deployed WAF rules for the known exploit vectors, available to all plans including free. That only covers traffic routed through Cloudflare. It is a stopgap, not a fix.


If You Cannot Patch Today

  • Assign an owner and a deadline to every host still on old PHP. Unassigned means unpatched.
  • Take truly unpatchable internet-facing PHP systems offline. CISA recommended exactly that for unsupported branches.
  • Restrict public access to admin panels, /phpmyadmin, and staging hosts.
  • Rotate secrets that passed through any unpatched shared worker: session keys, API tokens, database passwords, TLS private keys.
  • Start incident review from October 17, not October 21. Amazon observed attempts on that date.

Detection and Verification Checklist

  1. Find every PHP install — parallel branches, containers, hosting panel packages, appliance-bundled copies, and that forgotten staging VM.
  2. Update the right package, binary, or image — check the vendor changelog for the CVE, not only the version string.
  3. Restart or replace every worker — then verify the running process uses the new build.
  4. Re-check the mitigation settings — remove the multipart block and restore a finite memory_limit after patching.
  5. Test under memory pressure — the patched runtime can terminate a worker immediately at its hard memory threshold, bypassing normal shutdown handlers.
  6. Re-scan with your vulnerability scanner and validate external exposure.

Why This One Matters Beyond the Patch

PHP runs a large share of the public web: government services, banks, shops, media sites. The security work on the interpreter itself is still done by a small group of foundation-funded developers and volunteers.

The root cause was found in 2024. The fix stalled for two years over compatibility trade-offs. When the full impact became clear in August 2026, the Foundation's team worked through weekends to ship fixes across every supported branch. The Foundation's own conclusion is worth repeating: tools now find bugs faster than anyone can fix them, and deciding the right fix still takes engineers who know the whole codebase. There are too few of them.

If your business runs on PHP, sponsoring the PHP Foundation is the most direct way to reduce the chance that the next one of these stalls for two years.


Timeline

Date (UTC) Event
2026-08-01 Calif finds the first bug, with help from GPT-5.6 Sol
2026-08-11 Calif reports the first bug, coordinated disclosure starts
2026-08-19 Wiz independently finds the first vulnerability using Atlas, Gemini 4 Argon, and GPT-5.6 Sol
2026-08-24 Wiz Research reports to the PHP security team
2026-09-18 OpenAI reports further vectors
2026-10-17 Amazon MadPot honeypot records an exploitation attempt
2026-10-20 15:00 CVE IDs leak with wrong CVSS (10.0) and wrong release time
2026-10-20 19:30 PHP publishes advance notice
2026-10-21 07:41 Chainguard breaks embargo with prebuilt images
2026-10-21 07:43 Cloudflare reports early attacks
2026-10-21 14:00 PHP releases 8.5.12, 8.4.27, 8.3.36, 8.2.35

References