# PHP2Shell: two critical vulnerabilities in the PHP engine.

Source: https://libwatch.com/en/cve/php2shell

Critical alert · PHP engine

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

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.

[Check my projects](https://app.libwatch.com/users/sign_up?source=cve_php2shell)

[See the commands](#verifier)

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

## Fact sheet

As of Oct 22, 2026 · 10:30 a.m. CEST

CVE CVE-2026-109618
CVE-2026-109619

Severity CVSS v4.0 9.2 · critical

Impact Remote code execution, without authentication

Affects PHP-FPM, mod\_php, php-cgi, FrankenPHP, LiteSpeed

Fixed in 8.5.12 · 8.4.27 · 8.3.36 · 8.2.35

Exploitation Attempt observed as early as Oct 17

Alerts CERTFR-2026-ALE-014 · CISA

## 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.

| Branch | Vulnerable | Fixed in | Official support | What 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.

### 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
```

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.

[Check my projects](https://app.libwatch.com/users/sign_up?source=cve_php2shell)

[Or test a composer.lock without an account →](/en/tools/composer-check)

Your code stays with you: LibWatch reads your dependency files and only keeps the list of your packages and their versions. [How it works →](/en/security)

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 →](mailto:bonjour@isee-u.fr)

### 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.

## Sources

Checked on Oct 22, 2026. We update this page as soon as a source changes.

- [php.net · Security announcement](https://www.php.net/archive/2026.php#2026-10-20-1)
- [CERT-FR · CERTFR-2026-ALE-014](https://www.cert.ssi.gouv.fr/alerte/CERTFR-2026-ALE-014/)
- [CISA · Alert of Oct 21, 2026](https://www.cisa.gov/news-events/cybersecurity-advisories)
- [Rapid7 · Technical analysis](https://www.rapid7.com/blog/)
- [Google Cloud · CVE response](https://cloud.google.com/support/bulletins)
- [Cisco · Security advisories](https://sec.cloudapps.cisco.com/security/center/publicationListing.x)
