From 3c005293056f87a10a36df74157bd47ac3b137b7 Mon Sep 17 00:00:00 2001 From: Charles Beaudin Date: Tue, 27 Oct 2026 16:23:24 -0400 Subject: [PATCH 1/2] Upgrade node version (against CVE-2026-111497) --- .github/workflows/ci.yml | 7 ++++++- .github/workflows/deploy.yml | 7 ++++++- scripts/check-node-version.js | 37 +++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 scripts/check-node-version.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d15d2b..f32af9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,14 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: npm + # Fails on a Node.js whose bundled Brotli is vulnerable to + # CVE-2026-111497 (anything below 22.23.4 on the 22 line). + - name: Check Node.js version + run: node scripts/check-node-version.js + - name: Install dependencies run: npm ci diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 311d1bc..601f5e7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,9 +29,14 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: npm + # Fails on a Node.js whose bundled Brotli is vulnerable to + # CVE-2026-111497 (anything below 22.23.4 on the 22 line). + - name: Check Node.js version + run: node scripts/check-node-version.js + - name: Install dependencies run: npm ci diff --git a/scripts/check-node-version.js b/scripts/check-node-version.js new file mode 100644 index 0000000..75eccb9 --- /dev/null +++ b/scripts/check-node-version.js @@ -0,0 +1,37 @@ +// Fails if the running Node.js bundles a Brotli decoder vulnerable to +// CVE-2026-111497 ("Node2Shell"): a crafted Brotli stream can corrupt +// memory in whatever decompresses it, and the build decompresses one — +// fetch() in fetch-profile-readme.js accepts `Content-Encoding: br`. +// Runs first in ci.yml and deploy.yml, before anything touches the network. +// +// Only release lines with a fix are accepted, each from its first fixed +// version. Node 20 never got a fix, and odd lines (23, 25) are end of life. +// To move to a new line, add its first fixed version here. +// https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497 + +const FIXED = { + 22: [22, 23, 4], + 24: [24, 22, 1], + 26: [26, 12, 1], +}; + +function isFixed(version) { + const parts = version.replace(/^v/, '').split('.').map(Number); + const minimum = FIXED[parts[0]]; + if (!minimum) return false; + for (let i = 1; i < 3; i++) { + if (parts[i] !== minimum[i]) return parts[i] > minimum[i]; + } + return true; +} + +if (require.main === module) { + if (!isFixed(process.version)) { + const accepted = Object.values(FIXED).map((v) => `>=${v.join('.')}`).join(', '); + console.error(`check-node-version.js: Node ${process.version} is vulnerable to CVE-2026-111497; use one of ${accepted}`); + process.exit(1); + } + console.log(`check-node-version.js: Node ${process.version} is not affected by CVE-2026-111497`); +} + +module.exports = {isFixed}; From 948247b7acab07e5754bfb60b45ae095bbb0942b Mon Sep 17 00:00:00 2001 From: Charles Beaudin Date: Thu, 29 Oct 2026 15:46:46 -0400 Subject: [PATCH 2/2] Upgrade node version (against CVE-2026-111497) --- .github/workflows/ci.yml | 5 +++-- .github/workflows/deploy.yml | 5 +++-- .nvmrc | 1 + package.json | 4 ++-- scripts/check-node-version.js | 8 ++++---- 5 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 .nvmrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f32af9a..fbe561f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,11 +27,12 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version-file: .nvmrc + check-latest: true cache: npm # Fails on a Node.js whose bundled Brotli is vulnerable to - # CVE-2026-111497 (anything below 22.23.4 on the 22 line). + # CVE-2026-111497 (see FIXED in scripts/check-node-version.js). - name: Check Node.js version run: node scripts/check-node-version.js diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 601f5e7..b259c3f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,11 +29,12 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version-file: .nvmrc + check-latest: true cache: npm # Fails on a Node.js whose bundled Brotli is vulnerable to - # CVE-2026-111497 (anything below 22.23.4 on the 22 line). + # CVE-2026-111497 (see FIXED in scripts/check-node-version.js). - name: Check Node.js version run: node scripts/check-node-version.js diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/package.json b/package.json index c35f718..67a2bb0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "BSD-3-Clause", "scripts": { "docusaurus": "docusaurus", - "generate": "node scripts/fetch-profile-readme.js", + "generate": "node scripts/check-node-version.js && node scripts/fetch-profile-readme.js", "prestart": "npm run generate", "start": "docusaurus start", "prebuild": "npm run generate", @@ -39,6 +39,6 @@ ] }, "engines": { - "node": ">=20.0" + "node": "^22.23.4 || ^24.22.1 || ^26.12.1" } } diff --git a/scripts/check-node-version.js b/scripts/check-node-version.js index 75eccb9..610b733 100644 --- a/scripts/check-node-version.js +++ b/scripts/check-node-version.js @@ -2,11 +2,13 @@ // CVE-2026-111497 ("Node2Shell"): a crafted Brotli stream can corrupt // memory in whatever decompresses it, and the build decompresses one — // fetch() in fetch-profile-readme.js accepts `Content-Encoding: br`. -// Runs first in ci.yml and deploy.yml, before anything touches the network. +// Runs first in ci.yml and deploy.yml (before npm ci), +// and again via npm run generate. // // Only release lines with a fix are accepted, each from its first fixed // version. Node 20 never got a fix, and odd lines (23, 25) are end of life. -// To move to a new line, add its first fixed version here. +// To move to a new line, add its first fixed version here, then update +// engines in package.json and .nvmrc. // https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497 const FIXED = { @@ -33,5 +35,3 @@ if (require.main === module) { } console.log(`check-node-version.js: Node ${process.version} is not affected by CVE-2026-111497`); } - -module.exports = {isFixed};