DEV Community

Cover image for PHP Critical RCE Fix: Update to 8.5.12, 8.4.27, 8.3.36
devTalk
devTalk

Posted on Originally published at dev-talk.com

PHP Critical RCE Fix: Update to 8.5.12, 8.4.27, 8.3.36

On 21 October 2026 the PHP project released security updates for every supported branch, and the front page of php.net carries a banner that reads "Critical remote code execution vulnerabilities, update now." Two flaws can allow unauthenticated remote code execution, and both are rated CVSS v4.0 9.2. If you run PHP behind a web server, this is a patch-today item. This article covers what was announced, how to tell whether your server is covered (the version number can mislead you), how to update, and what to do if you truly cannot update right now. I stick to the official advisory and avoid anything that would help an attacker.

The short version

  • Fixed versions: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.
  • Vulnerabilities: CVE-2026-109618 and CVE-2026-109619, both unauthenticated remote code execution.
  • Who is at risk: per php.net, all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The risk is highest for mod_php.
  • Complete fix: update. php.net says there are no complete mitigations.
  • PHP 8.1 and older get no updates from the PHP project. PHP 8.2 reaches end of life on 31 December 2026.

What the two vulnerabilities are

This is how php.net describes them, in its own words:

  • CVE-2026-109618, RCE via out-of-memory corruption. Out-of-memory handling can interrupt PHP while internal request data is only partly initialized, and request cleanup may then treat the invalid data as valid.
  • CVE-2026-109619, RCE via stale global state. Request-owned internal state can survive after its memory has been freed, and a later request handled by the same worker may use that stale state before normal initialization resets it.

The practical meaning: these bugs live in the PHP engine, not in your application. Laravel, WordPress, Symfony or hand-written code does not matter. The PHP team says that for mod_php there is a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs, so a web application firewall or tight application code does not save you.

Step 1: find out what you actually run

Do not trust one command. The CLI and the web server can use different PHP builds on the same machine.

# the CLI
php -v

# PHP-FPM (adjust for your version)
php-fpm -v          # or: php-fpm8.3 -v

# Apache: is mod_php loaded?
apachectl -M | grep -i php
Enter fullscreen mode Exit fullscreen mode

If you run containers, check inside the container (docker exec <container> php -v), because the host's PHP is irrelevant to the image.

The version number trap

Linux distributions patch security bugs without changing the upstream version number. On the Ubuntu 24.04 machine I used for testing, php -v reports 8.3.6, but the installed package is 8.3.6-0ubuntu0.24.04.11 and its changelog lists security fixes from 2026. If you compare 8.3.6 to 8.3.36 you will think the server is ancient when it may be fully patched, or the reverse. For distro packages, the changelog is the real answer:

# Debian / Ubuntu
zcat /usr/share/doc/php8.3-cli/changelog.Debian.gz | grep -E "CVE-2026-109618|CVE-2026-109619"
Enter fullscreen mode Exit fullscreen mode

On my test machine this printed nothing (count 0), which means that package had not received the fix yet. For RPM-based systems, rpm -q --changelog php | grep CVE-2026-109618 is the equivalent, but I did not run it. If the grep shows both CVEs, the package has the fix, whatever the version string says.

For builds taken straight from php.net, the version is reliable. Here is a small helper that applies the fixed versions from the advisory (I ran it against a list of sample versions):

<?php
function php_upstream_status(string $v): string {
    $fixed = ['8.5' => '8.5.12', '8.4' => '8.4.27', '8.3' => '8.3.36', '8.2' => '8.2.35'];
    $branch = implode('.', array_slice(explode('.', $v), 0, 2));

    if (!isset($fixed[$branch])) {
        return 'no upstream release for this branch: use a vendor backport or upgrade';
    }

    return version_compare($v, $fixed[$branch], '>=')
        ? 'upstream version includes the fix'
        : "older than {$fixed[$branch]}: update (or confirm a vendor backport)";
}

echo php_upstream_status(PHP_VERSION), PHP_EOL;
Enter fullscreen mode Exit fullscreen mode

