Introduction
On October 21, 2026 the PHP project released PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical vulnerabilities in the PHP runtime itself. CVE-2026-109618 and CVE-2026-109619 both allow unauthenticated remote code execution as the web worker user, and both are rated CVSS 4.0 9.2. Against Apache with mod_php, a working exploit fires before any application code runs, so the framework and the application on top offer no protection.
The PHP security team announced the release a day in advance, on October 20. Linux distributions and LTS vendors received the patches before publication.
| CVE | Advisory | Vulnerability |
|---|---|---|
| CVE-2026-109618 | GHSA-w8hw-w9fx-j79w | Out of memory handling leaves request data half built, and request cleanup can use it |
| CVE-2026-109619 | GHSA-6wmf-4rv5-p3rp | State from one request outlives it, and a later request on the same worker can use the freed memory |
Technical Information
CVSS Breakdown
Both vulnerabilities share the same vector:
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
- Attack Vector: Network. The attack arrives as ordinary HTTP requests.
- Attack Complexity: High and Attack Requirements: Present. Success depends on how the server is set up. For CVE-2026-109618, the advisory names the PHP build, the loaded extensions, the web server in front of PHP and memory layout.
- Privileges Required: None and User Interaction: None. No account and no victim action are needed.
- Confidentiality, Integrity and Availability: High on the PHP server itself.
Running more workers makes an attack take more tries. It does not stop it.
CVE-2026-109618: Out of Memory Corruption in Request Startup
When PHP runs out of memory, it leaves the current code path with longjmp(). Some request data is reachable before it is fully set up. If any allocation fails in that window, request shutdown can later read that half built data as if it were valid. The allocation that failed does not have to be related to that data.
The method the advisory shows is pushing one request past memory_limit, and it works with default settings. A multipart body with no usable Content-Length gets past the first post_max_size check. A single multipart part can carry any number of headers, and they cost far more memory inside PHP than on the wire. Empty file fields build arrays without counting against max_file_uploads, and nested field names multiply that work.
On mod_php all of this happens during request startup, because that is when PHP parses the body, and mod_php runs shutdown even when startup fails. PHP-FPM ends the worker when startup fails, which is why it is harder to exploit there.
CVE-2026-109619: Stale Global State Across Requests
One PHP worker serves many requests. Error, session, object and extension state from a request can stay referenced after that request's memory is freed.
The attack uses two requests on the same worker. The first one leaves state behind that PHP never resets. Fatal errors do this, including parse errors, a failed require, uncaught errors and execution timeouts. So do out of memory errors, and warnings raised during cleanup after PHP has already cleared that state. The second request reaches code that reads the leftover state before request setup clears it. The advisory names two such places: warnings, notices or deprecations from INI settings applied before request startup, and session upload progress. The second request can then use freed memory.
Two defaults make this worse. Session upload progress is on by default and works without the application calling session_start(). In PHP 8.5, fatal_error_backtraces is also on by default. It stores backtrace state and always misses the reset, and it is the basis of the confirmed mod_php exploit.
Hiding errors does not help. PHP reads the stale state before it checks error_reporting, @, display_errors or log_errors.
Affected Systems and Versions
| Branch | Affected | Fixed in |
|---|---|---|
| PHP 8.5 | Before 8.5.12 | 8.5.12 |
| PHP 8.4 | Before 8.4.27 | 8.4.27 |
| PHP 8.3 | Before 8.3.36 | 8.3.36 |
| PHP 8.2 | Before 8.2.35 | 8.2.35. The branch reaches end of life on December 31, 2026 |
| PHP 8.1 and older | All versions | No upstream release. Minimal source backports exist for 7.4, 8.0 and 8.1 |
Exposure depends on the server API that PHP uses to receive requests:
| Server API | CVE-2026-109618 | CVE-2026-109619 |
|---|---|---|
| Apache mod_php | RCE confirmed over HTTP, before any application code runs | RCE confirmed |
| PHP-FPM | Possible, based on the source. FPM ends the worker when request startup fails, so an attack needs an out of memory error later, in application code. No exploit shown | RCE confirmed through session upload progress on a normal pool, given a suitable application operation. Also possible when the web server passes PHP_VALUE or PHP_ADMIN_VALUE settings that raise a warning |
| FrankenPHP | Likely without application code, based on the source | The INI warning path was not shown in the default setup. The advisory says this does not make it immune |
| LiteSpeed LSAPI | Likely in some applications, not tested | Possible through INI values set by the environment |
php.net also lists php-cgi as at risk. mod_php carries the highest risk according to the PHP security team.
Patch Information
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix both vulnerabilities. Distribution and LTS vendor packages may already be available, since those vendors received the patches early. Users of rpms.remirepo.net should switch to distribution packages or build from source, because the PHP team says that repository will not have updates on release day.
For CVE-2026-109618, the fix removes longjmp() from out of memory handling. PHP now stops the request at the next safe point, and ends the worker with _exit() if memory keeps growing past a second, higher limit.
For 7.4, 8.0 and 8.1, the PHP security team published minimal source backports: 7.4, 8.0, 8.1. They turn off session upload progress and end the worker whenever it hits the memory limit. Moving to a supported branch or a vendor LTS build is the better path.
After updating, administrators should restart PHP-FPM, Apache or whatever runs PHP, so every worker loads the new build.
Detection Methods
Check the PHP Build That Serves Traffic
The php command line binary can be a different build from the one that serves web requests. Check the serving build directly:
php-fpm -v # often php-fpm8.3 on Debian and Ubuntu apachectl -M | grep -i php # mod_php loads as php_module
In containers, run the same commands with docker exec.
Review Error Logs for Stale State Producers
The CVE-2026-109619 advisory suggests turning on log_errors, a working error_log and error_reporting=E_ALL in an isolated environment, then reviewing the logs for fatal errors, timeouts and early INI warnings. The advisory also notes that clean logs do not prove a server is safe.
Mitigation Strategies
These steps block the known attack paths. Other variants may still work, and updating is the only full fix.
For CVE-2026-109618:
- Set
memory_limit=-1withphp_admin_valuein the FPM pool or Apache config, and check that no pool, directory or application setting puts a limit back. Use a container or cgroup memory limit as an availability boundary instead, ideally one that kills only the affected worker. Do not useRLIMIT_ASorRLIMIT_DATA. They make allocations fail, which is what triggers the bug. - Set
post_max_sizeto8M, or32Mwhere uploads are needed, and keepupload_max_filesizebelow it. Lowermax_input_nesting_level. - At the proxy, cap decoded body size, field count, multipart parts, headers and nesting depth, including for requests with no
Content-Length. Block multipart forms where the application does not use them.
For CVE-2026-109619:
- Set
session.upload_progress.enabled=0inphp.ini, the FPM pool or the server config, then restart every worker.ini_set()cannot change this setting, and.user.iniapplies too late. - On PHP 8.5, turn
fatal_error_backtracesoff withphp_admin_flagin the FPM pool or Apache config, then restart every worker. A plainphp.inisetting is not enough, because applications can turn it back on withini_set(). - Remove invalid or deprecated INI settings applied per request, and fix fatal errors and timeouts that an attacker can trigger.
- Where performance allows, set
pm.max_requests=1so each FPM worker serves a single request.
Vendor Security History
PHP has shipped critical remote code execution fixes before, and attackers have used several of them. These earlier vulnerabilities are all in CISA's Known Exploited Vulnerabilities catalog:
| CVE | Component | Vulnerability | Fixed in | Added to CISA KEV |
|---|---|---|---|---|
| CVE-2024-4577 | PHP-CGI on Windows | Windows "Best-Fit" character conversion lets an attacker pass command line options to PHP | 8.1.29, 8.2.20, 8.3.8 | June 12, 2024 |
| CVE-2019-11043 | PHP-FPM | Certain FPM setups write past allocated buffers, opening a path to code execution | 7.1.33, 7.2.24, 7.3.11 | March 25, 2022 |
| CVE-2012-1823 | php-cgi | Query strings without an = are parsed as command line options, allowing code execution | 5.3.12, 5.4.2 | March 25, 2022 |
As of the catalog version released on October 21, 2026, CVE-2026-109618 and CVE-2026-109619 are not listed.
For this release, the PHP security team gave a day of advance notice, delivered patches to distributions and LTS vendors ahead of publication, and published minimal backports for 7.4, 8.0 and 8.1 even though the project no longer supports those branches.



