claude-code

A CVE Email Turned Into a Server Cleanup Day

DigitalOcean flagged a Node.js Brotli RCE on my droplet. I pointed Claude Code at the box, asked for a report before any fixes, and ended the day patched, locked down and 13 GB lighter.

Pixel art of a dim room with a beige CRT and tower PC on a desk, a server rack behind them, pink cabling across the floor

Friday morning DigitalOcean emailed me about CVE-2026-111497, a remote code execution bug in how Node.js decompresses Brotli. Fixed in 24.22.1. My droplet runs about a dozen side projects, so "update Node" is not one command.

I opened Claude Code and gave it one rule: SSH in, tell me what's affected, and don't fix anything until I say so.

The report

Thirteen Node apps. Some under PM2, most in Docker.

Claude also found a major issue, Docker publishes ports in iptables ahead of UFW, so every container was reachable directly on the public IP, skipping Cloudflare entirely. My firewall said SSH only. We fixed that first.

How we worked

Every change went in as a PR opened from the server. I merged on GitHub, the server pulled main. That surfaced the embarrassing stuff: a week of feature work running in production that never got committed, a domain change that only lived on the box, a live SQLite database tracked in git.

Test builds caught the real Node 24 problem before anything shipped. Six projects ran better-sqlite3 versions with no Node 24 build. Bumped them, rebuilt, and checked that each image could actually open a database.

Things it found that I didn't ask about

  • E2E tests on Laser Map Studio had been red since September. Playwright was sending a test header to the CDNs too, and once I added SRI the browser started preflighting those requests.
  • My weekly Overture data bump had failed four Mondays straight because GitHub Actions wasn't allowed to open PRs. One setting.
  • A Flask debugger running in production, on a port that was public until that morning.

It also found four dead services. One was serving data last updated in January. Archived, torn down, one domain redirected.

Where it messed up

It restarted the Cloudflare tunnel while I was using one of the sites. Thirty seconds of downtime is fine, the surprise wasn't. It also asked me to merge two PRs with red CI because each one fixed the other's failure. Correct, but I wasn't thrilled. Both times it owned it and changed how it worked for the rest of the day.

End state

  • Everything on Node 24.22.1
  • Host Node now comes from apt, so the next patch is one command
  • Ubuntu updated, rebooted, and every service came back on its own
  • About 13 GB freed

The CVE took maybe an hour. The rest was years of hobby-project drift. Left alone I would have patched Node and called it done. Claude helped me keep it clean.

That's practical AI to me. Hand it the boring ops work, keep the merge button.