Three security disclosures in two days, and what patching them took
TL;DR
- If you have a website or an app: make sure everything is up to date. If nobody around you has heard about any of this, that's your cue to start asking questions: who hosts it, what it runs on, and when it was last updated.
- PHP: two critical remote code execution bugs. Update to 8.2.35, 8.3.36, 8.4.27 or 8.5.12 today. 8.1 and older get no fix, so migrate.
- Node.js: ten fixes, four high severity. Rebuild every app and container on 22.23.4, 24.22.1 or 26.12.1, then check the running version.
- eMudhra: a certificate authority's keys can be recovered. Browsers are safe. Update the certificate lists on servers, containers and devices.
- The lesson: the patch is easy, and with an AI agent so is finding everything you run. The real work is old frameworks, which turn a rebuild into a rewrite.
Between Tuesday and Wednesday this week, three things landed at once. A certificate authority turned out to have private keys anyone could recover. PHP shipped fixes for two critical remote code execution bugs. Node.js shipped ten security fixes, four of them high severity. Between my own projects and a few companies I help, I look after fourteen servers, and most of them run at least one of these.
I mentioned all this to a few friends who run businesses, not tech teams, and most of them hadn't heard about any of it. That's why I'm writing it down.
This post covers what each disclosure is, what it means for a company, what to do about it, and what it actually took me. That last part is the useful bit. The advisories make patching sound like a single step. For me it took three days, and the hardest part wasn't in any of the three advisories.
1. PHP: critical, and announced a day ahead
On October 20 the PHP project warned that a critical security release would ship the next day at 14:00 UTC. On the 21st it published PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, fixing two vulnerabilities (CVE-2026-109618 and CVE-2026-109619). Both are rated 9.2 and both allow unauthenticated remote code execution. In plain terms: someone who can send a request to your site may be able to run their own code on your server. Security firms expected mass scanning to start within minutes of the release.
What it means for a company. If you run WordPress, Drupal, MediaWiki, Laravel or any other PHP app that faces the internet, you are in scope. PHP 8.1 and older are end-of-life and get no fix at all, so an old PHP version is now an open door, not just a matter of hygiene. The less obvious lesson is that "managed" hosting varies a lot. AWS's bulletin shows the range inside a single company:
- Elastic Beanstalk with managed platform updates turned on: patched for you.
- Amazon Linux: updated packages are available, but you have to install them.
- Lightsail: "AWS cannot update running Lightsail instances in place." You create a new instance from an updated blueprint and move your site onto it yourself.
And if your Lightsail WordPress came from the older Bitnami blueprints, those stopped getting updates in May. The console now labels them "no longer maintained."
What to do. List every PHP runtime you have, check it with php -v, and move
to a fixed version. Anything on 8.1 or older needs a migration, not a patch. If you can't patch today, a
WAF rule can buy time, but AWS itself calls those compensating controls, not fixes. Plan beyond this
week too: PHP 8.2 stops getting security fixes on December 31, 2026.
What it took me. One of my old sites ran WordPress on Lightsail. I'm a developer, and I hate WordPress and its stupid interface. Lightsail offered no simple update, so the official route was to back the site up with WordPress tools, deploy a new instance, restore it and make sure everything still worked. Instead I asked Claude to copy the website to plain HTML and deploy it on Cloudflare Pages. No PHP, no WordPress, nothing to patch next time.
With an AI agent, copying a website (SEO aside) and deploying it is two prompts.
2. Node.js: the bugs are in the calls you make
Node's October 21
release fixes ten CVEs in the 22, 24 and 26 lines. The four high-severity ones: two ways to get
around TLS certificate hostname checks, an out-of-bounds write in the Brotli decoder that can lead to
code execution, and dns.resolve cutting names short at a NUL character. The release also
updates the bundled CA list for the eMudhra issue below, and OpenSSL on 22 and 24.
What it means for a company. Most of the high-severity bugs sit in outgoing connections: verifying the server you call, and decoding what it sends back. So an internal worker that only calls third-party APIs is in scope too, not just your public web server. That's my reading of the CVE titles; the advisory doesn't give much more detail than that. The other catch is where Node lives. It isn't one install per server. Every container image and every bundled app carries its own copy, so upgrading Node on the host fixes none of them. And versions past end-of-life have the same bugs, they just never get the fix.
What to do. Inventory running Node processes, including inside every container, not
just the node on your PATH. Rebuild on 22.23.4, 24.22.1 or 26.12.1. Then check the version
that is actually running after the rebuild, because a rebuild doesn't always give you the new
version (see below). Anything on Node 20 or older is out of support and needs code changes, not a rebuild.
What it took me. I thought it would take an evening. It took three days.
- The easy part: 28 apps in one evening. Everything on a supported Node line was a rebuild away. I checked them again a day later: all still running, no unexpected restarts.
- "Rebuilt" didn't mean "patched." On two servers, the build tooling carried an old list of Node versions, so a clean rebuild quietly reinstalled the same vulnerable Node. I only caught it because I checked the running version afterwards. The fix was to pin those apps to the current official buildpack. Homebrew also didn't have the new Node yet on release day.
- The second sweep found what the first one missed. Three apps left over from the first round, the Node bundled inside my own product's plugins (re-released with the patched version), and my own laptop. One dead staging app on Node 19 got shut down instead of upgraded.
The hard part was an old platform I look after: four production sites and their staging copies, plus a second server, all on Node 16, which stopped getting fixes in 2023. Luckily I had Claude to take care of the upgrade. But the frameworks they were built on hadn't been updated either, and they didn't support a current Node. So it wasn't a rebuild with the right version number. It needed code rewrites, and far more testing than a rebuild, before each site could go back online.
By the end, every app on the servers I can reach (more than 40, on eight servers) runs a patched Node. The advisory was the reason I finally looked at the old ones.
3. eMudhra: when the trust itself breaks
eMudhra, an Indian certificate authority, generated eight intermediate CA keys so weakly that anyone can recover them, and with them issue a certificate for any website. Browsers blocked them between October 17 and 20, so browsing is fine. The risk is everything else that trusts an old CA list: servers, scripts, containers, mobile apps, VPNs and IoT devices, open to interception on any network an attacker controls.
What to do. Update ca-certificates on every server, rebuild containers, and
update language bundles (Python certifi, Java, Go, Node). On macOS, install the latest
security update.
What it took me. I checked every server for the compromised root in three places: the operating system, each Node runtime, and other language stores. The server operating systems were already clean. Nine places still trusted it, and two were surprises. My Git server shipped its own certificate store inside its container, so the host's update never reached it. And my laptop was two macOS updates behind.
What I take from the week
The patch is the easy part, and so is the inventory. Each fix was one version number. With an AI agent, finding every place that version lived took about an hour: containers, bundled runtimes, plugins, a Git server with its own certificate list, build tools with stale version lists. The real work was the old frameworks.
Check, don't assume. Again and again this week the obvious signal was wrong. A successful rebuild reinstalled the old Node. A "managed" service turned out to mean "you migrate it yourself." An OS upgrade removed the tool that deploys the apps. The only thing I trusted was the version reported by the process that was actually running.
End-of-life is where the risk is. Everything on a supported version took minutes once I found it. The real exposure was in the old things: Node 16, frameworks nobody upgraded, operating systems without updates for years, a WordPress site no one has edited in almost two years. A disclosure is a good excuse to look at those.
The AI's "protections" worked for the attackers. I did all of this with Claude Code. It ran the scans, did the rebuilds and upgrades, read the cloud consoles and checked every version. But in auto mode, where it's supposed to work on its own, Claude refused almost everything that mattered. It wouldn't ssh into my production servers to check their Node version, even after I said "go ahead" in the chat. It wouldn't delete a cloud instance, run an OS upgrade, push a fix to production or set new secrets. When a go-live broke, it diagnosed the problem in minutes, then refused to apply the fix, and I typed it myself while the site was half-down. Each time it asked me to switch the session to manual approval, or to run the command myself. In the end I did both, many times.
I understand why those guardrails exist. But think about who they slow down. When PHP published its fix, security firms expected mass scanning to start within minutes. The attackers' tools are fully automated, and nobody makes them stop and ask permission. Meanwhile the defender's tool refuses to patch the defender's own servers without a human approving each command, late at night, one server at a time. On a day like this, a protection you can't turn off for your own machines doesn't protect you. It gives the attacker a head start. What I want is simple: let me tell the agent, once, "these are my servers, patch them," and let it work as fast as the people scanning for the hole.
I was lucky. None of the websites and apps I manage are big names, even though one of them has more than 200,000 users. I wasn't the most interesting target, and that gave me time. I feel sorry for all the companies that got hit this week.
If you run anything on PHP or Node, or anything that makes TLS connections outside a browser, this week has work for you. Start with the list of what you run. Mine was longer than I thought, and the oldest things on it were the most dangerous.