
PHP2Shell Security Updates and Temporary Mitigations
Updated 21 October 2026 — security releases are now available
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 have been released to address two critical vulnerabilities that can allow unauthenticated remote code execution. Administrators should install a trusted patched release immediately.
Known publicly as PHP2Shell, the vulnerabilities are tracked as CVE-2026-109618 and CVE-2026-109619. Both carry a CVSS v4.0 score of 9.2. The PHP security announcement and the advisories linked below now provide the affected versions, fixes and temporary mitigation guidance.
Our recommendation is to update now. Configuration changes and request filters reduce exposure to specific attack paths, but only an update containing both fixes provides a complete solution to these vulnerabilities.
What website owners need to know
The PHP team advises all installations serving web requests to update, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.
The team considers the risk highest for mod_php, where an unauthenticated attack has been demonstrated before application code runs. PHP-FPM also requires patching; exploitation of the stale-state vulnerability has been validated in FPM under suitable application conditions.
The update concerns the PHP runtime that executes website code. Updating a CMS, plugin or theme alone does not update that runtime.
Identify every PHP installation you operate, including separate PHP-FPM services and pools, containers, control-panel installations and older versions assigned to individual websites. If you manage your own VPS or dedicated server, the PHP installations inside it need to be checked and updated. If another provider manages your PHP environment, confirm who will apply the update and how completion will be verified.
Fixed PHP versions
The following upstream releases contain both fixes:
| PHP branch | Fixed release |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
Use the fixed release for your branch, or a newer supported release that includes the fixes. Official source downloads and Windows binaries are available on the PHP downloads page.
Linux distributions and LTS vendors received the patches in advance. If your vendor backports security fixes, verify its advisory and the exact package revision; the upstream version number alone may not establish whether that package is patched.
PHP 8.1 and older are outside normal upstream support. Upgrade to a supported branch or confirm that your distribution or LTS vendor supplies both fixes. The PHP team has also published exceptional, minimal source backports for PHP 7.4, PHP 8.0 and PHP 8.1. These are source branches for people maintaining their own builds, not renewed general support or ready-made distribution packages.
Remi packages: in its 21 October announcement, the PHP team states that the volunteer-maintained Remi repository will not publish updates that day and recommends distribution packages or source builds for immediate remediation. Check current package availability and deployment compatibility before changing package sources.
What the vulnerabilities do
CVE-2026-109618 — RCE via OOM corruption: an out-of-memory error can interrupt PHP while internal request data is only partly initialized. Request cleanup may then act on that invalid data. Multipart parsing and application-specific memory consumption can provide ways to reach this condition. See GHSA-w8hw-w9fx-j79w.
CVE-2026-109619 — RCE via stale global state: internal state belonging to one request can remain in a worker after the associated memory has been freed. A later request handled by the same worker may use that stale state before normal initialization resets it. Confirmed paths involve session upload progress and, on PHP 8.5, fatal-error backtraces. See GHSA-6wmf-4rv5-p3rp.
Install the security update immediately
- Identify every PHP runtime and package source. Include all websites, PHP branches, services, containers and control-panel environments.
- Install trusted packages containing both fixes. Verify vendor advisories and package revisions where fixes are backported.
- Restart the affected PHP services and replace every old worker. Restart PHP-FPM, Apache when using mod_php, or the relevant PHP application server. Redeploy containers using an image that includes the patched runtime.
- Verify the runtime actually serving each website. Checking
php -valone does not confirm that PHP-FPM or Apache is running the same version. - Test essential application functions, including login, forms, checkout and uploads. Remove temporary restrictions only after confirming that every affected runtime is patched.
Temporary measures when an immediate update is not possible
The measures below address different parts of the attack surface. None is a substitute for installing both fixes. If a patched deployment is unavailable, consider restricting public access while arranging the update.
Block multipart requests before they reach PHP
If your application can operate without multipart requests, reject requests whose Content-Type contains multipart at the web server.
This also blocks legitimate file uploads and forms or API calls using multipart encoding, even when no file is attached. Check the effect on your application. The restriction reduces exposure through multipart processing but does not cover every way of exploiting either vulnerability.
Apache 2.4
Add the following to the relevant virtual host configuration or an appropriate directory context. It can also be used in .htaccess where the server permits these directives:
<If "req('Content-Type') =~ /multipart/i">
Require all denied
</If>
The /i flag makes the expression case-insensitive, matching values such as multipart/form-data and Multipart/Form-Data. See the Apache expression reference.
Check the configuration before reloading:
apachectl configtest
Reload Apache only after the check succeeds, using the service name appropriate to your system.
Nginx
Add this map once inside the existing http {} context, outside individual server {} blocks:
map $http_content_type $block_multipart {
default 0;
"~*multipart" 1;
}
Then add this guard at the top of each server {} block that can pass requests to PHP, including servers that proxy to an Apache backend:
if ($block_multipart) {
return 403;
}
The ~* prefix enables case-insensitive matching. The map defines the variable; the guard performs the rejection. Nginx documents the map context and matching rules and server-level processing order.
Test the configuration and reload only if the test succeeds:
nginx -t && systemctl reload nginx
Apply the restriction across all relevant hostnames and routes, including direct access to the origin. Check that custom 403 handling does not forward rejected requests back into PHP.
Disable session upload progress
For installations awaiting a patch, disable session upload progress:
session.upload_progress.enabled = Off
Apply this through php.ini, a loaded system .ini file, an FPM pool, or server configuration that takes effect before request parsing, then restart every worker. Do not rely on ini_set() or FPM .user.ini for this mitigation.
This blocks the confirmed session upload-progress paths without disabling ordinary PHP sessions. Applications using PHP’s upload-progress tracking will lose that feature. Other stale-state paths remain possible.
If the application does not require file uploads, you can also set:
file_uploads = Off
This is a system-level setting. It disables PHP file uploads and is not equivalent to rejecting all multipart requests at the web server.
Reduce other stale-state paths
On PHP 8.5, also disable fatal-error backtraces administratively and restart every worker:
fatal_error_backtraces = Off
This removes the producer used by the confirmed fatal-backtrace exploit, but does not cover every global-state or extension path.
Remove invalid or deprecated settings that emit diagnostics when applied before request initialization. Suppressing messages with error_reporting, display_errors or @ does not prevent the vulnerable state access. Review fatal errors and execution timeouts reachable through attacker-controlled requests, including callbacks, upload/import processing and cleanup.
For PHP-FPM, the stale-state advisory also suggests considering this pool setting where the performance cost is acceptable:
pm.max_requests = 1
It recycles a worker after one request, limiting reuse of stale state across requests. It can substantially affect throughput and does not address the separate OOM vulnerability.
Reduce exposure to OOM corruption
For unpatched installations, the PHP team recommends temporarily enforcing:
memory_limit = -1
Apply this administratively so application code cannot restore a finite PHP memory limit. For example, the corresponding setting in an FPM pool is:
php_admin_value[memory_limit] = -1
Restart every worker and check for conflicting settings across pools, directories and applications.
This removes PHP’s per-request memory cap and can increase denial-of-service risk. It avoids the predictable PHP memory-limit failure used by confirmed attacks, but an underlying allocation failure can still reach the vulnerable path.
The PHP team’s accompanying recommendations are:
- Keep
post_max_sizelow: 8M for applications without file uploads, or 32M where uploads are necessary. Keepupload_max_filesizebelowpost_max_size. - Enforce request-size limits independently at the web server or proxy. Where supported, also bound input fields, multipart parts, headers and nesting. Controls must cover decoded request bodies and requests without a usable
Content-Length. - Use container or cgroup memory limits to contain resource exhaustion, preferably with a policy that kills only the affected worker. These limits do not guarantee protection from allocation failures.
- Do not substitute
RLIMIT_ASorRLIMIT_DATA. They can cause allocation failures that trigger the vulnerable path.
These emergency settings require application and capacity checks. After patching, review temporary changes and restore appropriate normal memory limits. Full details are in the OOM advisory.
Check that the request filter is active
Send a harmless multipart request to an existing PHP-backed URL on your own website:
curl -sS -o /dev/null -w '%{http_code}\n' -F 'mitigation_test=1' https://example.com/index.php
Replace the example URL with a real endpoint. With the rule active on that route, the expected response is 403 Forbidden.
Check the web-server logs to confirm that the filter caused the rejection, and test normal requests for disruption. A successful test confirms that this request was blocked; it does not prove protection against every exploit variant.
After changing PHP configuration, confirm the effective settings in every website runtime and ensure all old workers have been replaced. Command-line PHP may load a different configuration. Complete remediation requires a running PHP version or vendor package containing both CVE fixes.


