Get started
Security

PHP2Shell Explained: How to Patch the Critical PHP RCE Flaws

PHP2Shell is two critical bugs in the PHP engine, not in WordPress or any plugin, and any unpatched PHP site can be taken over without a login. Fixed versions, cPanel, Plesk, CloudLinux, Linux and Docker steps, what to ask a shared host, and what to check after patching.

PHP2Shell vulnerability: critical PHP remote code execution flaws CVE-2026-109618 and CVE-2026-109619 and how to patch them

Last revised 22 October 2026. We will update this post as vendor packages and exploitation reports develop.

What is PHP2Shell, in plain English

When a visitor loads a page, a PHP "worker" process builds it and sends it back. On a busy server that worker does not shut down afterwards. It cleans up and takes the next request.

PHP2Shell is a problem in that clean-up. If a request is cut off at exactly the wrong moment, because it runs out of memory or hits a fatal error, PHP can leave behind internal notes that point at memory it has already given away. The next request handled by the same worker may trust those stale notes. An attacker who can trigger the error on purpose, and then shape what lands in the freed memory, can make the worker run their code or hand over a copy of whatever was in that memory.

Think of a hotel housekeeping trolley. Each guest's paperwork is supposed to be cleared before the next guest checks in. PHP2Shell is a fire alarm going off mid-cleaning, so the previous guest's room key is still on the trolley when the next guest arrives. Someone who knows how to set off that alarm at the right moment can collect keys that were never meant for them.

The PHP project rated both CVEs 9.2 on CVSS v4.0. A figure of 10.0 leaked on 20 October, and the PHP Foundation has confirmed it was wrong.

Why this is different from a normal WordPress security alert

Most security notices are about a plugin, a theme or a CMS version. You update that component and the risk is gone. PHP2Shell does not work that way.

These bugs live in the PHP engine, underneath every application. Wiz, one of the research teams that reported the flaws, demonstrated unauthenticated code execution against fully updated container images of WordPress, Drupal and Joomla. Sansec reports the same against Magento 2.4.9 and ten other PHP applications. The application code was never the problem, so updating the application does not help. Only updating PHP does.

Two consequences for a business owner:

  1. "My WordPress is fully updated" is not a defence here.
  2. The person who can fix this is whoever controls the PHP version on the server: you (on a VPS), your hosting provider (on shared hosting), or the team that manages the server for you.

Who is affected

Versions

PHP branch Status Fixed version
8.5 Supported 8.5.12
8.4 Supported 8.4.27
8.3 Supported 8.3.36
8.2 Supported until 31 Dec 2026 8.2.35
8.1, 8.0, 7.4 End of life No official release. Source backports from the PHP security team, plus vendor packages (cPanel, Plesk, CloudLinux, Ubuntu, Debian, Red Hat)
7.3 and older End of life Vendor-dependent (CloudLinux alt-php and Ubuntu Pro cover some); otherwise upgrade

Handler and server setup

The PHP project lists PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed as affected. Risk is not equal across them.

How PHP runs Risk Why
Apache with mod_php Highest The PHP team confirmed a working exploit where one unauthenticated request triggers the bug before any application code runs.
PHP-FPM (Nginx or Apache) High Code execution confirmed through application-level code paths. Red Hat notes that FPM workers normally exit on early initialisation failures, so reliable exploitation is harder and usually needs non-default behaviour.
LiteSpeed / OpenLiteSpeed (lsphp) Affected Listed as affected by the PHP project. No LiteSpeed-specific advisory found at the time of writing. Treat lsphp as vulnerable until updated and verified.
php-cgi, FrankenPHP Affected Same engine, same bugs. FrankenPHP has shipped fixed images.
PHP CLI only (cron, scripts) Low Triggered by web requests. Update anyway so CLI and web builds match.

Hosting type

