Updated: 26 October 2026 (first published 23 October 2026)
What’s new (26 Oct)
- These two bugs now have a public name: php2shell (also PHP2Shell). It’s the same pair, CVE-2026-109618 and CVE-2026-109619, not a new CVE.
- AWS saw an exploitation attempt against its honeypots on 17 October, four days before disclosure. Public proof-of-concept code showed up around 21 October.
- Wiz found a second technique that leaks freed server memory through the
PHPSESSIDcookie, even if your app never callssession_start(). - CISA updated its alert on 23 October with a SIGMA detection rule, and says to take PHP 8.1 and older offline if you can’t patch.
session.upload_progress.enabled=0is not enough on its own. Patching is the only real fix.
The PHP vulnerability of October 2026 is really two bugs: CVE-2026-109618 and CVE-2026-109619, both critical remote code execution flaws that need no login. On 21 October, PHP released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix them. Update to the release for your branch and restart every PHP worker. PHP 8.1 and older get no official fix.
I’ve already written up the rollout process and the case for upgrading off old branches. This post covers the vulnerabilities themselves: what they are, how bad they are, who is exposed, and the short list of things to do today.
What happened: the October 2026 PHP security release
PHP pre-announced the release on 20 October and published the advisories on 21 October 2026 at 13:34 UTC, which was 6:34 PM PKT (GitHub advisory, CERT-EU). You may see 22 October next to these versions on the php.net ChangeLog. The advisories and the release announcement say 21 October, so I use that date. The ChangeLog lists the fix under Core as “Avoid state corruption via bailout.”
CVE-2026-109618: RCE via out-of-memory corruption
When PHP runs out of memory, it uses longjmp() to bail out. If that happens while request memory is only partly set up, the shutdown code later reads invalid state, and that can lead to code execution as the web worker user (GHSA-w8hw-w9fx-j79w). An attacker doesn’t need to find a memory-hungry page. The advisory lists ways to force the out-of-memory error during request parsing: multipart bodies with no usable Content-Length that slip past post_max_size, parts with unlimited headers, empty file fields that don’t count toward max_file_uploads, and deeply nested field names.
CVE-2026-109619: RCE via stale global state
Here, some state owned by one request stays on the worker after that request’s memory is freed. A later request on the same worker can then use it, which is a use-after-free (GHSA-6wmf-4rv5-p3rp). It takes two steps: one request triggers a fatal error, out-of-memory error or timeout, and a later request on the same worker uses the stale state. The advisory’s confirmed paths include PHP 8.5 with fatal_error_backtraces on, session upload progress (enabled by default, and it doesn’t need session_start()), and INI warnings raised before the request starts. Turning off error_reporting, using @ or disabling display_errors doesn’t help. Running more workers or recycling them “reduce[s] success per request but do[es] not remove the condition.”
Update, 26 October 2026: The security community now calls this pair php2shell. The name comes from Wiz Research, which combined both bugs into one exploit script it called php2shell (Wiz). CISA uses the name too (CISA). According to Wiz, it found the first bug on 19 August, had code execution on Drupal and WordPress by 20–21 August, and reported it to PHP on 24 August. It demonstrated shell access on the latest official WordPress, Drupal and Joomla images, and says every PHP version back to 5.4 is hit by at least one of the two bugs.
Update, 26 October 2026: Wiz also describes a memory leak that doesn’t need code execution at all. After an out-of-memory error leaves stale session state behind, a later multipart request can get freed server memory written into its PHPSESSID cookie. That can expose passwords, tokens or API keys, and it works even when the app never calls session_start() (Wiz).
How severe are they?
| Scorer | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| PHP (CNA), CVSS 4.0 | 9.2 Critical | 9.2 Critical |
| NVD, CVSS 3.1 | 9.8 Critical | 8.1 High |
| Red Hat, CVSS 3.1 | 8.1 Important | 8.1 Important |
Sources: NVD CVE-2026-109618, NVD CVE-2026-109619, Red Hat. Why do the numbers differ? For 109618, NVD rates attack complexity as Low, while PHP and Red Hat rate it High. I don’t spend time arguing over which number is right. Every scorer puts both bugs in the “patch now” range.
Is anyone exploiting them yet? That hasn’t been confirmed. Neither CVE was in CISA’s Known Exploited Vulnerabilities feed dated 21 October (CISA KEV), but that feed came out within hours of the release. CERT-EU says proof-of-concept code “ha[s] begun to circulate” and that exploitation is more likely. php.net says it would have released early if it had seen evidence of active exploitation. So treat in-the-wild exploitation as unconfirmed, and patch as if it were coming.
Update, 26 October 2026: Attackers have started trying. AWS says its MadPot honeypots caught an exploitation attempt on 17 October, four days before the public disclosure, and saw broad attempts once proof-of-concept code went public around 21 October (AWS). watchTowr, Patchstack and Cloudflare also reported attempts (watchTowr, SecurityWeek). As of 22–23 October, nobody had confirmed a successful attack, and I rechecked CISA’s KEV feed on 26 October: neither CVE is listed yet. Attempts are real, though, so don’t wait for a KEV entry before patching.
Update, 26 October 2026: CISA updated its alert on 23 October and added a SIGMA detection rule. It lists mod_php (highest risk), PHP-FPM, php-cgi, FrankenPHP and LiteSpeed as affected setups, and says PHP 8.1 and older should be taken offline if they can’t be patched (CISA). Canada’s Cyber Centre has a matching advisory (AL26-026).
Also announced: CVE-2026-115560 (no patch yet)
On 23 October, PHP posted an informational note about a third issue, CVE-2026-115560. It’s a remote code execution path through session upload progress that only works if an app switches session.serialize_handler at runtime with ini_set() before session_start(). PHP calls that “unlikely in practice” (php.net). There is no patch yet. PHP says the fix and the full advisory will come with the next regular release. Which versions are affected, its CVSS score and the fixed version haven’t been published, and NVD had no record of it when I checked, so I can’t confirm any of them. The suggested mitigation is session.upload_progress.enabled=0, the same setting that closes one of the 109619 paths.
On Laravel Forge? Here’s a Forge Recipe that applies session.upload_progress.enabled = Off on every PHP-FPM version.
Fixed versions: affected and patched PHP releases
| Branch | Affected | Fixed in | Status |
|---|---|---|---|
| 8.5 | Below 8.5.12 | 8.5.12 | Patched |
| 8.4 | Below 8.4.27 | 8.4.27 | Patched |
| 8.3 | Below 8.3.36 | 8.3.36 | Patched |
| 8.2 | Below 8.2.35 | 8.2.35 | Patched (end of life on 31 Dec 2026) |
| 5.4 – 8.1 | All | None | End of life, no official release |
- PHP 8.4.27 fixes both CVEs for the 8.4 branch. Its ChangeLog also lists other memory-safety fixes that have no CVE number (ChangeLog).
- PHP 8.3.36 fixes both CVEs for 8.3, the branch many Laravel 12 and 13 apps run on.
- PHP 8.5.12 and 8.2.35 fix both for their branches. The 8.6.0 RC4 build has the fixes too.
Version ranges come from both GitHub advisories. For 8.1 and older, the PHP security team published only “minimal source-backports” for 7.4, 8.0 and 8.1, not official releases (php.net).
Are you affected? How to check
Check the CLI and web PHP versions
The CLI and the web server can run different PHP builds, and the web one is what attackers reach. Check php -v, your php-fpm binary, a private phpinfo() page or your hosting panel. On distro packages, check the package version too. Distros keep the upstream version number and backport the fix. Ubuntu 24.04’s 8.3.6-0ubuntu0.24.04.13 is patched even though plain 8.3.6 looks old (Ubuntu). Debian bookworm’s fixed package is 8.2.35-1~deb12u1, and trixie’s is 8.4.27-1~deb13u1 (Debian security tracker). On Debian or Ubuntu, dpkg -l | grep php shows the installed package version.
Which setups are at risk
- Apache mod_php: highest risk. The advisory confirms RCE over HTTP with default limits, triggered during body parsing before any of your code runs.
- PHP-FPM: susceptible to 109618 according to source analysis, though no complete exploit has been shown. For 109619, RCE through session upload progress was validated on FPM, but it needs a suitable application operation.
- FrankenPHP: likely susceptible. LiteSpeed (LSAPI): application-specific exploits are likely but not validated. php-cgi: listed by CERT-EU among the exposed setups.
If you run Laravel, your app is affected because it runs on an affected PHP version. No source names Laravel specifically, so I won’t claim Laravel adds its own risk. My own reading, which no source confirms, is that long-lived workers like Octane and queue workers fit the advisory’s “later request on the same worker” condition, so make sure you restart them too.
How to apply the PHP security update (October 2026)
VPS / Ubuntu
Update the PHP packages for your current branch, then restart PHP-FPM or Apache. If you use Ondřej Surý’s PPA, its 8.2.35, 8.3.36, 8.4.27 and 8.5.12 builds for Noble and Jammy were uploaded on 21 October (Launchpad). Stay on your current branch. This isn’t the time to change branches.
Docker images
Docker Hub shows the official php:8.4-fpm tag was pushed again on 21 October (Docker Hub). Rebuild with --pull, redeploy, and check php -v inside the running container. Don’t assume the tag already has the patched version until you see it.
Shared hosting
You can’t patch the binary yourself. Check the version in your panel’s PHP selector. If it still shows an unpatched release in your branch, open a ticket and ask your host when 8.2.35, 8.3.36, 8.4.27 or 8.5.12 (or their distro equivalent) will be live.
Laravel apps
Laravel teams have more to cover: Composer’s platform setting, CI images, staging, and every queue, Horizon and Octane worker that keeps PHP in memory. I wrote all of that up in my step-by-step guide to patching PHP in Laravel production, so I won’t repeat it here.
Running PHP 8.1 or older? There’s no fix, so upgrade
PHP 8.1 reached end of life on 31 December 2025, and every older branch was already unsupported. PHP made no official release for these CVEs on any of them. Some distros may still ship fixes for their own old packages. Red Hat, for example, lists fixed php:7.4 and 8.0 builds for RHEL 8 and 9 (Red Hat). That covers those vendors’ packages, not PHP in general, so don’t count on it for your setup. The lasting fix is to upgrade your PHP version to a supported branch, ideally 8.4 or 8.5.
Verify the patch worked
After the restart, check the version the web server is actually running, not just the CLI. Confirm 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer, or a fixed distro package. Old workers that kept running with the old binary in memory are the most common way a server stays vulnerable after it’s “patched.” Configuration changes like session.upload_progress.enabled=0 reduce exposure, but AWS and CERT-EU both say upgrading is the only complete fix (AWS, CERT-EU).
Update, 26 October 2026: Datadog reproduced both bugs and found that session.upload_progress.enabled=0 does not fully protect you. Login checks in your app can’t block it either, because the bug fires before your code runs. Limiting or blocking oversized multipart uploads at a reverse proxy or WAF can help as a stopgap (Datadog). Still patch.
What to watch for in your logs (added 26 October)
- POST requests containing
PHP_SESSION_UPLOAD_PROGRESS, especially with large multipart bodies. - “Allowed memory size exhausted” errors during request startup, before your app logs anything.
- PHP workers starting shells or downloading tools.
- Hits on CISA’s SIGMA rule, if your logs feed a SIEM.
Also check for PHP you didn’t install yourself: inside Docker images, appliances and hosting panels. CISA and the Cyber Centre both call this out.
FAQ
What is php2shell?
php2shell is the public name for CVE-2026-109618 and CVE-2026-109619 together. Wiz Research named its combined exploit script php2shell, and CISA and others now use the name. The fix is the same: PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, then restart every PHP worker.
What are CVE-2026-109618 and CVE-2026-109619?
They are two critical remote code execution flaws in PHP’s core, fixed on 21 October 2026. CVE-2026-109618 corrupts memory when PHP runs out of memory. CVE-2026-109619 leaves stale state on a worker that a later request can use. PHP rates both CVSS 4.0 9.2.
Which PHP versions are affected by the October 2026 vulnerabilities?
All PHP 8.2 to 8.5 releases before 8.2.35, 8.3.36, 8.4.27 and 8.5.12 are affected. So is every version from 5.4 to 8.1, and those are end of life with no official fix. Distro packages may carry backported fixes under older version numbers.
Which PHP version fixes the October 2026 vulnerabilities?
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix both CVEs. If you are on 8.4, install 8.4.27. If you are on 8.3, install 8.3.36. Then restart every PHP worker so the new binary is actually the one serving requests.
Can attackers exploit these without logging in?
Yes. Both allow remote code execution without authentication. On Apache mod_php, the advisory confirms that a crafted request can trigger CVE-2026-109618 during body parsing, before any application code runs. Attackers have been trying since at least 17 October, but no successful attack had been confirmed as of 23 October.
Is there a fix for PHP 8.1 or older?
Not from PHP. Branch 8.1 and everything before it are end of life, and the security team published only minimal source backports. Some vendors patch their own packages, but the real fix is moving to a supported branch. Here’s why and how to upgrade PHP.
How do I check if my server is patched?
Run php -v, then check the web server’s version with phpinfo() or your hosting panel. Look for 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer after restarting workers. On Ubuntu or Debian, check the package version, because distros backport fixes.
Do I need to restart PHP after updating?
Yes. PHP-FPM, mod_php, FrankenPHP and long-running workers keep the old binary in memory until they restart. Restart the FPM service or Apache, and any queue or Octane workers, then confirm the new version from the web server.
Is changing PHP configuration enough?
No. Settings such as session.upload_progress.enabled=0 close some paths, but php.net, AWS and CERT-EU all say installing the patched version is the only complete fix. Use configuration changes as a short-term cover while you patch.
Patch today, then plan the upgrade
Today, get every server onto 8.2.35, 8.3.36, 8.4.27 or 8.5.12, restart the workers and check the web version. If you need the full rollout steps, here’s how to patch PHP in production. After that, put the bigger date on your calendar: 8.2 reaches end of life on 31 December 2026, and the next bug like this won’t be patched for it.