It reported 8.3.35 and 8.4.26 as needing the update, and 8.3.36 and 8.4.27 as fixed. Treat it as a first filter for upstream builds, not proof for distro packages.

Step 2: update, then restart

How you update depends on where PHP comes from:

  • Distribution packages: run your normal package update and check your vendor's notice. php.net says distributions and LTS vendors received the patches in advance.
  • Docker: rebuild your image from a patched base tag, not just restart the container. Confirm with php -v inside it.
  • Built from source: get the fixed release from php.net and rebuild.
  • PHP 7.4, 8.0 and 8.1: the PHP team provided minimal source backports, and some vendors ship backports of their own. Better: move to a supported branch.

After the package is updated, restart the processes that serve requests (PHP-FPM, or Apache for mod_php). A running worker keeps the old code in memory until it is restarted.

Hosting platforms and panels

According to Laravel News: Laravel Cloud is patched in place; Forge needs a manual "Update PHP" (or an update over SSH, then confirm with php -v); on Vapor, patched runtimes are live but you must redeploy. It also notes that there is no patch for PHP 8.0 or 8.1 on Forge and Vapor. Plesk lists 8.5.12, 8.4.27, 8.3.36 and 8.2.35 as fixed versions and says the PHP builds arrive through its normal update process. InMotion Hosting says it turned off session.upload_progress.enabled on its managed servers as a precaution while patches roll out. Status changes quickly, so check your own provider's page.

If you cannot update today

php.net is clear that these measures reduce exposure and do not make an installation safe. Use them only to buy a few hours or days. This is the configuration from the advisory:

; php.ini  (apply before request parsing, then restart workers)
memory_limit = -1
post_max_size = 8M          ; 32M only if you need uploads
upload_max_filesize = 8M    ; keep below post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0  ; PHP 8.5 only
Enter fullscreen mode Exit fullscreen mode

Per the advisory, the memory setting is for CVE-2026-109618, together with a container or cgroup memory limit as an availability boundary (and not RLIMIT_AS or RLIMIT_DATA). The upload-progress and backtrace settings are for CVE-2026-109619, and it also asks you to fix fatal errors and execution timeouts that an attacker can reach.

The advisory says to set these "in a way applications can't override." I checked why on PHP 8.3.6, using each setting's access level:

Setting Who can change it Result of ini_set() in my test
memory_limit Anywhere, including application code Succeeded (returned the old value)
post_max_size php.ini and server config only Returned false
session.upload_progress.enabled Per-directory level (php.ini, server config, .user.ini) Returned false; value stayed 0

So application code can raise memory_limit again at runtime. That is why the advisory suggests locking it with php_admin_value in the FPM pool or Apache config. The upload-progress setting cannot be changed with ini_set(), but it is a per-directory setting, which is why the advisory warns against relying on .user.ini and asks for php.ini, the pool or the server configuration. fatal_error_backtraces does not exist in PHP 8.3 (it showed as unavailable), consistent with the "PHP 8.5 only" note.

Is anyone exploiting this?

Sources differ in what they report. php.net says it has a demonstrated exploit for mod_php. The Laravel News article does not report observed attacks in the wild. InMotion says a public exploit appeared before the patch. I could not independently confirm active attacks, and you should not wait for confirmation. If you think a server may already be compromised, update first, then review web server and PHP logs, rotate credentials and keys that were readable by PHP, and restore from a known clean state where you can.

Common questions

Does this affect Laravel specifically?

The flaws are in PHP itself, so every PHP framework and CMS on an unpatched runtime is exposed. There is no Laravel or Composer package update that fixes it.

What about CLI-only scripts and queue workers?

The advisory is about installations serving web requests. The CLI and web server commonly come from the same package, so updating covers both, and I would not leave any server on the old build.

Is PHP 8.2 still OK to run?

8.2.35 contains the fix, but php.net notes PHP 8.2 reaches end of life on 31 December 2026 and gets no security fixes after that. Plan your upgrade now.

Sources


Originally published on DEV Talk.

Top comments (0)