On October 21, 2026, the PHP project released emergency fixes for PHP2Shell, two critical flaws in PHP itself that can let an unauthenticated attacker run code on a web server. On October 26, CISA added both flaws to its Known Exploited Vulnerabilities catalog. This guide covers who is exposed, how to confirm the fix is running and not only installed, what to do if you can’t patch today, and how our team handled PHP2Shell across client environments.
PHP2Shell in 60 seconds
- What it is: two critical flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619, that can let an attacker run code on a web server without logging in.
- Who is affected: any system that uses PHP to serve web pages, whatever runs on top of it. That includes Adobe Commerce, Magento, Shopware, WooCommerce and custom PHP builds, plus the PHP tools that sit around SaaS stores.
- What fixes it: PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor package that carries the same fix. Updating your platform or extensions doesn’t help.
- How urgent: CISA has listed both flaws as exploited in real attacks since October 26, 2026.
Three questions to ask your host, agency or IT team today:
- Is every PHP server we run on a fixed build, including staging and integration servers?
- Were PHP workers restarted, or containers redeployed, after the update?
- Has anyone checked our logs for signs of attack from before the patch?
The rest of this guide is the detailed version your technical team can work from.
What is PHP2Shell?
PHP2Shell is the name for two remote code execution vulnerabilities in the PHP engine, CVE-2026-109618 and CVE-2026-109619, both rated 9.2 (critical) on CVSS v4.0. The PHP security team fixed both in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released October 21, 2026, and states that updating is the only safe choice because no configuration change fully mitigates them.
| CVE | PHP’s name for it | What goes wrong, in plain terms |
|---|---|---|
| CVE-2026-109618 | RCE via OOM corruption | When a request runs PHP out of memory at the wrong moment, PHP can leave half-built data behind and later treat it as valid. An attacker can trigger this with a specially built upload request. |
| CVE-2026-109619 | RCE via stale global state | When a request fails at the wrong moment, PHP can keep pointing at memory it already released. The next request handled by the same PHP process can then use that memory. |
PHP rates the risk highest for Apache with mod_php, where an unauthenticated request can trigger the attack before your store’s own code even runs. No login page, admin URL restriction or platform security module stands in front of it. PHP confirms attackers can use these flaws to run code with the web server’s permissions and to read data from server memory.
The underlying bug predates the headlines. According to the PHP Foundation, a PHP core developer first found signs of it in 2024, and outside researchers proved it exploitable in August 2026.
PHP2Shell timeline
| Date (2026) | What happened | Source |
|---|---|---|
| October 20 | The two CVE IDs leak online. PHP publishes its pre-announcement early and moves the release up from October 22 to October 21 | PHP Foundation, php.net |
| October 21 | PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 with its security advisory; CISA issues an alert urging immediate patching | php.net, CISA |
| October 23 | PHP publishes an informational advisory on a separate, configuration-dependent flaw (CVE-2026-115560) that is not part of PHP2Shell and recommends disabling session upload progress until the next regular release | php.net |
| October 26 | CISA adds CVE-2026-109618 and CVE-2026-109619 to its Known Exploited Vulnerabilities catalog | CISA |
Which commerce platforms are affected by PHP2Shell?
Every platform that runs on PHP stays exposed until its runtime carries the fix, because the flaws live in PHP and not in any application. PHP’s advisory lists all PHP installations serving web requests as at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. In commerce, that covers Adobe Commerce, Magento Open Source, Shopware, WooCommerce, Drupal Commerce, Sylius and custom PHP builds. PHP runs 69.2% of websites whose server-side language W3Techs can identify (W3Techs, October 26, 2026).
Who owns the PHP runtime decides your next move:
| Your setup | Who patches PHP | Your job |
|---|---|---|
| Self-managed servers or cloud VMs | You or your agency | Patch, restart and verify (steps below) |
| Managed hosting or PaaS | Your host | Get written confirmation of the patched build, then verify it yourself |
| Containers (Docker, Kubernetes) | You, at image build time | Rebuild from a patched base image and redeploy every service built on it |
| SaaS commerce (Shopify, BigCommerce) | The SaaS vendor, for the core platform | Patch the PHP you run around the platform |
The last row is where exposure hides. A SaaS storefront can sit next to self-hosted PHP: a WordPress content site, an ERP or PIM connector, a B2B quoting tool, a product feed generator, or a staging server nobody shut down. Those systems can hold the same API keys and customer data as the store. If you don’t have a current list of every PHP system around your store, an eCommerce security audit covers vulnerability scanning and patch gap analysis across all five major platforms.
How to fix PHP2Shell: six steps
1. Inventory every PHP runtime that serves web requests
List every storefront, admin host, staging and UAT environment, subdomain, container and integration server that runs PHP. Start with internet-facing systems, the order the UK NCSC recommends. The NCSC also flags appliances and third-party services that bundle PHP, so check vendor advisories for those. For each system, record the PHP version, how PHP runs (mod_php, PHP-FPM, LiteSpeed or FrankenPHP), where PHP comes from (Linux package, hosting panel or container image) and who owns the patch.
What goes wrong: teams patch production and forget staging. Staging often runs the same code as production, and sometimes the same credentials, with looser access controls.
2. Install the fixed PHP release or your vendor’s patched package
Update to the fixed release on your current branch. Linux distributions and long-term support vendors received the patches in advance, so servers on distribution packages can take a package update instead of a source build.
| PHP branch | Fixed in | Notes |
|---|---|---|
| 8.5 | 8.5.12 | Supported |
| 8.4 | 8.4.27 | Supported |
| 8.3 | 8.3.36 | Supported |
| 8.2 | 8.2.35 | Reaches end of life December 31, 2026 |
| 8.1, 8.0, 7.4 | No official release | The PHP security team published minimal source patches for these branches in the official php-src repository, for teams that compile PHP themselves. They’re a stopgap, not restored support, and AWS’s security bulletin treats these branches as having no fix. Prefer a distribution or LTS vendor package, or upgrade. Unofficial third-party patches for older branches also circulate on GitHub and have no review from the PHP project. |
| 7.3 and older | No official release or backport | Get a fix from your distribution or LTS vendor, or upgrade. |
What goes wrong: jumping several PHP branches under incident pressure. Check which PHP versions your platform and extensions support before you switch branches. The patched release on your current branch is the faster and safer fix.
3. Restart every PHP worker and redeploy every container
A patched package on disk changes nothing until PHP loads it. Restart every PHP-FPM pool, Apache (for mod_php) and LiteSpeed. For containers, rebuild from the patched base image, pull the new base layer instead of reusing a cached one, and roll out every service built on it, including queue consumers and cron containers.
What goes wrong: a second PHP version installed side by side. A server can run php8.2-fpm and php8.3-fpm at once, and updating or restarting one leaves the other on the old build. List every running PHP process and compare its start time with the package install time.
4. Verify the running version, not the installed package
php -v reports the command-line binary, which can differ from the PHP that serves your web traffic. Check the web-facing binary instead: run the FPM binary with -v (its name varies by distribution, for example php-fpm8.3 -v on Debian and Ubuntu or php-fpm -v on RHEL-family systems), or load a phpinfo() page behind authentication and delete it afterwards.
Distribution packages often backport security fixes without changing the upstream version string, so a patched server can report an older version number. Search the package changelog for the CVE IDs:
bash
# Debian and Ubuntu
apt changelog php8.3-fpm | grep -E 'CVE-2026-10961(8|9)'
# RHEL, AlmaLinux and Rocky Linux
rpm -q --changelog <your-php-package> | grep -E 'CVE-2026-10961(8|9)'
If the CVE IDs appear, the build carries the fix. If they don’t and the version sits below the fixed release for its branch, the server is still exposed.
5. Check for signs of compromise from before the patch
Treat every day a server ran unpatched as an exposure window, since CISA now lists both CVEs as exploited. Here is what an attempt, or a successful attack, can look like in your logs and on the server:
- Upload requests built to exhaust memory (CVE-2026-109618). Repeated multipart POST requests with very large bodies, hundreds of form fields, deeply nested field names, many empty file fields, or unusually many headers inside each part. PHP’s advisories describe these request patterns as ways to run PHP out of memory.
- Upload-progress probing (CVE-2026-109619). Multipart POST requests that carry a
PHP_SESSION_UPLOAD_PROGRESSfield (PHP’s default name for that feature) sent to URLs that never handle uploads. - Bursts of out-of-memory errors and crashes. Clusters of “Allowed memory size exhausted” or “Maximum execution time exceeded” errors, followed by worker crashes: “exited on signal 11 (SIGSEGV)” in PHP-FPM logs, or “exit signal Segmentation fault (11)” in the Apache error log for mod_php.
- Processes the web server should never start.
sh,bash,curl,wgetor extraphpprocesses running as the web server user, with Apache or PHP-FPM as the parent process. - Web shells and new files. New or changed PHP files in the web root, upload or cache directories containing
eval(,base64_decode(,assert(or similar obfuscation, plus new crontab entries.
None of these proves an attack on its own, since a heavy catalog import can also run PHP out of memory. A pattern of several together, from unfamiliar IP addresses, is worth escalating.
Clean logs don’t prove a server is safe. PHP’s advisory for CVE-2026-109619 warns that a failure can happen before PHP writes any message. If you find anything, or if a server stayed unpatched for days, rotate every secret the PHP process could read: database credentials, payment gateway keys, ERP and PIM API tokens, and admin sessions. PHP confirms attackers can read data from server memory, so treat anything held there as potentially exposed.
6. Harden the server after you patch
Two changes from PHP’s own advisories stay useful after the update:
- Keep session upload progress off if you don’t use it. PHP calls it a hardly-used feature and suggests leaving
session.upload_progress.enabled=0in place even after patching. It also blocks CVE-2026-115560, a separate and much narrower flaw, until PHP ships the full fix. - Block or cap risky requests at the web server. If an application never accepts file uploads through multipart forms, block those requests before they reach PHP. Where you do need them, limit request size and the number of form fields and uploads. PHP notes these limits reduce out-of-memory and denial-of-service risk even on patched versions.
Running these steps across several stores, hosts and integration servers takes most of the time in an incident. Our eCommerce support and maintenance team handles patching, verification and incident response across Adobe Commerce, Magento Open Source, Shopify Plus, Shopware and BigCommerce.
What to do if you can’t patch PHP today
Apply PHP’s interim settings, set a firm date to patch, and treat the server as exposed until then. PHP states that these measures reduce exposure to specific attack paths but do not make an installation safe. The UK NCSC goes further and tells organizations that can’t fix a system right away to consider taking it offline.
| Setting (restart every PHP worker after changing it) | What it blocks | What to watch for |
|---|---|---|
session.upload_progress.enabled=0 | The confirmed session paths of CVE-2026-109619 (PHP2Shell). Also blocks CVE-2026-115560, a separate flaw (see note below). | Set it in php.ini or server config, not in application code. PHP calls this a hardly-used feature. |
memory_limit=-1, set so applications can’t override it | Part of CVE-2026-109618 | Removes PHP’s memory ceiling, so add a server or container memory limit instead. Check that no other setting puts a PHP limit back. |
post_max_size = 8M without file uploads, 32M with them | Part of CVE-2026-109618 | Can break catalog imports, B2B bulk order uploads and product media uploads. Run large imports from the command line until you patch. |
fatal_error_backtraces=0 (PHP 8.5 only) | Part of CVE-2026-109619 | Affects debugging output only. |
A note on CVE-2026-115560. This is a separate flaw, not part of PHP2Shell, and far narrower. According to PHP’s advisory, it only applies when an application sets session.serialize_handler to php_binary or php_serialize and then switches it to php at runtime with ini_set() before session_start(), with upload progress still enabled. PHP calls this setup unlikely in practice. Disable upload progress and move on; don’t spend incident hours on it while the PHP2Shell update is still pending.
Three common moves don’t solve the problem. Switching from mod_php to PHP-FPM is no fix, because PHP-FPM also appears on PHP’s at-risk list. Hiding PHP errors doesn’t help either. A web application firewall helps against known attack patterns, but it only filters traffic that passes through it and leaves the vulnerable runtime in place.
How Atwix responded to PHP2Shell
Our team checked client environments, put together an individual response plan for each client, coordinated fixes with our technology and hosting partners, and kept clients informed. The work now continues with verification that patched runtimes are in place.
Slava put it this way: “The established process helped. So did having people who care, figure things out and take ownership without waiting for me.”
Thank you to everyone at Atwix who did the daily work behind this response. Thanks also to the PHP security team, who shipped fixed releases for all four supported branches and, given the severity, minimal source backports for three end-of-life branches on the same day.
Our take: patch speed gets decided before the CVE drops
Every team received the same advisory at the same hour. Teams that already knew every PHP system they ran, who owned it and how it got updated could patch the same day. Teams that had to build that list during the incident spent the first days on discovery. If PHP2Shell forced you to build the list, keep it current.
PHP2Shell also showed what end of life means in practice: PHP 8.1 and older got no official release. PHP 8.2 reaches end of life on December 31, 2026, so if you run it, plan the move to 8.3 or later now, after confirming your platform supports it.
Frequently asked questions about PHP2Shell
Does updating my platform or CMS fix PHP2Shell?
No. PHP2Shell lives in the PHP runtime, so updating Adobe Commerce, Magento, Shopware, WordPress or any extension leaves the flaw in place. You need PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 or a vendor package that carries the same fix.
My host says PHP is patched, but the version number looks old. Is my site safe?
Possibly. Linux distributions and hosting platforms often backport fixes without changing the upstream version string. Ask your host which build carries the fix, or search the package changelog for CVE-2026-109618 and CVE-2026-109619.
Should I switch from mod_php to PHP-FPM?
Not as a fix. PHP rates mod_php as the highest-risk setup, but PHP-FPM is still affected: PHP validated remote code execution against PHP-FPM for CVE-2026-109619. Patch first, then decide on your server architecture separately.
Do I still need the session.upload_progress setting after patching?
PHP recommends keeping session.upload_progress.enabled=0 until its next regular bugfix release to block CVE-2026-115560, a separate and much narrower flaw that needs an unusual application setup. If your applications don’t use upload progress, PHP suggests leaving it off for good.
Get a second set of eyes on your PHP2Shell response
If your team still can’t say which PHP systems around your store run the patched build, that gap is your exposure. Our support team can check your storefront, staging and integration servers and confirm the fix is running on each. Talk to our support team about your PHP2Shell response.
