PHP2Shell is the name given to two critical PHP vulnerabilities, CVE-2026-109618 and CVE-2026-109619, that let an attacker run code on a web server through an ordinary HTTP request, without logging in. The PHP project published fixed versions on 21 October 2026 at 14:00 UTC: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older are end-of-life and received no release. Both flaws are rated 9.2 (critical) on CVSS v4, and attacks were reported several hours before the fixed versions were out. Panelica has released updated PHP 8.2, 8.3, 8.4 and 8.5 packages and a patched PHP 8.1 package, all available now in System Updates.
What Happened and When
On 20 October 2026 the PHP security team announced an out-of-band security release for the next day, without details. On 21 October at 14:00 UTC it published PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 together with two advisories. The name PHP2Shell comes from an exploit tool of that name, a screenshot of which circulated alongside the advisory. Exploitation attempts against PHP sites were reported from 07:43 UTC that morning, more than six hours before the fixed versions could be downloaded, which is why this release needs to be applied the same day rather than in the next maintenance window.
The Root Cause, in Plain Terms
Both vulnerabilities come from the same weak spot: what PHP does when a request ends abnormally. PHP keeps a lot of per-request data in memory and expects to clean it up in an orderly way at the end of every request. When a request is cut short at the wrong moment, that cleanup works on data that is half-built or already freed, and an attacker who controls the request can shape that memory to take over the PHP process.
CVE-2026-109618: Out-of-Memory Corruption
When a request uses more memory than memory_limit allows, PHP stops it. Until this release, PHP did that by jumping straight out of whatever code was running (a longjmp(), called a bailout). If the jump happens while PHP is still setting the request up, for example while it is reading a file upload, some internal structures are only partly initialised. The cleanup at the end of the request then treats the incomplete data as valid, reads it and acts on it, and that is enough for code execution.
The advisory lists ways an attacker can force out-of-memory at exactly that point with a single request:
- A multipart request without a usable declared length, which gets past
post_max_size - Large numbers of headers inside multipart parts, which use up
memory_limit - Empty file fields, which build up internal arrays without counting against
max_file_uploads
The fix removes the jump for out-of-memory. PHP now records a soft out-of-memory condition and stops the request at the next safe point of execution, and if memory keeps growing past a second, higher threshold, the process ends immediately instead of continuing with damaged state.
CVE-2026-109619: Stale Global State Between Requests
A PHP-FPM worker serves many requests one after another. Some state lives in globals that outlast a single request: error information, session data, objects and extension state. If a request ends with a fatal error, an out-of-memory condition or a timeout, a global can still point to memory that the request has already freed. The next request handled by the same worker may use that pointer before PHP resets it, a classic use-after-free that the advisory confirms can be turned into memory disclosure and remote code execution.
An attack needs a producer that leaves request memory in a global and a consumer that touches it early in the next request. Confirmed producers are session upload progress (session.upload_progress.enabled, which is on by default) and, in PHP 8.5, fatal_error_backtraces. Confirmed consumers are deprecated or invalid INI settings that print a warning before the request is fully initialised. The fix resets this state completely at the end of every request.
Who Is Affected
Every PHP installation that serves web requests is in scope: PHP-FPM behind nginx or Apache, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The advisory names Apache mod_php as the setup with a demonstrated exploit that works regardless of the application, because it always runs request shutdown even when request startup failed. For PHP-FPM, the advisory for the first flaw states that source analysis supports the same weakness, with exploits more likely to depend on the application, and the advisory for the second flaw lists the conditions under which PHP-FPM is exposed. Every PHP line from 8.1 downwards is affected as well, but has no official release.
No configuration change fully closes either flaw. In the words of the advisory, updating to a release with the patch is the only complete mitigation.
Fixed Versions at a Glance
| PHP line | Official fixed release | Panelica package | Reported by php -v |
|---|---|---|---|
| 8.5 | 8.5.12 | 8.5.12 | 8.5.12 |
| 8.4 | 8.4.27 | 8.4.27 | 8.4.27 |
| 8.3 | 8.3.36 | 8.3.36 | 8.3.36 |
| 8.2 | 8.2.35 | 8.2.35 | 8.2.35 |
| 8.1 | None (end-of-life) | 8.1.35.3 | 8.1.34, with the security team's fix applied |
What Panelica Released
Panelica has released new packages for every PHP version it runs natively. PHP 8.2, 8.3, 8.4 and 8.5 are the official fixed releases. Each was built from the verified php.net source in a fixed build environment, checked against the previous package so that no extension or file went missing, and installed and tested on AlmaLinux 9 and 10, Rocky Linux 9 and 10, Debian 12 and 13, and Ubuntu 22.04, 24.04 and 26.04.
PHP 8.1 needed more work, because the PHP project no longer releases it. Its security team did publish a minimal source backport for 8.1, a change called "Avoid state corruption via bailout" that addresses both CVEs. Panelica applied that change to the last 8.1 release, PHP 8.1.34, required it to apply cleanly with no fuzzy matching, and confirmed the built binary contains the new memory-error handling that the unpatched 8.1 package lacks. That is why the package is numbered 8.1.35.3 while php -v still reports 8.1.34: the version number of PHP 8.1 itself did not change, its code did.
The build date tells the patched 8.1 apart from the earlier 8.1.34 build.
How to Update a Panelica Server
The update replaces PHP's program files. The php.ini of each version and every account's PHP settings and pools are kept.
What Panelica's PHP Setup Changes, and What It Does Not
Panelica runs PHP only through PHP-FPM, with a separate pool and Linux user for every account; Apache mod_php, the setup with the application-independent exploit, is not used. Per-account settings are written into the pool configuration by the panel, and the web server does not pass PHP settings to PHP-FPM with each request, which removes the PHP-FPM route the advisory confirms for the second flaw. By default each pool also runs with open_basedir and with shell functions such as exec, system and proc_open disabled.
None of this makes a Panelica server safe without the update. The first flaw does not depend on these settings, the advisory warns that applications and extensions can also leave or read stale state, session upload progress is on by default in every PHP version, and a memory corruption exploit runs native code that ignores disable_functions. Per-account isolation limits what a compromised worker can reach, as described in How Panelica Isolates Every User: 5-Layer PHP Security Architecture Explained, but it does not prevent the exploit. Treat every server as affected until System Updates shows the new versions.
If You Cannot Update Right Away
The advisories list temporary measures and are clear that they are incomplete. For the second flaw: set session.upload_progress.enabled = 0, and on PHP 8.5 fatal_error_backtraces = 0, in php.ini or the pool configuration (not with ini_set() or .user.ini), then restart the workers. Remove deprecated INI settings and fix fatal errors that visitors can trigger. For the first flaw, keep post_max_size conservative and limit request size and header counts at the web server. These steps narrow the attack surface for a few hours at most; the update is the fix.
Sites Still on PHP 8.1
The patched 8.1 package closes PHP2Shell, but PHP 8.1 itself receives no further fixes from the PHP project, and the backport is described by its authors as a minimal mitigation for an end-of-life version. Sites on 8.1 should move to PHP 8.2 or newer. In Panelica the PHP version is chosen per domain, so sites can move one at a time and be checked after each switch. For the command-line PHP, see How to Change the Default PHP Version in Terminal (SSH).
Frequently Asked Questions
What is PHP2Shell?
PHP2Shell is the common name for CVE-2026-109618 and CVE-2026-109619, two critical flaws in the PHP core that allow remote code execution through crafted HTTP requests without authentication. It is taken from the name of an exploit tool shown alongside the advisory.
Which PHP versions fix PHP2Shell?
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, released on 21 October 2026. PHP 8.1 and older have no official release; Panelica's PHP 8.1 package 8.1.35.3 includes the PHP security team's backport of both fixes.
Is PHP-FPM affected, or only Apache mod_php?
Both. The demonstrated exploit targets mod_php, but the advisory for CVE-2026-109618 states that PHP-FPM is susceptible as well, and CVE-2026-109619 depends on persistent workers, which is how PHP-FPM runs. Update either way.
Can a php.ini change protect my server instead of updating?
No. The advisories call every configuration measure incomplete and say that updating is the only complete mitigation.
Do I need to restart PHP-FPM after updating in Panelica?
No. Applying a PHP package restarts PHP-FPM for that version, including every account's pool, so the fix is active when the update finishes.
Why does PHP 8.1 still show 8.1.34 after the update?
The fix is a patch on top of 8.1.34, the last PHP 8.1 release, so PHP's own version number stays the same. The Panelica package number, 8.1.35.3, and the build date of 21 October 2026 show that the patched build is installed.