PHP2Shell (CVE-2026-109618): critical PHP RCE explained

If your website runs on PHP — and every WordPress, WooCommerce, Laravel, Drupal and Magento site does — October 2026 brought the most serious PHP security issue in years. Two flaws in PHP itself, nicknamed PHP2Shell, let an unauthenticated attacker run code on the web server. CISA has confirmed they are being exploited in real attacks.
This post explains what the flaws are, who is affected, how to check your servers, and what to do if you cannot patch today.
The short version
- CVEs: CVE-2026-109618 and CVE-2026-109619 (plus a third, CVE-2026-115560, disclosed two days later).
- Impact: Unauthenticated remote code execution on the web server.
- Severity: CVSS 4.0 score of 9.2 from the PHP project (some trackers show 9.8 under CVSS 3.1).
- Exploited: Yes. CISA added both CVEs to its Known Exploited Vulnerabilities catalog on October 26, 2026, with a three-day deadline for US federal agencies.
- Fixed in: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released October 21, 2026.
- Not fixed by the PHP project: PHP 8.1 and older are end of life. Minimal source backports exist for 7.4, 8.0 and 8.1, but you should get a patched package from your vendor or upgrade.
What the two flaws are
Both bugs are in the PHP engine, not in an extension or a framework, which is why they affect almost every PHP application.
CVE-2026-109618: memory corruption on out-of-memory
PHP enforces memory_limit by jumping out of whatever it is doing when a request runs out of memory. If that happens at the wrong moment — for example, while PHP is still parsing a form-based file upload — some internal request data is only partly set up. During cleanup, PHP can then treat that half-initialised data as valid and free memory that may still contain attacker-controlled bytes.
The PHP Foundation says that on Apache with mod_php, a single unauthenticated request can trigger this before any application code runs, and full remote code execution was demonstrated with default settings. RCE was also confirmed on PHP-FPM through application code paths.
CVE-2026-109619: stale state between requests
PHP workers handle many requests one after another. If a fatal error happens at the wrong point, internal state belonging to that request can survive after its memory has been freed. The next request on the same worker may then use that stale state before it is reset — a classic use-after-free. The reporter demonstrated RCE against a real-world application on Apache with mod_php.
CVE-2026-115560: a third, narrower issue
On October 23, the PHP project disclosed a third RCE issue in session upload progress. It only applies when session.serialize_handler is set to php_binary or php_serialize in configuration and then switched to php at runtime with ini_set() before session_start(), with upload progress still enabled. The project judged it unlikely to be a risk and is fixing it in the next regular release, with session.upload_progress.enabled=0 as the interim mitigation.
Who is affected
According to the PHP project, all PHP installations that serve web requests: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The risk is highest with mod_php. Products that bundle their own PHP runtime (control panels, appliances, some desktop and NAS software) may be affected too; NCSC-NL maintains a list of affected third-party software at github.com/NCSC-NL/php2shell.
For WordPress site owners this is the important part: updating WordPress, your theme or your plugins does not fix this. The fix is in PHP itself, which is managed by your host or by whoever runs your server.
How to check your version
On the server:
php -v # CLI version
php-fpm8.3 -v # FPM version (adjust the binary name to your PHP version)
The CLI and the version actually serving your site can differ. To see what the web server really runs, create a temporary file with <?php echo PHP_VERSION;, open it in the browser, then delete it. In WordPress, Tools → Site Health → Info → Server shows the PHP version too.
You are safe from these two CVEs if the version is 8.5.12+, 8.4.27+, 8.3.36+ or 8.2.35+, or if your distribution's security advisory says its package includes the fix. Distributions and LTS vendors received the patches in advance, so their package versions often have their own numbering — check the advisory, not just the version string.
How to fix it
-
Update PHP to a fixed release, or install your distribution's patched package:
# Debian / Ubuntu sudo apt update && sudo apt install --only-upgrade 'php8.*' # RHEL / AlmaLinux / Rocky sudo dnf update 'php*' -
Restart every PHP worker so no process keeps running the old code:
sudo systemctl restart php8.3-fpm # or your PHP-FPM service name sudo systemctl restart apache2 # if you use mod_php -
Prioritise internet-facing servers, and mod_php setups first.
-
On shared or managed hosting, ask your host to confirm in writing that your PHP build includes the October 21 fixes. If you are still on PHP 8.1 or older, this is the moment to move to 8.3 or 8.4 — 8.2 itself reaches end of life on December 31, 2026.
A note for users of the popular Remi repository: on release day no updated packages were available there, and the PHP team advised switching to distribution packages or building from source until they were.
If you cannot patch today
The PHP project lists mitigations that reduce exposure but do not make an installation safe. Use them only as a bridge to the update:
; CVE-2026-109619 and CVE-2026-115560 — set before request parsing, then restart all workers
session.upload_progress.enabled = 0
fatal_error_backtraces = 0 ; PHP 8.5 only
; CVE-2026-109618
memory_limit = -1 ; set with php_admin_value in the FPM pool or Apache config
post_max_size = 8M ; or 32M if you need uploads; keep upload_max_filesize below it
Important details from the advisory:
- Do not rely on
ini_set()or.user.inifor the session setting; it must apply before the request is parsed. - With
memory_limit = -1, put a memory limit on the container or cgroup instead so one runaway worker cannot exhaust the server. Do not useRLIMIT_ASorRLIMIT_DATA. - Enforce request size, field count and multipart part limits at the web server or reverse proxy.
- If none of this is possible, take internet-facing PHP servers off the public network until they are patched.
What I would do this week
- Inventory every server and container image that runs PHP, including staging sites and old projects nobody looks at.
- Patch and restart workers, starting with public-facing mod_php hosts.
- Rebuild Docker images — an old
php:8.3-apacheimage pulled months ago still contains the vulnerable PHP. - Check web server logs since mid-October for unusual multipart uploads and repeated PHP fatal errors or worker crashes, and review the server for unexpected files, cron jobs and processes if you were exposed.
- Plan the move off any PHP version that no longer receives security fixes.
If you run WordPress sites and are not sure what PHP version your host gives you, or you want someone to check and patch your server, book a free consultation and I will take a look.


