Patching PHP for CVE-2026-109618 and CVE-2026-109619 on Ubuntu
Two CVSS 9.2 PHP flaws allow remote code execution. The fixed builds on Ubuntu 24.04 and 26.04, and why PPA PHP never updates itself.
Jacob Søndergaard ·
On 21 October 2026 the PHP project fixed two flaws that give an unauthenticated attacker remote code execution with a single request: CVE-2026-109618 and CVE-2026-109619, both rated CVSS 9.2. Every way of running PHP for the web is affected, PHP-FPM included, and CERT-EU’s advisory reports proofs of concept in circulation. The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.
This post covers what patching means on an Ubuntu 24.04 or 26.04 server, which depends on where your PHP came from. If it came from Ubuntu, the fix is probably already installed or will be by tomorrow. If it came from Ondřej Surý’s PPA or packages.sury.org, nothing on the server will install it until you do, and the way to fix that has a trap in it. Every command here was run on fresh Ubuntu 24.04 and 26.04 servers on the day.
The two flaws
- CVE-2026-109618. If a request runs out of memory while its data is only partly set up, for example while a multipart file upload is being parsed, the cleanup code can free memory that was never initialised and may hold attacker-controlled data.
- CVE-2026-109619. State from one request can outlive its memory, after a fatal error for example, and a later request handled by the same worker can use it before it is reset.
The second is why a restart matters as much as the upgrade: a PHP-FPM worker that was already running keeps the old code until it is replaced. PHP 8.1 and older are past end of life and get no fix from the PHP project. The project published minimal source backports for 7.4, 8.0 and 8.1, but the supported answer is to move to 8.2 or newer.
Which build is the fixed one on Ubuntu
Ubuntu does not move a release to a new PHP minor version. It backports the fix into the version the release shipped and bumps the package revision, so the patched PHP on 24.04 still calls itself 8.3.6 and the patched PHP on 26.04 still calls itself 8.5.4. php -v cannot tell you whether you are patched. The package version can:
| Where PHP comes from | Fixed package version | Published on 21 October |
|---|---|---|
| Ubuntu 24.04 archive, PHP 8.3 | 8.3.6-0ubuntu0.24.04.13 | 13:41 UTC |
| Ubuntu 26.04 archive, PHP 8.5 | 8.5.4-0ubuntu1.5 | 13:41 UTC |
| ondrej/php PPA (24.04) | 8.2.35, 8.3.36, 8.4.27, 8.5.12 | 14:45 UTC |
| packages.sury.org (26.04) | 8.2.35, 8.3.36, 8.4.27, 8.5.12 | same day |
Check what each PHP-FPM on the server is, and where apt would take its next version from. On a server with the third-party source, the second command lists its versions beside Ubuntu’s:
dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\n' 'php*-fpm' | awk '$1 == "ii" { print $2, $3 }'
apt-cache policy php8.3-fpmPatch now
Upgrade every installed PHP package and nothing else. Leaving the rest of the system alone keeps this quick and avoids a reboot:
sudo apt-get update
sudo apt-get install --only-upgrade $(dpkg-query -W -f='${db:Status-Abbrev} ${Package}\n' 'php*' | awk '$1 == "ii" { print $2 }')The PHP-FPM package restarts its service when it is upgraded. Confirm it did: the start time below should be from after the upgrade. If it is not, restart it yourself, once per PHP version on the server:
systemctl show -p ActiveEnterTimestamp php8.3-fpm
sudo systemctl restart php8.3-fpmWhy the third-party PHP was never going to patch itself
Ubuntu enables unattended-upgrades on its server images, and it is easy to read that as “security fixes install themselves”. They do, from Ubuntu. The default policy trusts Ubuntu’s own security pockets and nothing else:
sudo unattended-upgrade --dry-run --debug 2>&1 | grep "Allowed origins"Allowed origins are: o=Ubuntu,a=noble, o=Ubuntu,a=noble-security, o=UbuntuESMApps,a=noble-apps-security, o=UbuntuESM,a=noble-infra-securityA PHP from the ondrej/php PPA or packages.sury.org is not in that list. Both sources had fixed builds out within hours, and a server with the default configuration would not have installed them that day or any day after. The same is true of every package from any third-party repository on the box.
The fix is to add the sources’ origins. These are the Origin: fields of their Release files, LP-PPA-ondrej-php and deb.sury.org; a pattern that matches nothing fails silently, so run the check above again afterwards and look for both names at the end of the line:
sudo tee /etc/apt/apt.conf.d/52php-source-upgrades >/dev/null <<'EOF'
Unattended-Upgrade::Origins-Pattern {
"origin=LP-PPA-ondrej-php";
"origin=deb.sury.org";
};
EOFThe trap: trusting the source can replace Ubuntu’s fix
Each third-party source carries every PHP version, including the one Ubuntu ships, under a higher version number. Once unattended-upgrades trusts the source, it will move that PHP off Ubuntu’s builds and onto the source’s. That is fine when the source’s build is patched. On the day, it was not always: packages.sury.org had 8.5.12 for amd64 but still only 8.5.11 for arm64. On an arm64 26.04 test server, adding the origin made unattended-upgrades replace Ubuntu’s patched 8.5.4-0ubuntu1.5 with sury’s unpatched 8.5.11.
Pin the version Ubuntu ships below the third-party source. apt then takes that version from Ubuntu whenever Ubuntu has it, and takes every other PHP version from the source as before:
sudo tee /etc/apt/preferences.d/php-source >/dev/null <<'EOF'
Package: php8.3 php8.3-*
Pin: release o=LP-PPA-ondrej-php
Pin-Priority: 100
Package: php8.5 php8.5-*
Pin: release o=deb.sury.org
Pin-Priority: 100
EOF
apt-cache policy php8.5-fpmOn 24.04 the version Ubuntu ships is 8.3; on 26.04 it is 8.5. A pin below 1000 never downgrades, so a server whose PHP 8.3 already came from the PPA keeps taking the PPA’s updates.
At the time of writing, the third-party arm64 builds of 8.3, 8.4 and 8.5 were still the unpatched versions while amd64 had the fixes. On an ARM server, such as Hetzner’s CAX line, running a PHP version Ubuntu does not ship, check the installed version after upgrading and apply the stopgap below until the fixed build arrives.
If you cannot patch yet
CERT-EU lists temporary mitigations. They reduce exposure and do not remove the flaws. The two that cost a typical application nothing go in each PHP-FPM pool, as php_admin_flag so the application cannot switch them back with ini_set():
; /etc/php/8.3/fpm/pool.d/<your pool>.conf
php_admin_flag[session.upload_progress.enabled] = off
; PHP 8.5 only
php_admin_flag[fatal_error_backtraces] = offsudo php-fpm8.3 -t
sudo systemctl restart php8.3-fpmsession.upload_progress is the upload progress tracking almost no Laravel application uses. Setting it in a pool changes PHP-FPM only; the CLI keeps its own php.ini. The advisory’s other mitigations, such as capping post_max_size and request sizes at the web server, can break uploads, so weigh them against your application before applying them. And restart the workers after any change: the advisory is explicit that only fresh workers are protected.
What Provisore does about it
Provisore installs every PHP version Ubuntu does not ship from ondrej/php on 24.04 and packages.sury.org on 26.04, and every server it manages relied on unattended-upgrades, so those versions had exactly the gap described above. Each server with that source now has both origins added and the version Ubuntu ships pinned to Ubuntu’s builds, written on every PHP deploy and rolled out to existing servers. The rollout also upgrades the installed PHP packages straight away rather than at the next daily run. See the runtimes documentation for where each PHP version comes from.