Hosting type Who patches What you do
Shared hosting (cPanel, Plesk, DirectAdmin) The host Confirm the vendor packages are applied. Use the ticket template below.
Managed WordPress / managed cloud The provider Check their status page. GoDaddy, for example, says its managed WordPress tier is patched.
VPS or dedicated with a control panel You or your sysadmin Run the panel update, restart workers, verify.
Self-managed Linux, Docker, Kubernetes You or your DevOps team Update packages or rebuild images, redeploy, verify.

Technical deep dive for developers

This section explains the mechanisms at the level the official advisories and researcher write-ups disclose. It stops short of exploitation detail.

The root cause

All four bugs share one root cause: PHP's handling of fatal errors, and out-of-memory errors in particular, during request start-up and shutdown. When a request dies this way the per-request heap is torn down, but some engine globals still hold pointers into it. Nothing resets those globals until the normal request initialisation path runs, and parts of the next request are processed before that happens. The result is a cross-request use-after-free: request B reuses memory that belonged to request A.

The PHP project's descriptions match. CVE-2026-109618 is "RCE via OOM corruption": memory exhaustion interrupts PHP while internal request data is only partly initialised, and clean-up then treats the invalid data as valid. CVE-2026-109619 is "RCE via stale global state": request-owned state survives after its memory is freed, and a later request on the same worker uses it before initialisation resets it.

The four bug classes

Wiz groups the issues into four bugs across the two CVEs.

1. Upload-progress deserialiser use-after-free (CVE-2026-109618). The session.upload_progress feature records upload progress in a global while the multipart body is still being parsed. If memory runs out during that parse, the global is left pointing at destroyed heap. The next request on the same worker can treat attacker-controlled heap contents as live bookkeeping state. This is the path most exploit attempts use, which is why the interim WAF guidance centres on PHP_SESSION_UPLOAD_PROGRESS.

2. Remote process-memory disclosure (CVE-2026-109618). Multipart bodies are parsed before module initialisation finishes. An out-of-memory error there can leave a session-ID pointer dangling. On a later multipart request, PHP URL-encodes whatever now sits in that reclaimed memory straight into the PHPSESSID response cookie. The application never needs to call session_start(). Worker memory can hold database passwords, API keys, session tokens and configuration values from other requests, which is why secrets rotation is part of the clean-up.

3. Fatal-error backtrace use-after-free (CVE-2026-109619). PHP 8.5 can record a backtrace for the last fatal error. That global is not cleared after an out-of-memory failure, and early diagnostics in the next request can touch the freed memory. The fatal_error_backtraces=0 mitigation blocks this path, which is why it only applies to 8.5.

4. OPcache shared-memory type confusion (CVE-2026-109619). OPcache keeps a process-local slot counter and shared-memory metadata, and the counter advances before the shared state is updated. If an allocation fails in between, the shared metadata points at slots that are later reused. Because OPcache memory is shared across workers, this becomes a cross-worker type confusion. Wiz demonstrated code execution against WordPress through this path.

Why mod_php is worse than FPM

Under mod_php the PHP engine lives inside the Apache worker and keeps serving requests after a failure, so the stale state is simply there for the next request. Under PHP-FPM, Red Hat reports that a worker which fails during early initialisation normally exits before reaching the corrupted structures, so the attacker needs the application to parse a second request body during script execution, or another non-default behaviour. That is a higher bar, not a safe harbour: the PHP team confirmed FPM code execution through application paths.

Why configuration changes are not a fix

The confirmed session paths can be blocked with session.upload_progress.enabled=0, and the backtrace path with fatal_error_backtraces=0 on 8.5. The PHP advisory states these block "the confirmed session paths but not other variants," and Wiz expects more variants. The patched releases fix the root cause (stale state surviving a fatal error), which the settings do not.

Am I vulnerable? A 2-minute self-check

