Critical alert · PHP engine

  • CVSS 9.2
  • Unauthenticated RCE
  • Fixed Oct 21, 2026

PHP2Shell: two critical vulnerabilities in the PHP engine.

CVE-2026-109618 and CVE-2026-109619 allow remote code execution, without authentication, on any server that serves PHP pages. Here is how to tell in two minutes whether you are affected, and how to fix it.

Updated October 22, 2026 at 10:30 a.m. CEST · Sources: php.net, CERT-FR, CISA

Read with an AI .md version

The essentials in 60 seconds

The engine is affected, not your code.

Both vulnerabilities are in the PHP interpreter itself. Any server that handles web requests with an unpatched version is exposed.

Updating your CMS is not enough.

Keeping WordPress, Symfony, Laravel or your Composer packages up to date changes nothing: it's the server's PHP binary that has to be replaced.

Only one action really fixes it.

Upgrade to 8.2.35, 8.3.36, 8.4.27 or 8.5.12, then restart the PHP processes. Workarounds only block some of the attacks.

What's happening

Two memory bugs at the heart of the interpreter

They trigger while an HTTP request is being processed, before your application even runs.

CVE-2026-109618 · CVSS 9.2

Memory corruption when memory runs out

When an allocation fails while a request is being parsed, PHP aborts processing and leaves structures half-initialized. The end-of-request cleanup reuses them: an attacker can take control of them with a crafted request.

Apache with mod_php is the most exposed setup.

CVE-2026-109619 · CVSS 9.2

Memory freed, then reused between two requests

A single PHP process handles several requests in a row. After a fatal error, an internal state still points to freed memory, which the next request reads again. File upload progress tracking (session.upload_progress, on by default) is the known attack path.

Affects PHP-FPM, mod_php, FrankenPHP and LiteSpeed.

Who is affected

Your PHP branch, and what to do

Support dates for each branch come from the official php.net schedule. A branch past its end of life no longer gets fixed releases.

BranchVulnerableFixed inOfficial supportWhat to do
8.5 8.5.0 to 8.5.11 8.5.12 Active · security → 2029 Update to 8.5.12
8.4 8.4.0 to 8.4.26 8.4.27 Active · security → 2028 Update to 8.4.27
8.3 8.3.0 to 8.3.35 8.3.36 Security only → 2027 Update to 8.3.36
8.2 8.2.0 to 8.2.34 8.2.35 Ends Dec 31, 2026 Patch today, migrate before Dec 31
8.1 and earlier All none Ended Dec 31, 2025 Your distribution's patched package, or migrate to 8.3+

PHP 8.2 reaches end of life in ten weeks

Patch to 8.2.35 today, then plan the migration to 8.3 or 8.4. After December 31, 2026, a new vulnerability in the engine will leave 8.2 servers without a fix, as 8.1 is today.

Check in 2 minutes

Look in two places: the repository and the server

The repository says which PHP version the project expects. The server says which one actually runs. Both matter.

Where to check

In your repositories: composer.json and composer.lock

In the repository · declared version
$ grep -E '"php"' composer.json
  "php": "^8.1"

$ composer show --platform | grep -E "^php "
php   8.1.29   The PHP interpreter
What it means
"php": "^8.1"  → the project accepts 8.1: branch past end of life
"php": "^8.2"  → patch to 8.2.35, migrate before Dec 31, 2026
"php": "^8.3"  → patch to 8.3.36 or later

On your servers: php -v, PHP-FPM, Apache, Docker

On the server
$ php -v
$ ps aux | grep -E 'php-fpm|lsphp'

On a WordPress site: Tools › Site Health

On WordPress
Tools › Site Health › Info › Server

The “On your servers” and “WordPress” commands appear when you click step 2 or 3.

What LibWatch does for you

