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.
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
| Branch | Fixed build | Typical command |
|---|---|---|
| 8.5 | 8.5.12 | apt install --only-upgrade php8.5-fpm |
| 8.4 | 8.4.27 | apt install --only-upgrade php8.4-fpm |
| 8.3 | 8.3.36 | apt install --only-upgrade php8.3-fpm |
| 8.2 | 8.2.35 | apt 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
- The binary.
php-fpm8.3 -vandphp -v. Both should show the fixed build. - The running process. The master's
/proc/<pid>/exemust point at the updated binary, with a start time after your update. - 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.