No server access needed.

  1. WordPress: go to Tools, then Site Health, then the Info tab, then Server. Compare the PHP version shown with the fixed-version table. If it is 8.1.x or lower you are on an end-of-life branch and need to talk to your host.
  2. Hosting panel: in cPanel look for "Select PHP Version" or "MultiPHP Manager"; in Plesk open the domain's "PHP Settings".
  3. Ask your host. On shared hosting the version number alone may not tell you whether the backported fix is installed, because cPanel and Plesk kept the same version string for 7.4, 8.0 and 8.1. Ask directly whether the fix for CVE-2026-109618 and CVE-2026-109619 is applied, and when.
  4. If you are not sure, assume you are exposed and move to the fix section, or contact someone who can check for you.

How to fix it, by environment

Two rules apply everywhere. Update PHP. Then restart every PHP worker (Apache, PHP-FPM, LiteSpeed, long-running queue workers). A patched package with the old binary still in memory protects nothing.

cPanel / WHM (EasyApache 4)

cPanel shipped fixed ea-php82 through ea-php85 (8.2.35, 8.3.36, 8.4.27, 8.5.12) and backported both CVEs into ea-php74, ea-php80 and ea-php81 with the version number unchanged. Run EasyApache 4 updates in WHM, or from the shell:

yum clean all
yum update "ea-php*"
/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpm

Because the 7.4, 8.0 and 8.1 packages keep their old version numbers, verify through the changelog rather than php -v:

rpm -q ea-php81-php-cli --changelog | grep -E 'CVE-2026-(109618|109619)'

No output means the fix is not installed yet. Update cPanel & WHM itself too: its internal PHP was fixed in 138.0.18, 136.0.50, 134.0.66 and 110.0.153.

Plesk

Plesk released fixed PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12 for Linux and Windows. For PHP 7.4.33, 8.0.30 and 8.1.34 on Linux the version number did not change: builds dated 21 October 2026 or later carry the fix. Update through Tools & Settings, then Updates, then confirm the build date:

/opt/plesk/php/8.1/bin/php -v

Plesk's own engine (sw-engine) was also vulnerable and is fixed in Obsidian 18.0.81 Update 4 and 18.0.80 Update 11. Apply that too, then restart PHP-FPM or Apache.

CloudLinux alt-php, ea-php on CloudLinux, and LiteSpeed

CloudLinux has pushed fixed alt-php packages for every version it maintains (5.2 through 8.5) to its stable repositories, and fixed ea-php52 through ea-php85 for cPanel on CloudLinux. A normal update picks them up:

# CloudLinux 7
yum clean all && yum update 'alt-php*' 'ea-php*'

# CloudLinux 8, 9, 10
dnf clean all && dnf upgrade 'alt-php*' 'ea-php*'

Verify with the changelog, since these packages keep lower version numbers than upstream:

rpm -q --changelog alt-php82-common | grep -E 'CVE-2026-(109618|109619)'

If you run Imunify360, confirm the ModSecurity ruleset is 8.85 or later. Ruleset 8.83 ran only on Apache and Nginx; 8.84 and later also run on LiteSpeed. The ruleset is a virtual patch for the upload-progress path and does not cover the out-of-memory path.

For LiteSpeed Enterprise and OpenLiteSpeed, update the lsphp8x packages from your repository, restart LiteSpeed, and confirm with the binary (for example /usr/local/lsws/lsphp84/bin/php -v). We could not find a LiteSpeed-specific advisory at the time of writing; if your lsphp build still shows a pre-fix version, raise it with LiteSpeed or your host.

Ubuntu, Debian and the RHEL family

Distribution packages carry backported fixes under their existing version numbers, so compare the full package version string, not the upstream number.

