Skip to content

Upgrade from EOL Node 20 to Node 24 for CVE-2026-111497 - #44

Merged
manggit merged 2 commits into
masterfrom
critical-node-upgrade
Oct 23, 2026
Merged

manggit merged 2 commits into
masterfrom
critical-node-upgrade

Conversation

@manggit

@manggit manggit commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This app runs on Node 20 everywhere: .nvmrc, CI, the deploy workflow and the App Engine runtime: nodejs20. Node 20 is end-of-life and gets no fix for CVE-2026-111497. That CVE is a high-severity out-of-bounds write in the Brotli decoder bundled with Node, reachable through node:zlib. Patched releases are 22.23.4, 24.22.1 and 26.12.1.

This PR moves the app to Node 24, the active LTS line:

  • .nvmrc: v20 → v24
  • package.json engines: >=20.0.0 → >=24.0.0
  • app-template.yaml: runtime: nodejs20 → nodejs24. App Engine applies Node patch updates for the runtime.
  • lint-and-test.yml and deploy.yml: node-version: 20 → 24

CI fixes

CI was broken before this change, so this PR also fixes it:

  • Retired actions: GitHub now automatically fails jobs that use actions/cache@v2. lint-and-test.yml now uses v4 of actions/cache, actions/checkout and actions/setup-node. The cache key prefix moves from v1- to v2-, so a node_modules built under Node 20 isn't restored under Node 24.
  • Client tests: yarn test:client failed with SyntaxError: Unexpected token '<' on Node 20.20+, 22 and 24. Mocha 10 loads test files with import(), and newer Node treats a .js file containing import statements as an ES module. That skips @babel/register, so the JSX in the tests is never transpiled. test:client now passes --node-option no-experimental-detect-module to mocha, which affects the client tests only.
    • Upgrading to mocha 10.8.2 doesn't fix this.
    • "type": "commonjs" makes the tests pass, but webpack then rejects the ESM in src/client, so the build fails.

Testing on Node 24.22.1

  • yarn lint, yarn test:server and yarn test:client pass locally and in CI.
  • yarn build compiles.
  • The server boots and serves / with a 200.

Known follow-up

The tests don't run on Node 26 yet. The old yargs that mocha depends on crashes on startup with require is not defined in ES module scope. Nothing here targets 26, so I left it for a dependency upgrade when the app moves to 26.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KW4XMLaQFJA9YEDWY1ZJwL

Node 20 is end-of-life and receives no fix for the Brotli decoder
out-of-bounds write (CVE-2026-111497). Move local, CI, deploy and the
App Engine runtime to Node 24, whose 24.22.1 release carries the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KW4XMLaQFJA9YEDWY1ZJwL
@manggit
manggit requested a review from a team October 23, 2026 15:54
GitHub now hard-fails jobs using actions/cache@v2, so bump cache,
checkout and setup-node to v4, and bump the cache key so node_modules
built under Node 20 aren't restored under Node 24.

Newer Node detects ESM syntax in .js files, so mocha's import() of the
client tests loaded them as ES modules and bypassed @babel/register,
failing on JSX. Disable module syntax detection for the client tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KW4XMLaQFJA9YEDWY1ZJwL
@manggit
manggit merged commit 22a8796 into master Oct 23, 2026
3 checks passed
@manggit
manggit deleted the critical-node-upgrade branch October 23, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants