Skip to main content
October 21, 20269 min read

PHP Patches Two Unauthenticated RCEs, Worst on mod_php

Get technical support

Patched, monitored, restored on a schedule

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, two flaws that allow unauthenticated code execution, worst on mod_php. What changed, who is exposed, and what to do before the update lands.

What Was Released

The PHP security release arrived on October 21, a little ahead of the announced 14:00 UTC. The two advisories went up on GitHub at 13:34 UTC, and php.net published the releases shortly after. The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.

Both vulnerabilities are rated critical, CVSS v4.0 9.2, and both allow unauthenticated remote code execution as the account the web workers run under.

CVEAdvisoryShort nameFixed in
CVE-2026-109618GHSA-w8hw-w9fx-j79wRCE via OOM corruption8.2.35, 8.3.36, 8.4.27, 8.5.12
CVE-2026-109619GHSA-6wmf-4rv5-p3rpRCE via stale global state8.2.35, 8.3.36, 8.4.27, 8.5.12

The php.net release notes are blunt about it. There are no complete mitigations, and updating is the only safe choice. Our earlier note, written before the details were out, covers how to find every PHP you run, which is the first step either way.

Who Is at Risk

PHP's advisory names every installation that serves web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. It puts the risk highest on mod_php, where a demonstrated exploit runs before any application code does.

Server setupWhat the advisories say
Apache with mod_phpRemote code execution confirmed for both flaws, triggered during request startup before the application runs
PHP-FPMCode execution validated for the session upload progress path of CVE-2026-109619. For CVE-2026-109618, source analysis shows FPM is susceptible, but no complete FPM exploit has been demonstrated
FrankenPHPCalls request shutdown unconditionally like mod_php, so source analysis says it is likely susceptible to application-independent attacks
LiteSpeed (LSAPI)Modelled on FPM, with application-specific exploits likely but not validated

The important line for anyone running mod_php is that application code offers no protection. The confirmed attack happens while PHP is still starting the request, so a firewall rule in the application, a framework's maintenance mode or a security plugin never gets a chance to run.

CVE-2026-109618, RCE via Out-of-Memory Corruption

PHP handles an out-of-memory error by jumping straight out of whatever it was doing and abandoning the request. The advisory explains that in some places, request memory is already reachable before it has been fully set up. If any allocation fails at that moment, even one unrelated to that memory, PHP leaves the request in an invalid state, and the shutdown code that runs afterwards treats the invalid state as real.

The attacker's job is to make PHP run out of memory at the right moment while staying inside the limits it normally enforces. The advisory lists several ways multipart form requests can do that.

  • A multipart request without a usable declared content length can pass the initial post_max_size check and keep supplying body data.
  • A single multipart part can carry an unlimited number of headers, and PHP's internal representation of them uses far more memory than they take on the wire.
  • Empty file fields do not count toward max_file_uploads, yet still create the usual file metadata arrays, and nested field names multiply that work.

Under mod_php, Apache runs PHP's request shutdown even when request startup has failed, so the whole sequence completes before the application is involved. FPM instead kills a worker whose startup failed, which removes that exact path, but an out-of-memory error later in a request can still reach the same flaw.

The fix removes the jump for out-of-memory errors. PHP now raises a soft out-of-memory error at the next safe point, and ends the process immediately if memory crosses a second, higher threshold.

CVE-2026-109619, RCE via Stale Global State

A PHP worker keeps some global state between requests, such as error, session and extension state, that points into memory owned by a single request. That state has to be reset before the request's memory is freed. The advisory describes cases where it is not, so that the next request on the same worker reads freed memory before normal initialization replaces it.

Exploitation needs two halves. A producer leaves request-owned state behind, typically because a fatal error or an out-of-memory error abandoned an operation before its cleanup ran. A consumer in a later request on the same worker then acts on that stale state. The advisory confirms two consumers.

The first is any warning, notice or deprecation raised while per-request INI settings are applied, before the request is initialized. Under mod_php that means .htaccess and Apache php_value or php_flag directives. Under FPM it means PHP_VALUE and PHP_ADMIN_VALUE parameters sent by nginx or another frontend. Deprecated or invalid settings are enough, and the advisory notes that hiding diagnostics with error_reporting, display_errors or the @ operator does not help, because the stale state is touched before PHP decides whether to report anything.

The second is session upload progress, which can reach session handling before ordinary session initialization. It is enabled by default and needs no session_start() call in the application. Code execution through this path was validated against both mod_php and FPM.

On PHP 8.5, the advisory adds a confirmed case where fatal_error_backtraces stores backtrace state that is never reset. That is the basis of the confirmed mod_php exploit for this flaw.

