CVE-2026-109619 explained: PHP stale global state RCE and how to fix it

CVE-2026-109619 is a critical PHP vulnerability where request-owned internal state survives after its memory is freed, letting a later request on the same worker run attacker-controlled code; the fix is updating to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35.

This article, part of our PHP security guide, explains the stale global state bug in plain terms, shows which servers are exposed, lists the fixed builds per branch, and covers the partial workarounds php.net published for the hours before an update lands.

CVE-2026-109619 explained: PHP stale global state RCE and how to fix it
The php.net advisory lists CVE-2026-109619 as GHSA-6wmf-4rv5-p3rp and says to update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35. (Image: php.net)

What is CVE-2026-109619?

CVE-2026-109619 is tracked by the PHP project as GHSA-6wmf-4rv5-p3rp and described as remote code execution via stale global state. It was disclosed in the php.net security advisory of 21 October 2026, together with CVE-2026-109618.

Both flaws can allow unauthenticated remote code execution. That means an attacker does not need an account or a login on the site to reach the bug; a crafted web request is enough.

Item CVE-2026-109619 detail
Advisory ID GHSA-6wmf-4rv5-p3rp
Bug class RCE via stale global state
Authentication needed None (unauthenticated)
Severity Critical; the pre-release notice rated both flaws CVSS v4.0 9.2
Disclosed 21 October 2026 on php.net
Fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35
Complete mitigation None; php.net says updating is the only safe choice

The PHP critical RCE security release covers the announcement for both CVEs; this article stays on CVE-2026-109619.

How the stale global state attack works

PHP keeps some internal state per request. php.net says that with CVE-2026-109619, this request-owned state can survive after its backing memory has been freed.

A long-running worker then handles a later request. That request may use the stale state before PHP's normal initialization resets it, so it touches memory that no longer belongs to it. That is a use-after-free pattern, and it is what makes code execution possible.

Stage What happens
1 A request runs in a PHP worker and creates request-owned internal state.
2 The request is cut short or fails, and the memory behind that state is freed while a reference to it remains.
3 The same worker picks up the next request.
4 Before normal initialization resets the state, PHP reads the stale reference.
5 An attacker who shapes what lands in that freed memory can steer execution.

The PHP ChangeLog lists the fix for 8.5.12, 8.4.27, 8.3.36 and 8.2.35 under Core as "Avoid state corruption via bailout". A bailout is PHP's internal way of aborting a request after a fatal error or timeout, which is why the php.net workarounds target fatal errors, timeouts and diagnostics raised before initialization.

The confirmed trigger paths php.net names are session upload progress handling and, on PHP 8.5, fatal error backtraces. php.net warns that other variants exist.

Which PHP setups are exposed to CVE-2026-109619

php.net says all PHP installations serving web requests are at risk. The CLI used for cron jobs and scripts is not named in the advisory, but any web-facing SAPI on the same server is.

Setup Exposed? php.net note
Apache with mod_php Yes Highest risk; a demonstrated exploit runs before any application code
PHP-FPM (Nginx, Apache proxy_fcgi) Yes Serves web requests from reused workers
php-cgi Yes Named in the advisory
FrankenPHP Yes Named in the advisory
LiteSpeed Yes Named in the advisory
PHP 8.1, 8.0, 7.4 and older Assume yes No project update; source backports only for 7.4, 8.0 and 8.1

Because the mod_php exploit fires before application code runs, keeping WordPress, Laravel or other app code up to date does not protect the server. Only the PHP binary itself carries the fix.

CVE-2026-109619 fixed versions

Each supported branch got one fixed release on 21 October 2026. Match the build to the branch you already run; there is no need to jump branches to get the fix.

Branch Fixed version Security support until
PHP 8.5 8.5.12 31 Dec 2029
PHP 8.4 8.4.27 31 Dec 2028
PHP 8.3 8.3.36 31 Dec 2027
PHP 8.2 8.2.35 31 Dec 2026
PHP 8.1 and older No php.net release End of life

Source and Windows builds are on php.net/downloads.php and windows.php.net/download/. Download builds only from those official pages; per-branch details are in the PHP 8.5.12 download for Windows, PHP 8.4.27 download and PHP 8.3.36 and 8.2.35 downloads.