Distribution Package Fixed version Advisory
Ubuntu 26.10 php8.5 8.5.9-0ubuntu2.1 USN-8948
Ubuntu 26.04 LTS php8.5 8.5.4-0ubuntu1.5 USN-8948
Ubuntu 24.04 LTS php8.3 8.3.6-0ubuntu0.24.04.13 USN-8948
Ubuntu 22.04 LTS php8.1 8.1.2-1ubuntu2.28 USN-8948
Ubuntu 20.04 and older php7.4 and earlier Ubuntu Pro (ESM) only USN-8948
Debian 13 (trixie) php8.4 8.4.27-1~deb13u1 DSA-6574-1
Debian 12 (bookworm) php8.2 8.2.35-1~deb12u1 DLA-4848-1
RHEL 8 / 9 / 10 and clones php, php:8.x modules Per-stream errata in Red Hat bulletin RHSB-2026-013 RHSB-2026-013
# Debian / Ubuntu
sudo apt update && sudo apt install --only-upgrade 'php8.*'
sudo systemctl restart php8.3-fpm apache2   # adjust to your version and stack

# RHEL family
sudo dnf update 'php*'
sudo systemctl restart php-fpm httpd

Then confirm with dpkg -l 'php8*' or rpm -q php that the installed version matches the table.

Docker and container images

Official PHP images have fixed tags for every supported branch, for example php:8.4.27-fpm, php:8.3.36-apache and php:8.2.35-cli. FrankenPHP images are fixed as well. There are no fixed tags for 8.1 or older. Rebuild on the new base, redeploy, and replace every running container. The PHP version is baked into the image tag, so host-level patching does not cover containers.

Shared hosting: what to ask your host

Copy this into a support ticket:

Subject: PHP2Shell patch status (CVE-2026-109618 / CVE-2026-109619) for my account

My account runs PHP [version] on [domain]. Please confirm: (1) whether the vendor fix for CVE-2026-109618 and CVE-2026-109619 has been applied to the server hosting my account, and when; (2) whether PHP-FPM / Apache workers were restarted after the update; (3) if my PHP branch is 8.1 or older, whether the backported package is installed, and which supported branch you recommend I move to; (4) if the patch is not yet applied, which interim mitigations are in place (WAF rule, session.upload_progress disabled) and your ETA.

If the answer is vague, or the ETA is more than a day away, escalate or get help moving to a host that has patched.

If you cannot patch today

These settings reduce exposure. The PHP project states that only an update is a complete solution. All of them must be set in php.ini, an FPM pool file (php_admin_value) or the web server configuration, with every worker restarted afterwards. Setting them through .user.ini, .htaccess php_value or ini_set() does not work, because the vulnerable code runs before those are read.

; CVE-2026-109619: blocks the confirmed session upload-progress path only
session.upload_progress.enabled = 0

; CVE-2026-109619, PHP 8.5 only: blocks the confirmed fatal-backtrace path only
fatal_error_backtraces = 0

; CVE-2026-109618: removes the memory_limit trigger, with real trade-offs
memory_limit = -1
post_max_size = 8M        ; or 32M if uploads are required
upload_max_filesize = 2M  ; must stay below post_max_size

What each one costs you:

  • session.upload_progress.enabled=0 disables upload progress bars that depend on it. Most modern applications do not use it.
  • memory_limit=-1 removes PHP's own memory ceiling. Replace it with a container or cgroup limit that kills only the affected worker, and watch memory use. The PHP project warns against RLIMIT_AS or RLIMIT_DATA for this.
  • A low post_max_size breaks large uploads. The PHP project also recommends request-size, field-count and multipart-part limits at the web server or proxy, applied even when there is no usable Content-Length header.
  • WAF rules from Cloudflare, Imunify360 and others block the request shapes seen so far. Attackers have already been observed changing payloads to get past them, and Datadog's refined exploit returned HTTP 200 and left the worker running. A WAF buys hours, not a fix.

Two further points from the advisory: hiding diagnostics with error_reporting, display_errors or @ does not help, and you should remove invalid or deprecated per-request INI settings that emit warnings before initialisation, since those warnings are part of the attack surface for CVE-2026-109619.

If you cannot patch today and the site is public, emergency website recovery is the route for getting it patched and checked without waiting on a host.

EOL PHP (7.x, 8.0, 8.1): no official fix, and what to do

