On the morning of 21 October 2026, our team's phones lit up within minutes of each other. The PHP project had shipped 8.2.35, 8.3.36, 8.4.27 and 8.5.12 to kill two critical remote-code-execution bugs — CVE-2026-109618 and CVE-2026-109619, both rated 9.2 out of 10. An hour later, Node.js published its own set: 22.23.4, 24.22.1 and 26.12.1, closing ten vulnerabilities including a Brotli decoder bug that lets an attacker run code inside your Node process.
Two of the world's most widely deployed runtimes, patched on the same day, for flaws that end with someone else's code running on your server. Proof-of-concept exploits for the PHP bugs started circulating within hours (CERT-EU, 21 Oct 2026), so the usual "we'll patch it in the next maintenance window" thinking didn't apply.
We patched our own Laravel backend on an AlmaLinux 8 VPS that same morning, and we kept the terminal log. This article is that log turned into a proper walkthrough: what actually broke, which versions get a fix, and the exact commands for each version — including the awkward cases nobody writes about, like servers running five PHP versions side by side.
Our take up front: this was not a "check php.net when you get a minute" release. The PHP Foundation itself said updating is the only safe choice — there are no complete workarounds. If you read one line of this article, make it this: find out what PHP and Node versions your servers run tonight, and patch anything on the list below before the weekend.
Section 1 — Patching PHP: every version, step by step
Who needs what
| Your PHP version | Patched version | What to do |
|---|---|---|
| 8.5.x | 8.5.12 | Update |
| 8.4.x | 8.4.27 | Update |
| 8.3.x | 8.3.36 | Update |
| 8.2.x | 8.2.35 | Update |
| 8.1 and older | No official fix | Migrate to 8.2+, or use your distro's backported patch |
Both bugs affect PHP going back decades (LWN, 21 Oct 2026), but the PHP project only ships fixes for supported lines. For 7.4, 8.0 and 8.1 it released reference patches so Linux vendors can backport them — meaning your distro might have a fixed package for an old version, but your own app does not get out of upgrading for free.
The two bugs, in plain language (PHP Foundation, 21 Oct 2026):
- CVE-2026-109618 — RCE via out-of-memory corruption. If a request hits PHP's
memory_limitat exactly the wrong instant, PHP can mistake half-initialised junk for real data and corrupt memory. On Apache with mod_php, a single unauthenticated request can trigger this before your application code even runs. - CVE-2026-109619 — RCE via stale global state. A fatal error at the wrong moment leaves a worker holding pointers to memory that has already been freed. The next request on that worker can use it. Use-after-free, worker crash, and demonstrated code execution.
PHP-FPM (the setup most of us run) is also confirmed exploitable through application code paths — so "we use FPM, not mod_php" is not a defence.
Step 0 — Find out what you're actually running, and back it up
This sounds obvious, but multi-version servers are everywhere. Our own VPS was running nine PHP-FPM services side by side (5.6 through 8.3), which we only discovered when we looked:
php -v # CLI PHP — the version your cron jobs and artisan use
php artisan --version # if it's a Laravel app, note the framework version too
# Every PHP-FPM pool on the box — this is what actually serves web traffic
systemctl list-units --type=service --all | grep -Ei 'php.*fpm|httpd|nginx'
# Apache and its PHP mode (mod_php vs proxy_fcgi)
httpd -v
apachectl -M 2>/dev/null | grep -i php
Then take a backup before touching anything:
mkdir -p /home/backups
zip -r /home/backups/site-backup-$(date +%Y%m%d-%H%M%S).zip /home/your-app
mysqldump -u dbuser -p dbname > /home/backups/db-$(date +%Y%m%d-%H%M%S).sql
Our take: the backup step is where people cut corners, and it costs them the one time a patch collides with an old library. Five minutes of zip has saved us hours of panic more than once.
Step 1 — Patch on RHEL / AlmaLinux / Rocky (Remi repo)
This is the path we ran. On RHEL-family servers, PHP usually comes from Remi's repository, and each minor version is its own package set. The catch: dnf update php only touches the default PHP, not the side-by-side SCL packages (php74-php-fpm, php82-php-fpm, …). You have to name each one.
# Make sure the Remi repo is current, then update your active PHP line
dnf install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm # skip if already installed
dnf module reset php -y
dnf module install php:remi-8.2 -y # the line your app uses
# Update every side-by-side PHP version you serve traffic with
dnf update -y php82-php* # PHP 8.2 -> 8.2.35
dnf update -y php83-php* # PHP 8.3 -> 8.3.36
dnf update -y php81-php* # 8.1: only if Remi ships a backported build
Then restart the FPM services — a patch that isn't restarted is a patch that isn't applied:
systemctl restart php82-php-fpm php83-php-fpm
systemctl status php82-php-fpm --no-pager
Step 2 — Patch on Ubuntu / Debian (Ondřej Surý's PPA)
Most Ubuntu PHP comes from the ondrej/php PPA (this is what Laravel Forge and many VPS panels use). Note that Forge's own advisory warns its automatic security updates do not cover PHP — you have to do this by hand (Laravel Forge, 21 Oct 2026):
sudo apt update
sudo apt install --only-upgrade php8.2 php8.2-fpm # -> 8.2.35
sudo apt install --only-upgrade php8.3 php8.3-fpm # -> 8.3.36
sudo apt install --only-upgrade php8.4 php8.4-fpm # -> 8.4.27
sudo apt install --only-upgrade php8.5 php8.5-fpm # -> 8.5.12
sudo systemctl restart php8.2-fpm php8.3-fpm
If you run Apache with mod_php, one extra line matters more than any other today, because mod_php is the highest-risk configuration:
sudo systemctl restart apache2
Step 3 — Patch on shared hosting / cPanel / Plesk
If you don't control the server root, your host's "MultiPHP Manager" is the fix. Switch each domain to the newest patched version it offers (8.2.35 or better), or open a support ticket asking for the October 2026 PHP security release. Do not accept "PHP 8.2" as an answer — ask for the full version number.
Step 4 — Running 8.1 or older? There is no official patch
This is the uncomfortable row in the table. PHP 8.1 ended security support on 31 December 2025, and 7.4 long before that. Your options, in order of preference:
-
Upgrade the app to PHP 8.2+ — for a Laravel app this is the real fix. Test on a staging box first:
composer check-platform-reqs # confirms your dependencies accept the new PHP php artisan about # sanity check after the switch php artisan optimize:clear # flush stale config/views compiled for the old runtime - Wait for your distro's backport — Remi and Surý have historically backported critical fixes into their old-version packages. Run
dnf update php81-php*or the apt equivalent and checkphp -vfor a patched build. - Isolate meanwhile — CERT-EU's advice for unpatchable, internet-facing apps: pull them off the public internet until they're fixed (CERT-EU, 21 Oct 2026). Unpopular advice, correct advice.
Step 5 — Verify the patch actually landed
The number on the terminal is the only proof that counts:
php -v # must read 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12
php -m # extension list intact
composer check-platform-reqs
php artisan optimize:clear && php artisan about
curl -sI https://your-site.com | head -5 # app still answers 200
Our take: on our server the whole thing took under twenty minutes, because the panic was spent before it started — on checking which of the nine PHP versions actually served the admin panel. That inventory step is worth more than any patch script.
Section 2 — Patching Node.js: every version, step by step
Who needs what
| Your Node version | Patched version | What to do |
|---|---|---|
| 26.x | 26.12.1 | Update |
| 24.x (LTS) | 24.22.1 | Update |
| 22.x (LTS) | 22.23.4 | Update |
| 20.x and older | No fix — EOL since 30 April 2026 | Migrate to 22 or 24 |
Node fixed ten issues in one release (Node.js project, 21 Oct 2026). The one to lose sleep over:
- CVE-2026-111497 — Brotli decoder RCE (High). Malformed Brotli data causes an out-of-bounds write; researchers demonstrated memory disclosure and command execution inside the Node process (Vercel advisory, 21 Oct 2026). Your app is exposed whenever it decompresses Brotli data an attacker controls — a request body, or a response your code fetches.
- CVE-2026-105483 / CVE-2026-106069 — TLS certificate hostname bypasses (High). Crafted hostnames (fullwidth digits, loosely-resolving IPs) can slip past certificate checks — a man-in-the-middle's favourite.
- CVE-2026-105482 —
dns.resolveNUL-byte truncation (High), plus medium and low fixes in HTTP keep-alive, crypto snapshot caches, and the permission model.
Unlike the PHP bugs, no exploitation in the wild had been reported at release — but the Brotli bug is exactly the kind that gets a working exploit within days. Node also updated bundled OpenSSL (3.5.9), Undici, c-ares, SQLite and the root CA store, so the runtime itself carries the fixes; you don't need to wait for your dependencies.
Step 1 — Find your version
node -v
which node # system install, nvm, or a package manager?
pm2 list # if you run PM2, note what's running before you touch anything
Step 2a — Patch via nvm (most common on VPSes)
nvm install 22.23.4 # or 24.22.1 / 26.12.1 for your line
nvm alias default 22.23.4
nvm use 22.23.4
node -v # confirm the new number
pm2 restart all && pm2 save # processes keep the OLD binary until restarted
Step 2b — Patch a system install (NodeSource)
sudo apt update && sudo apt install --only-upgrade nodejs # Debian/Ubuntu
sudo dnf module install nodejs:22 # RHEL/AlmaLinux
sudo dnf update -y nodejs
node -v
Step 2c — Patch Docker images
The patch lives in the base image, so rebuild and redeploy — restarting a container is not enough:
FROM node:22.23.4-slim # was node:22-slim — pin the patched version
docker build -t your-app:patched .
docker compose up -d --build
Step 3 — Running Node 20 or older? No fix is coming
Node 20 reached end of life on 30 April 2026 (Konfirmity advisory, 22 Oct 2026), and 18 is far behind. The migration is usually gentler than teams fear:
nvm install 24.22.1
nvm use 24.22.1
rm -rf node_modules && npm ci # rebuild native modules against the new runtime
npm audit fix # while you're here
npm test # then flip engines/package.json and redeploy
Our take: the Brotli bug is sneaky because most teams say "we never decode Brotli" — then discover their HTTP client happily decompresses Brotli responses from third-party APIs. The runtime patch covers the fetched-response path, which is one more reason the version bump is not optional even if you think you're not exposed.
The one-page checklist
- PHP: 8.2 → 8.2.35, 8.3 → 8.3.36, 8.4 → 8.4.27, 8.5 → 8.5.12. 8.1 and older: migrate or isolate. Restart php-fpm/apache after updating, then
php -v. - Node: 22 → 22.23.4, 24 → 24.22.1, 26 → 26.12.1. 20 and older: move to 22/24. Rebuild Docker images;
pm2 restart allafter switching binaries. - Both: backup first, inventory all runtimes on the box (not just the one you remember), verify with your own eyes, then clear application caches.
- After patching: rotate anything suspicious in your logs, and set a weekly
php -v/node -vdrift check so the next emergency doesn't find you guessing.
Patch days like this one are becoming the rhythm of the industry, not the exception — both ecosystems fixed unrelated-but-equal emergencies on the same day. The teams that come through fine are not the ones with the cleverest scripts; they're the ones that knew exactly what was running before the advisory dropped.
If you'd rather have someone else run this drill on your servers — or want a patch-management review before the next CVE lands — reach us at info@devaigo.com or call +91 9625208088.