Linux distributions and LTS vendors received the patches in advance, so their fixed packages may carry their own version numbers. Check the vendor's security notice for the fixed package version; on Ubuntu that is USN-8948-1, and the apt update steps for Ubuntu and Debian list each fixed package. php.net also says rpms.remirepo.net will not have updates on release day.

CVE-2026-109619 fixed version 8.5.12 in the PHP 8 ChangeLog Core section
The Core entry "Avoid state corruption via bailout" covers both GHSA advisories behind CVE-2026-109618 and CVE-2026-109619. (Image: php.net)

How to fix CVE-2026-109619 on your server

The fix is an update plus a full restart of every PHP worker. Old workers keep running the vulnerable code until they are replaced.

  1. Find your branch with php -v, and check the web SAPI too with a phpinfo() page or your host's control panel, since CLI and web builds can differ.
  2. On Debian or Ubuntu, run sudo apt update then sudo apt upgrade once your vendor publishes the fixed packages.
  3. On RHEL, AlmaLinux, Rocky or Fedora, run sudo dnf upgrade once the vendor's fixed packages are available.
  4. On Windows, download the matching 8.5.12, 8.4.27, 8.3.36 or 8.2.35 zip from windows.php.net/download/ and replace the old PHP folder, keeping your php.ini.
  5. In Docker, pull the updated official image tag and rebuild and redeploy every container that uses it.
  6. Restart PHP-FPM, Apache or the other SAPI so no worker from before the update keeps serving requests.
  7. On PHP 8.1 or older, ask your distribution or LTS vendor for a backport, build from the php.net minimal source backports for 7.4, 8.0 or 8.1, or move to a supported branch.

Platform-by-platform commands are in the guide to update PHP on Windows, Linux or XAMPP.

CVE-2026-109619 fix status for php8.2 and php8.4 in the Debian security tracker
Debian shows trixie (security) fixed in 8.4.27-1~deb13u1 via DSA-6574-1, while other releases are still listed as vulnerable. (Image: security-tracker.debian.org)

CVE-2026-109619 workarounds: session.upload_progress and fatal_error_backtraces

php.net lists four measures that reduce exposure to specific CVE-2026-109619 paths. They do not make an installation safe, and they are not a substitute for the update.

  1. Set session.upload_progress.enabled=0 in php.ini, an FPM pool or server configuration that applies before request parsing. Do not rely on ini_set() or an FPM .user.ini file. This blocks the confirmed session paths, not other variants.
  2. On PHP 8.5 only, set fatal_error_backtraces=0. This blocks the confirmed fatal backtrace path only.
  3. Remove invalid or deprecated settings applied per request that emit diagnostics before initialization. Hiding diagnostics with error_reporting, display_errors or the @ operator does not help.
  4. Fix fatal errors and execution timeouts an attacker can reach, including failures in callbacks, upload or import processing and cleanup.
  5. Restart every PHP worker after changing the settings.

The PHP manual notes that session.upload_progress.enabled defaults to 1 and that sites without upload progress bars can consider turning it off anyway. Settings for both CVEs, including the CVE-2026-109618 memory limits, are in the PHP mitigations checklist.

CVE-2026-109619 workaround: session.upload_progress.enabled in the PHP session settings table
session.upload_progress.enabled defaults to "1"; set it to 0 in php.ini or the FPM pool, not with ini_set(). (Image: php.net)

CVE-2026-109619 vs CVE-2026-109618

The two CVEs ship in the same releases and share one ChangeLog entry, but they break PHP in different ways and need different workarounds.

Detail CVE-2026-109619 CVE-2026-109618
Advisory ID GHSA-6wmf-4rv5-p3rp GHSA-w8hw-w9fx-j79w
Bug Stale global state OOM corruption
What goes wrong Freed request state is reused by a later request on the same worker Out-of-memory handling interrupts PHP while request data is half initialized, and cleanup treats it as valid
Workaround focus session.upload_progress.enabled=0, fatal_error_backtraces=0, fix fatal errors and timeouts memory_limit=-1, low post_max_size, proxy request limits, cgroup limits
Fixed in 8.5.12, 8.4.27, 8.3.36, 8.2.35 8.5.12, 8.4.27, 8.3.36, 8.2.35

One update fixes both, so there is no reason to patch them separately. Branch-by-branch download links for the companion flaw are in the CVE-2026-109618 fix guide.

Check CVE-2026-109619 is patched