All your PHP projects checked at once, and monitored every night.

  • Finds the PHP version declared by each repository and each WordPress site, and matches it against known vulnerabilities and end-of-life dates.
  • Includes CERT-FR alerts on PHP: an affected exact PHP version (8.2.30, not ^8.2) is flagged by the following night at the latest.
  • Rechecks everything every night, even projects nobody touches, and notifies the team by email, Slack, Zulip or webhook.

Its limit: LibWatch sees the version declared in the repository, not necessarily the one installed on your servers. Also check php -v in production.

Your code stays with you: LibWatch reads your dependency files and only keeps the list of your packages and their versions. How it works →

Fix

Three steps, and the second is the one people forget

Only updating PHP fixes both vulnerabilities. Keep your access and error logs: exploitation attempts were seen as early as October 17.

Update PHP, or rebuild your Docker images

Updating the host doesn't fix the PHP that runs inside a container: rebuild the image from a patched base.

On Debian / Ubuntu
$ sudo apt update && sudo apt install --only-upgrade 'php*'

# Docker: start again from a patched base image
$ docker build --pull --no-cache -t mon-app:corrigee .

Restart every PHP process

Without a restart, the old vulnerable version stays loaded in memory, even if the package on disk is up to date.

Restart and check
$ sudo systemctl restart php8.3-fpm
$ sudo systemctl restart apache2

# the start time must be later than the update
$ ps -eo pid,lstart,cmd | grep -E 'php-fpm|apache2'

Check the version actually served

Check the version seen by a real web request, not only by the command line: the two can differ.

Temporary workarounds

If you can't patch within the hour

Blocks

Turn off upload progress tracking

  • — The known attack paths of CVE-2026-109619.
  • — File uploads keep working normally.
  • — Takes effect only once the PHP processes have restarted.
php.ini
session.upload_progress.enabled = Off

Doesn't block

What it leaves open

  • — CVE-2026-109618, the memory corruption when memory runs out.
  • — Other possible paths to the second vulnerability.
  • — WAF rules (Cloudflare, AWS, Azure…) reduce the risk but don't replace the update.

Only updating PHP fixes it

The PHP maintainers, CERT-FR and CISA all say so: a workaround buys time, nothing more.

Timeline

Five days, from the first attack to this page

Oct 17, 2026

First exploitation attempt

Observed by Amazon Threat Intelligence, four days before the fix.

Oct 20, 2026

Leak and early announcement

A since-deleted post announced a CVSS score of 10, later denied: the official score is 9.2.

Oct 21, 2026

Fixes and alerts

PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35. CERT-FR (ALE-014) and CISA issue alerts. Cloudflare deploys WAF rules.

Oct 22, 2026

This page

Updated with every new fact: addition to the KEV catalog, EPSS score, distribution packages.

Frequently asked questions

What people have been asking us since October 21

Another question? Write to us →
Is updating WordPress, Symfony or Laravel enough?
No. The vulnerability is in the server's PHP engine, not in your CMS or your Composer packages. Until PHP is on 8.2.35, 8.3.36, 8.4.27 or 8.5.12 and its processes have restarted, the site stays exposed.
I'm on shared hosting or managed WordPress: what should I do?
Your host is the one who updates PHP. Check the version served in Tools › Site Health › Info › Server: if it's older than 8.2.35, 8.3.36, 8.4.27 or 8.5.12, ask your host to update it, or pick a patched version in your hosting dashboard if it lets you.
Why a score of 9.2 and not 10, as first announced?
On October 20, 2026, a since-deleted post announced a CVSS score of 10. It was later denied: the official score is 9.2 (CVSS v4.0), for each of the two vulnerabilities.
How can I tell whether my server was attacked before the update?
Keep your access and error logs: exploitation attempts were seen as early as October 17, four days before the fix. The update closes the vulnerabilities but doesn't undo an earlier intrusion: if in doubt, have those logs analyzed.
Does LibWatch need access to my code to detect the vulnerability?
No. LibWatch reads your dependency files and only keeps the list of your packages and their versions. Its limit: LibWatch sees the version declared in the repository, not necessarily the one installed on your servers. Also check php -v in production.