# PSA: update PHP today

> PHP security fixes are available. Update now, check the fixed versions, and use these temporary mitigations only while waiting for patched packages.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-10-21 | Updated: 2026-10-21 | Topics: [PHP](https://flaviocopes.com/tags/php/) | Canonical: https://flaviocopes.com/php-security-update/

If you run a PHP website, **make time to update PHP today**.

**The fixes are available.** PHP released its [security update on October 21, 2026](https://www.php.net/archive/2026.php#2026-10-21-5). Install the patched release for your branch:

| PHP branch | Fixed release |
| --- | --- |
| PHP 8.2 | 8.2.35 |
| PHP 8.3 | 8.3.36 |
| PHP 8.4 | 8.4.27 |
| PHP 8.5 | 8.5.12 |

Your Linux distribution may backport the fixes without adopting these exact upstream version numbers. Check its security advisory and package revision.

This concerns the PHP runtime underneath your application. Updating WordPress plugins or running `composer update` does not update that runtime.

## What's happening?

The vulnerabilities, **CVE-2026-109618 and CVE-2026-109619**, can allow an attacker to run code on your server without logging in. Both carry a CVSS v4.0 score of **9.2 out of 10**.

PHP's warning covers installations serving web requests, including PHP-FPM, Apache's PHP module, CGI, FrankenPHP, and LiteSpeed. Some confirmed exploit paths run before application code, so a login screen or a framework maintenance page doesn't protect the runtime.

The [PHP Foundation confirms](https://thephp.foundation/blog/2026/10/21/todays-php-security-release-and-how-were-strengthening-php-security/) that remote code execution was demonstrated before application code on `mod_php` with default settings, and through application-level code paths on PHP-FPM.

If you run Laravel, WordPress, Drupal, or another PHP application, check the PHP installation that serves it. Include old sites and admin tools you rarely open.

## The core issue

A PHP worker stays up and handles many requests. When a request hits a fatal error, including running out of memory, PHP does not return from the function it was in. It jumps out with `longjmp()`. PHP calls that jump a bailout.

The jump skips the cleanup of the work in progress. The request's internal data can be only half built, or the worker can still hold a pointer into memory that request already freed. Shutdown, or the next request on that same worker, then treats the leftover as real data. That is how the worker can be made to run an attacker's code.

The changelog line for the fix is "Avoid state corruption via bailout." The two CVE numbers are two ways into it.

### Out of memory

[CVE-2026-109618](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) is the case where the jump happens while PHP is still setting the request up. Shutdown then reads that unfinished memory. On Apache with `mod_php`, a demonstrated case does this before any of your application code runs.

The patched releases store the out-of-memory error and raise it at the next safe point in the virtual machine, once the normal `memory_limit` is crossed. A second, higher limit kills the process with `_exit()` and skips that cleanup.

### Leftover pointers

[CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp) is the pointer left behind. The worker keeps global fields for errors, sessions and similar state, and those fields point into the current request's memory. A bailout can free that memory and leave the fields in place. The next request on the same worker can use them before normal startup replaces them. The patch clears that state when the request ends.

```mermaid
flowchart TD
  accTitle: How a PHP bailout leaves bad state
  accDescr: A fatal error or out-of-memory condition jumps out of the current work. One path leaves request data half built, and shutdown reads it. The other leaves a worker pointer at freed memory, and the next request on that worker reads it.
  A[Out of memory or fatal error] --> B[Bailout jumps out]
  B --> C[Request data half built]
  B --> D[Pointer left at freed memory]
  C --> E[Shutdown reads it]
  D --> F[Next request on the same worker reads it]
```

## Why the fix took time

The Foundation says early signs of the out-of-memory problem emerged in 2024. Compatibility concerns, limited resources, and difficulty agreeing on a fix delayed the work. Reports demonstrating remote code execution made it the team's top security priority in August 2026. The team is changing its decision process to resolve similar problems faster.

Leaked CVE IDs prompted PHP to move the release from October 22 to October 21. At disclosure, the security team had found no working exploits among the public PoCs it inspected. That observation applies to those PoCs at that time; it doesn't establish whether servers have since been compromised. The [Foundation's account](https://thephp.foundation/blog/2026/10/21/todays-php-security-release-and-how-were-strengthening-php-security/) covers the disclosure timeline and funding needs.

## If you use Laravel Cloud, Forge, or Vapor

[Laravel announced these platform actions](https://x.com/laravel/status/2112873542346031513). Check its latest platform notices for confirmation that your applications have been patched:

| Platform | What you need to do |
| --- | --- |
| Laravel Cloud | Laravel announced automatic patching, with no manual action required. Confirm completion through its platform notices. |
| Laravel Forge | Manually update your server's PHP version through the Forge dashboard as soon as the patched package is available. Laravel says to power down the server if you cannot update it. |
| Laravel Vapor | Laravel announced automatic redeployment for PHP 8 applications. Its instructions tell PHP 7 users to upgrade to PHP 8. Check that your deployment has received the fix. |

For Forge, Laravel [confirmed the dashboard path](https://x.com/laravel/status/2112882551065055431): open your server, then **Runtime → Versions**, open the three-dot menu, and choose the update action for your PHP version.

## If you manage the server yourself

Check your distribution or PHP package provider's security advisory and install its fixed packages. If you deploy containers, rebuild with a patched PHP base image and replace the running containers. Static builds such as FrankenPHP bundle their own PHP runtime, so updating the system's PHP package won't update that binary.

Restart the PHP services and long-running workers that need it so they load the updated runtime. Then test the site and check the PHP version serving web requests. `php -v` checks your command-line PHP, which can differ from the PHP used by your web server.

```mermaid
flowchart TD
  accTitle: Apply the PHP security update
  accDescr: Identify each PHP deployment, obtain the patched runtime from its provider, restart or redeploy it, and verify the running application. Confirm completion when a managed platform patches automatically.
  A[Find your PHP deployments] --> B{Who applies the patch?}
  B -->|Your platform automatically| C[Watch for patch confirmation]
  B -->|You| D[Install fixed packages or rebuild image]
  D --> E[Restart services or redeploy]
  C --> F[Verify running PHP and test the site]
  E --> F
```

If you use shared or managed hosting, ask your provider whether the fix has been applied to **your site's PHP runtime**. Check each site if your account uses several PHP versions.

PHP currently [supports branches 8.2 through 8.5](https://www.php.net/supported-versions.php). PHP 8.1 and older are end of life upstream. Your distribution may still maintain its own packages, as Ubuntu does for PHP 8.1 below. The PHP security team has exceptionally supplied minimal source backports for 7.4, 8.0, and 8.1; these are not a return to normal upstream support or ready-made packages. Ask your vendor about a maintained fix or upgrade to a supported branch.

## Ubuntu and Debian fixes are available

[Ubuntu's security notice USN-8948-1](https://ubuntu.com/security/notices/USN-8948-1) lists these fixed package revisions:

| Ubuntu release | Fixed PHP package revision |
| --- | --- |
| 22.04 LTS | `8.1.2-1ubuntu2.28` |
| 24.04 LTS | `8.3.6-0ubuntu0.24.04.13` |
| 26.04 LTS | `8.5.4-0ubuntu1.5` |
| 26.10 | `8.5.9-0ubuntu2.1` |

These apply to Ubuntu's official packages. If you use a third-party PHP repository, check that provider's advisory and fixed revisions.

**An older upstream version number can still contain the fix.** Ubuntu backports patches, so compare the complete package revision with its notice. Ubuntu 22.04's patched PHP 8.1 package is one example of distribution maintenance continuing after upstream support ends.

Debian's trackers for [CVE-2026-109618](https://security-tracker.debian.org/tracker/CVE-2026-109618) and [CVE-2026-109619](https://security-tracker.debian.org/tracker/CVE-2026-109619) list these fixed security packages:

| Debian release | Fixed PHP package revision |
| --- | --- |
| Debian 12 (Bookworm) | `8.2.35-1~deb12u1` |
| Debian 13 (Trixie) | `8.4.27-1~deb13u1` |

Install the security updates for your release, then restart the services using PHP and verify the running site as described above.

## If you use Cloudflare

[Cloudflare has deployed PHP-specific WAF protections](https://blog.cloudflare.com/php-vulnerabilities-waf-protection/), including on Free plans. Free users receive the rules automatically. On paid plans, confirm that the Cloudflare Managed Ruleset is deployed in **Block** mode.

Cloudflare reports attack attempts, including changes to payloads aimed at bypassing its filtering. That establishes observed attack traffic, without showing that those attempts successfully compromised servers.

Some of the new protections inspect a request together with the origin's response. They can block a matching response before it reaches the attacker. That means some detection happens after PHP has processed a request.

Keep the WAF enabled while you patch. Make sure attackers cannot reach your origin directly and bypass Cloudflare. **Update PHP even with these protections enabled.** The linked announcement includes rule IDs and instructions for reviewing matched traffic under **Security → Security Analytics → Events**.

## Temporary mitigations while you wait for packages

[Mattias Geniar's mitigation guide](https://ma.ttias.be/php-cve-2026-109618-early-mitigation/) collects practical configuration examples and their limitations. PHP has now published its own advice too. **These measures only reduce exposure to particular attack paths. Updating PHP is the complete fix.**

If you can install a patched package now, do that first.

### Disable session upload progress

The [stale-state advisory](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp) recommends disabling session upload progress to block the confirmed session paths. Add this to the configuration used by your web-serving PHP runtime:

```ini
session.upload_progress.enabled = 0
```

On PHP 8.5, also disable fatal error backtraces:

```ini
fatal_error_backtraces = 0
```

Use `php.ini`, an FPM pool, or server configuration applied before request parsing. **Restart every PHP worker** and check the effective settings. Application-level `ini_set()` and FPM `.user.ini` are too late for this purpose.

These settings leave other paths open. Also remove obsolete or invalid per-request PHP settings that generate warnings. Hiding those warnings with `display_errors` or `error_reporting` does not remove the underlying problem.

### Reduce the request and memory attack surface

The [out-of-memory advisory](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) recommends blocking multipart requests at the frontend when the application doesn't need them. This must happen before PHP parses the body. Check your forms first: a multipart block can break legitimate requests, including uploads.

PHP also recommends administratively enforcing `memory_limit=-1` as an incomplete workaround. That removes PHP's per-request memory cap, so a request can consume the server's memory. A container or cgroup boundary can limit resource exhaustion, but may kill multiple workers and still cannot eliminate vulnerable allocation failures. Do not substitute `RLIMIT_AS` or `RLIMIT_DATA`, which can cause that failure.

Keep request limits conservative and enforce decoded body size at the frontend too. PHP's guidance suggests `post_max_size=8M` without uploads, or `32M` with uploads, keeping `upload_max_filesize` below it. A small `post_max_size` alone doesn't cover every parsing path.

Don't copy memory-limit changes into production without checking what they do to your application and host. The configuration details and remaining limitations are in the linked advisory.

### Take the site offline safely if you cannot patch

[CERT-EU recommends considering isolation](https://cert.europa.eu/publications/security-advisories/2026-018/) when you cannot patch promptly.

Mattias highlights an easy mistake here: **removing the PHP handler can make a web server serve your PHP source as plain text**, potentially exposing secrets. Block access, stop the web server, or have it return a static maintenance response without passing requests to PHP. Verify the result from outside.

Keep temporary protections until the updated runtime is running and you have checked the site. Then review the temporary settings: restore an appropriate PHP memory cap if you removed it, and test any uploads before lifting a multipart block. If you suspect a break-in, isolate the server and preserve the logs. Patching PHP does not remove files or other changes an attacker may already have left behind.