php -r "echo PHP_VERSION, PHP_EOL, ini_get('session.upload_progress.enabled'), PHP_EOL;"

Prints the PHP version and the current session.upload_progress.enabled value for the CLI build.

You should see: The first line reads 8.5.12, 8.4.27, 8.3.36, 8.2.35 or later on that branch. For the web server, confirm the same version in a temporary phpinfo() page, then delete that page.

On distribution packages, the version string may stay on the older upstream number with a vendor suffix. In that case compare the installed package against the fixed version in the vendor's security notice.

Check CVE-2026-109619 is patched with phpinfo() in the PHP manual
A temporary phpinfo() page shows the web server's PHP version; delete the page once you have confirmed it. (Image: php.net)

CVE-2026-109619 fix not taking effect

phpinfo() still shows the old version after the update

Running workers still hold the old binary, or the web server uses a different PHP install than the CLI.

  1. Restart PHP-FPM, Apache or the other SAPI fully, not with a reload of the site config only.
  2. Check the Server API and Loaded Configuration File rows in phpinfo() to find which install serves the site.

session.upload_progress.enabled still reads 1

The value was set with ini_set() or .user.ini, or a pool or directory setting overrides it.

  1. Set it in php.ini, the FPM pool or the server configuration instead.
  2. Restart every worker, then read the value again in phpinfo().

No fixed package from the distribution yet

The vendor has not published its update, or the server uses a third-party repository such as remirepo.

  1. Watch the vendor's security notice and apply the php.net workarounds meanwhile.
  2. php.net suggests switching from remirepo to distribution packages or building from source.

CVE-2026-109619 FAQ

What is the PHP vulnerability CVE-2026-109619?

A critical PHP flaw where request-owned internal state survives after its memory is freed, so a later request on the same worker can use it. It can allow unauthenticated remote code execution.

Which PHP version fixes CVE-2026-109619?

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix it, released on 21 October 2026. Linux distributions and LTS vendors ship the same fix in their own packages, so check the vendor's security notice for the fixed package version.

Is PHP 8.1 affected by CVE-2026-109619?

php.net no longer ships updates for 8.1 and older. It published minimal source backports for 7.4, 8.0 and 8.1; otherwise ask an LTS vendor or upgrade.

Does disabling session.upload_progress fix CVE-2026-109619?

No. php.net says it blocks the confirmed session paths but not other variants. Only the update is a complete fix.

Is CVE-2026-109619 being exploited?

php.net reports a demonstrated exploit against Apache mod_php, where an unauthenticated request triggers the attack before any application code runs. The advisory does not state that attacks have been seen in the wild, but it urges every PHP user to update immediately.

Does a WordPress or plugin update fix CVE-2026-109619?

No. The bug is in PHP itself, and the mod_php exploit triggers before application code runs. Update the PHP runtime.

Do I need to restart after the PHP update?

Yes. PHP-FPM, Apache mod_php and other web SAPIs keep long-running workers in memory, and those workers run the vulnerable build until they are replaced. Restart every worker after the update, and after changing any workaround setting.

What is the CVSS score of CVE-2026-109619?

The php.net advance notice published on 20 October 2026 rated both critical vulnerabilities CVSS v4.0 9.2. The release advisory itself describes them as critical flaws that can allow unauthenticated remote code execution.

Bottom line on CVE-2026-109619

Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your vendor's fixed package) today and restart every PHP worker. CVE-2026-109619 lets an unauthenticated request reach freed request state, and php.net says no workaround is complete. The settings above only narrow known paths until the update is in place.

Philip Celasco

Philip is a Texas-based technology writer and IT administrator at Techdows.com with more than 10 years of experience creating practical content for everyday users and professionals. He specializes in web browsers, particularly Chromium-based platforms such as Google Chrome, Microsoft Edge, Brave, and Opera. Through his work as an IT administrator, Philip has hands-on experience managing devices, configuring browser policies, troubleshooting software and network issues, and helping people resolve problems that affect productivity and security. His articles are based on practical testing and real-world technical experience. He covers browser settings, extensions, performance problems, privacy controls, security features, and Windows troubleshooting. Outside work, Philip enjoys the quieter side of life in Texas and stepping away from the screen when he can. He has two kids, two cats and loves to play golf with his mother during the weekends.

Leave a Reply

Your email address will not be published. Required fields are marked *