21 Oct 2026 Two critical RCE bugs in PHP core (CVE-2026-109618, CVE-2026-109619). Fixed in 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12. Is my PHP patched? →
Checklamp
Checklist · CVE-2026-109618 / 109619

The patch checklist: PHP RCEs of 21 October 2026

Published · updated

Written for whoever actually has the shell: the order of operations, the commands, and the checks that tell you the patch is live rather than merely installed. Work top to bottom; the first three steps close the hole.

Passive. Public responses only, nothing is attacked. No account. The result is on the page. Honest: if a value is hidden, we say so instead of guessing.
Reading public responses — usually 5–20 seconds

1. Find every PHP that serves traffic

The most common failure with this patch is updating a binary nobody uses. Before touching anything, list what is installed and what the web server points at.

# installed branches (Debian/Ubuntu)
ls /etc/php
dpkg -l | grep -E '^ii\s+php[0-9.]*-(fpm|cli|common)'

# what each FPM pool runs
grep -rh '^listen' /etc/php/*/fpm/pool.d/*.conf

# what Apache loads
apachectl -M 2>/dev/null | grep -i php

# containers and panels
docker ps --format '{{.Names}}\t{{.Image}}'
ls /usr/local/php* /opt/php* 2>/dev/null

Write the list down. Panels (cPanel, Plesk, ISPmanager, Hestia) usually keep their own builds under /opt or /usr/local, and those are exactly the ones apt upgrade does not touch.

2. Patch to the fixed build of each branch

BranchFixed buildTypical command
8.58.5.12apt install --only-upgrade php8.5-fpm
8.48.4.27apt install --only-upgrade php8.4-fpm
8.38.3.36apt install --only-upgrade php8.3-fpm
8.28.2.35apt install --only-upgrade php8.2-fpm

Use the repositories your host or vendor ships — distributions and LTS vendors had these builds before publication. If apt offers nothing new, the branch comes from a third-party repository (Ondrej, Remi, a panel's own repo): update from that source, not from php.net source tarballs in place, unless you built PHP yourself and have the build recipe.

3. Reload the workers — the patch is not live until you do

systemctl reload php8.3-fpm          # graceful: finishes in-flight requests
systemctl restart php8.3-fpm         # if reload does not pick up the new binary
apachectl graceful                   # mod_php

# confirm what the running master actually spawned
ls -l /proc/$(pgrep -o -f 'php-fpm: master')/exe

Deployments that skip this step are the ones that report “patched” while serving the vulnerable build for another week: the old worker keeps the loaded code until it is replaced.

4. Verify — three angles, not one

  1. The binary. php-fpm8.3 -v and php -v. Both should show the fixed build.
  2. The running process. The master's /proc/<pid>/exe must point at the updated binary, with a start time after your update.
  3. From outside. Run an external check. If the site discloses the version, it should now read at or above the fixed build; if it discloses nothing, the report will say “version not disclosed” — expected, and not evidence of failure.

5. If you cannot patch today

The advisory's interim measures reduce the chance of a successful exploit; none of them is a fix. Apply them knowing the cost:

; FPM pool — removes the memory ceiling the attack relies on
php_admin_value[memory_limit] = -1

; lower the request body ceiling: 8M without uploads, 32M with
post_max_size = 8M

memory_limit = -1 also removes the limit that contains ordinary runaway scripts and image processing, so watch memory after you set it. Disabling session.upload_progress appears in early guidance and does not stop the attack — do not count it.

6. Look for evidence of use

A successful exploit does not need to crash a worker, so an empty error log proves nothing. Search for the pattern instead:

# bursts of multipart POSTs, 17-21 October, from one address
awk '$6 ~ /Oct\/2026/ && $7 ~ /:1[7-9]|:2[0-1]/ && $0 ~ /POST/ {print $1, $7, $9}' \
  /var/log/nginx/access.log* | sort | uniq -c | sort -rn | head -30

# memory-exhaustion errors at request start
grep -iE 'allowed memory size|out of memory' /var/log/php*-fpm.log

# files that appeared in upload directories
find /var/www -path '*upload*' -type f -newermt '2026-10-16' -ls 2>/dev/null | head -40

Also check for shell processes with the web user as parent, and for cron entries added under it. If any of that is present, treat it as an incident: rotate credentials, compare files against a checksum baseline (how to build one), and only then close the ticket.

7. Report it in one page

Clients and managers ask one question: “are we patched?” Keep the answer short and dated — branch, fixed build, timestamp of the running process, external check result, and what you looked for when hunting evidence. Save the outside report as a PDF or a share link; it takes a minute and it is what you will be asked for when the next CVE lands.

Questions

How urgent is this compared to other PHP patches this year?

It is a pre-auth remote code execution in core, confirmed by the PHP team, CERT-EU and CISA on the same day. Those are the patches that do not wait for a maintenance window.

Do I have to restart FPM, or is reload enough?

Reload is graceful and normally spawns workers from the new binary, so it is the right first step. Verify the running master's executable; if it still points at the old build, restart.

Is a WAF enough to wait out the patch?

No. The affected code runs before your application, and generic WAF rules for a bug of this shape produce false positives and false negatives in equal measure. It is a compensating control for a short window, not a substitute.

Should I tell my clients before or after patching?

After, with the date and the build number. A message that says “patched on 21 October, build 8.3.36, external check attached” is worth more than a warning that raises a question you cannot answer yet.