PHP 8.1 and older stopped receiving releases before these bugs were reported, so there is no 8.1.x, 8.0.x or 7.4.x release with the fix. Three routes:

  1. Vendor packages. cPanel, Plesk, CloudLinux, Ubuntu (22.04 for 8.1; Pro ESM for older), Debian LTS and Red Hat received the patches in advance and have shipped or are shipping backported packages. Apply the package and verify through the changelog or build date as shown above.
  2. Source backports. The PHP security team published minimal backport branches for 7.4, 8.0 and 8.1 on GitHub for people who compile PHP themselves and have no LTS vendor. These are not full releases and carry no other fixes.
  3. Upgrade. This is the real answer. PHP 8.2 leaves support on 31 December 2026, so a move straight to 8.3 or 8.4 avoids doing this twice. For WordPress the jump from 7.4 to 8.3 is usually a matter of testing plugins on a staging copy; custom applications may need code changes. Either way, the server should run a supported PHP by the end of this year.

One caution: the community-maintained Remi repository, which many RHEL-family servers use for newer PHP, said it would not have the update on release day. If your server pulls PHP from there, check its current status or switch to distribution packages.

After patching: did anyone get in?

Patching stops future attacks. It does not undo one that already happened, and Amazon's honeypots recorded an exploitation attempt on 17 October, four days before disclosure. Start your review from that date.

Logs to inspect

  • PHP error log: "Allowed memory size exhausted" fatals reporting their location as "Unknown on line 0". That location means PHP failed during request initialisation, before any script ran, which is the signature of the out-of-memory trigger.
  • Apache error log: child process crashes with "exit signal Segmentation fault". Crashes are typical of failed attempts; a successful one may not crash anything.
  • Access logs: POST bodies containing PHP_SESSION_UPLOAD_PROGRESS, unusually large POSTs, repeated HTTP 500s from one client, and form-encoded POSTs with a single very long field name.
  • Responses: unusually large or malformed PHPSESSID cookies point at the memory-disclosure path.
  • Process activity: a web or PHP-FPM worker spawning a shell is the most direct indicator. Review any sh or bash child of httpd, apache2, php-fpm or lsphp.

Webshell sweep

Search the document root and uploads directories for PHP files modified since 17 October, PHP files inside wp-content/uploads or equivalent media folders (there should be none), and files whose names mimic core files but sit in the wrong place. Compare core, plugin and theme files against clean copies. Check cron entries and systemd timers for anything new.

Rotate secrets, even if you find nothing

The memory-disclosure bug returns fragments of worker memory to a remote client and leaves no trace on disk. You cannot prove afterwards that nothing leaked. Once patched, rotate what the workers could have held:

  • Database passwords (wp-config.php, .env, application config)
  • Application keys and salts (WordPress salts, Laravel APP_KEY, framework encryption keys)
  • Third-party API keys and tokens in configuration (payment gateways, email, integrations, cloud storage)
  • Admin passwords and CMS API credentials
  • TLS private keys, if they live on the same server
  • Active user sessions: force a logout of all users so stolen tokens stop working

The bigger lesson

Three separate teams found these bugs within weeks of each other in August 2026, and AI tooling was part of the story on both sides. The PHP Foundation notes that Alpha-Omega scanned PHP with an AI model earlier in the year, Wiz used AI models to adapt its exploits to different PHP versions and memory layouts, and the Foundation's own view is that tools now find bugs faster for defenders and attackers alike. The CVE IDs leaked a day early, a proof-of-concept video was posted by mistake, fixed container images appeared six hours before the embargo lifted, and honeypots saw attempts within hours of release.

The takeaway is not that PHP is unsafe. It is that the window between "a patch exists" and "attackers are using the bug" is now measured in hours. A site patched within a day of every critical release is in a different risk class from one patched when someone remembers.

Need this handled today?

If you are not sure whether your site is patched, do not have server access, or your host is not responding, WebXSentry can take it from here. WebXSentry is the website maintenance service of Aarav Infotech, which has kept 1000+ sites patched and online for 15+ years, so this is routine work for us.