How to Update

Move to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. PHP says Linux distributions and LTS vendors received the patches in advance, so distribution packages may already be available, and checking your vendor is the first step.

One package source is a problem today. PHP warns that the volunteer-maintained rpms.remirepo.net will not have updates on October 21 and urges its users to switch to distribution packages or build from source.

After the package update, restart every PHP worker and every Apache instance running mod_php, because a running process keeps the old code until it is restarted. Then confirm what is actually running.

php -v
php-fpm8.3 -v
apt changelog php8.3-fpm | head -20

On distributions that keep their own version numbers, a changelog entry naming CVE-2026-109618 and CVE-2026-109619 is the proof, since php -v may still show the older base version. Container images have to be rebuilt on an updated base image, and anything built from source needs a rebuild against the new tarball.

PHP 8.1 and Older

PHP 8.1 and older get no releases from the PHP project. Some distributions and LTS vendors backport fixes, so those users should ask their vendor. Given the severity, the PHP security team also published minimal source backports for PHP 7.4, 8.0 and 8.1 as branches in the php-src repository, meant for people who build from source or have no LTS vendor. That is a lifeline, not a support plan, and PHP 8.2 itself reaches end of life on December 31, 2026.

If You Cannot Update Today

PHP lists measures that reduce exposure to specific attack paths. It is explicit that none of them make an installation safe, so they belong to the hours before an update, not instead of it.

Against CVE-2026-109618

  • Set memory_limit=-1 in a way applications cannot override, such as php_admin_value in the FPM pool or the Apache configuration, and check that nothing puts a finite limit back. A failure in an underlying allocation can still reach the vulnerable path.
  • Keep post_max_size low, 8M for applications without uploads and 32M where uploads are needed, with upload_max_filesize below it. Enforce limits on decoded body size, field count, multipart parts, headers and nesting depth at the web server or proxy as well, including for requests without a usable Content-Length.
  • A container or cgroup memory limit can serve as an availability boundary. Do not use RLIMIT_AS or RLIMIT_DATA, which can cause exactly the allocation failure the flaw needs.

Against CVE-2026-109619

  • Set session.upload_progress.enabled=0 in php.ini, the FPM pool or the server configuration, then restart every worker. ini_set() and FPM's .user.ini apply too late. The advisory suggests keeping it off even after patching if you do not use the feature.
  • On PHP 8.5, set fatal_error_backtraces=0 and restart the workers.
  • Remove invalid or deprecated settings applied per request, such as old directives left in .htaccess or frontend PHP_VALUE lines.
  • Fix fatal errors and execution timeouts that an attacker can trigger, including in upload, import and cleanup code. Where performance allows, pm.max_requests=1 stops one request's leftovers from reaching the next.

An Order for Tonight

Not every server carries the same risk, and the advisories make the order clear. Servers running Apache with mod_php come first, because the confirmed attack there needs no application code at all. Next are FPM servers whose frontend sends PHP_VALUE or PHP_ADMIN_VALUE per request, and anything using session upload progress, since those are confirmed consumers of the stale state. Ordinary FPM pools behind nginx follow, then internal tools and staging servers that are not reachable from the internet.

Where an update cannot happen tonight, apply the stopgaps above to that server specifically, write down which ones, and remove nothing from the list until the patched version is confirmed running. A note that says which hosts are on stopgaps is what stops one of them from being forgotten once the urgency fades.

What the Leak Got Right

The details leaked a day before the release, and some of what circulated has now been checked against the advisories. Session upload progress, which several unofficial write-ups pointed to, is one of the confirmed paths for CVE-2026-109619, although it is not the whole story and does not cover CVE-2026-109618. Claims of a CVSS 10.0 were wrong, as both advisories score 9.2. The leak also changed the timing, since PHP had said it would release early if details became public, and the release did land ahead of schedule.

Checking Your Logs

The advisory for CVE-2026-109619 recommends an isolated audit with log_errors=On, a working error_log and error_reporting=E_ALL. Look for warnings and deprecations repeated before scripts run, diagnostics during cleanup, fatal and parse errors, Maximum execution time exceeded, and failures tied to routes or uploads an attacker controls. Fixing what turns up reduces exposure. A clean log does not prove safety, because past logs may have excluded deprecations, and a failure can happen before PHP writes anything.

Patching PHP across shared, Plesk and cPanel servers and checking that every worker restarted is routine work in our server management service.

Sources: php.net security advisory, GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp, PHP 8 ChangeLog

Or read how we handle it in Servers Management.