Emergency PHP2Shell patch and audit. A one-time engagement, no plan needed. We confirm your PHP version and handler, apply the patch or vendor package, restart workers, verify through the changelog, sweep for webshells and recent file changes, review logs from 17 October onwards, and rotate the secrets that matter. For shared-hosting customers we deal with the host on your behalf. Start with emergency website recovery, or choose "hacked, down or flagged" on the quote form.

Ongoing protection. The next engine-level bug will arrive on its own schedule. Every WebXSentry maintenance plan includes security patching, malware scanning and removal, encrypted off-site backups and uptime monitoring, with a first reply by the next business morning. Not sure what you have today? Request a free website maintenance audit.

Call +1 (855) 650-4040 in the US, WhatsApp +91 80081 00192, or use the contact page. Tell us your PHP version and hosting type and we will tell you in plain language where you stand.

Keep reading

Add-ons

Fixes related to this guide

Fixed-price add-ons, bought separately from a plan.

Security

WordPress Security Optimisation Service

One-time deep security hardening for your WordPress or WooCommerce website

$99 per site, one-time

Security

Website Firewall Hardening Service (WAF Setup)

One-time WAF setup on Cloudflare Pro that blocks attacks before they reach your website

$249 per site, one-time

Speed and search

WordPress Speed Optimisation Service

Faster pages on mobile and desktop: caching, image, database and render-blocking fixes, with a before and after PageSpee...

$149 per site, one-time

See all add-ons

Straight answers

Questions this article answers

Clear, direct answers to the questions we hear most.

Is my WordPress site vulnerable to PHP2Shell if WordPress and all plugins are up to date?

Yes, if the PHP version on the server is unpatched. The bugs are in PHP, not in WordPress. Updating WordPress, themes or plugins has no effect on them.

Which PHP versions fix PHP2Shell?

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. For 8.1, 8.0 and 7.4, use your vendor's backported package (cPanel, Plesk, CloudLinux, Ubuntu, Debian, Red Hat) or the PHP security team's source backports.

Is PHP2Shell being exploited?

Exploitation attempts have been observed by Amazon, Cloudflare, watchTowr and others, including one on 17 October, before disclosure. As of 22 October no vendor has published a confirmed compromise and the CVEs were not yet in CISA's Known Exploited Vulnerabilities catalogue. Exploit code is public, so treat exploitation as likely rather than theoretical.

Does disabling session.upload_progress fix it?

No. It blocks the confirmed session-based paths for CVE-2026-109619 only, and only when set at php.ini or pool level with a worker restart. It does nothing for CVE-2026-109618.

I am on shared hosting. What can I do?

Ask your host whether the vendor fix for both CVEs is applied, and when, using the ticket template in this post. If they cannot confirm, consider moving to a host that has, or get a specialist to review your situation.

Does a WAF or Cloudflare protect me?

Partially and temporarily. Cloudflare, Imunify360 and others deployed rules matching the request shapes seen so far, and attackers have already been seen altering payloads. Use a WAF to buy hours, not days.

Do I need to change passwords after patching?

Yes. One of the bugs can leak fragments of server memory to an attacker and leaves no evidence on disk. Rotate database credentials, application keys, API tokens and admin passwords once the server is patched.

Why do some sources say CVSS 9.8 or 10.0?

The PHP project's rating is 9.2 on CVSS v4.0. The 10.0 figure that leaked on 20 October was incorrect. Other databases score the same bugs on CVSS v3.1, which gives different numbers (NVD 9.8, Red Hat 8.1). It is critical under any of them.

Website care for businesses in every country

This guide applies wherever your business is. Pick your country to see how we work with your time zone.

All countries and time zones

Want someone to look after your website?

Pick a plan and a real person takes over the updates, security and backups, with hours for the changes you ask for. Month to month, and a 30-day money-back guarantee.

  • From $99/mo with hours included
  • Month to month
  • 30-day money-back guarantee
From $99/mo · hours included See plans