Repository navigation
chore(ci): pin CI/publish Node to 24.22.3 (floor 22.23.5), raise engines floor - #571
SavioBS629 wants to merge 2 commits into
Conversation
…to 22.23.4 CI, publish, and release workflows were building, testing, and publishing on floating and EOL Node tags (22.x, lts/*), which can silently resolve to Node releases carrying known CVEs. Following the October-2026 Node security release that fixed the Brotli decoder out-of-bounds write (CVE-2026-111497), this pins every workflow to Node 24.22.1 and runs CI against a fixed matrix of 22.23.4 (supported floor) and 24.22.1 (target). - .github/workflows/mcp-ci.yml: matrix node-version [22.x] -> [22.23.4, 24.22.1] - .github/workflows/npm-publish.yml: 22.x -> 24.22.1 - .github/workflows/beta-release.yml: 22.x -> 24.22.1 - .github/workflows/bump-version.yml: 22.x -> 24.22.1 - .github/workflows/mcp-registry-publish.yml: "lts/*" -> 24.22.1 - package.json: engines.node ">=20.9.0" -> ">=22.23.4" The engines field stays advisory (no engine-strict / .npmrc), so customers on older Node get a warning, not a hard install failure. node-version-notice.ts is intentionally left unchanged: its major-22 floor is correct now that Node 22 LTS is patched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
sarve-shreyas
left a comment
There was a problem hiding this comment.
Reviewed the full diff at d2e9c43 (6 one-line changes vs main; it merges cleanly with current main).
Verified: both pinned versions exist and are the 2026-10-20 security releases, and both carry the CVE-2026-111497 Brotli fix named in the description (checked against the Node changelogs).
Local run (stand-in for the CI matrix): on Node 24.7.0 (npm 11), npm ci, eslint and tsc --noEmit pass, and vitest passes 143 files / 2112 tests. On Node 22.15.0, tsc passes, all 2112 tests pass and npm run check:contract passes. I didn't have 22.23.4 or 24.22.1 installed, so these are same-major stand-ins. There were no failures at all on 22 or 24, so the ~27 failures in the description look specific to Node 20.9.0.
Note: mcp-ci.yml only runs on an approved review (pull_request_review + state == 'approved'), so the new matrix hasn't run on this PR yet. It first runs when someone approves.
Findings outside the diff (non-blocking):
.nvmrcis stillv22.1.0, below the new floor and older than the Brotli fix.nvm usein the repo puts devs on a runtime this PR calls vulnerable, and npm printsEBADENGINE. Bump it with the rest. It could also become the single pin the workflows read (see the inline comment onnpm-publish.yml).package-lock.jsonstill has>=20.9.0in the rootpackages[""].engines.npm cidoesn't care (it only compares dependency versions, and it installed fine on Node 24), but the nextnpm installrewrites it and an unrelated PR picks up the change.npm install --package-lock-onlyfixes it here.- The docs disagree with the new floor:
llms-install.md:12says "Node.js 20.9 or newer", andREADME.md:57-58says ">= 22" and recommendsv22.15.0, which is below the new floor. - Nit, pre-existing:
bump-version.ymlpinsactions/setup-node@v4by tag, not by SHA like the other four workflows. Optional while you're in there.
| strategy: | ||
| matrix: | ||
| node-version: [22.x] | ||
| node-version: [22.23.4, 24.22.1] |
There was a problem hiding this comment.
Blocking: these pins are already one security release behind. Node shipped 24.22.3 (2026-11-10) and 22.23.5 (2026-11-11). Both are marked as security releases in nodejs.org/dist/index.json and fix a batch of High-severity http2/tls/http CVEs (e.g. CVE-2026-123864 and CVE-2026-123872; 24.22.3 also fixes CVE-2026-126051, a remotely reachable TLS server crash).
Scenario: if this merges as-is, CI, npm publish, beta release, version bump and registry publish all run on runtimes that a newer Node security release replaces. The description sets out to prevent exactly that.
Suggestion: bump to 22.23.5 / 24.22.3 here and in the four other workflows. If you keep the engines floor patch-precise, bump it too (see the comment on package.json).
| ], | ||
| "engines": { | ||
| "node": ">=20.9.0" | ||
| "node": ">=22.23.4" |
There was a problem hiding this comment.
Non-blocking: two things about the floor.
- Because it's patch-precise, it goes stale with every Node security release (22.23.5 already replaces 22.23.4). If the goal is "run a patched Node", the CI pins already do that. The advisory floor could stay at a release-line boundary such as
>=22, which also matchesnode-version-notice.ts, so it doesn't need a bump every month. If you'd rather keep it patch-precise, make it>=22.23.5. - "Never a hard failure" only holds with the default npm config. Consumers who set
engine-strict=truethemselves (some enterprise setups do) will getEBADENGINEas an error when they runnpx @browserstack/mcp-serveron Node 20 or on 22 below the floor. Worth a line in the release notes for the version that ships this.
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | ||
| with: | ||
| node-version: 22.x | ||
| node-version: 24.22.1 |
There was a problem hiding this comment.
Non-blocking: 24.22.1 is now hardcoded in four workflows, plus two versions in the CI matrix, and nothing bumps them. Every Node security release means editing six places, and missing one puts us back where the comment on mcp-ci.yml is. Two options:
- Put the target in
.nvmrc(stillv22.1.0today) and usenode-version-file: .nvmrcin the publish and release workflows. A bump is then one line, and localnvm usematches what we publish with. - Or keep a release-line spec (
24.x) and addcheck-latest: true. A spec like22.xlags because setup-node uses the runner image's cached Node first whencheck-latestis false (the default). With it on, every run resolves the newest patch. Less deterministic, but never stale.
Either is fine; the first matches the PR's goal of deterministic builds.
| uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 | ||
| with: | ||
| node-version: "lts/*" | ||
| node-version: 24.22.1 |
There was a problem hiding this comment.
Non-blocking (description accuracy): lts/* wasn't EOL. Node 26 became LTS on 2026-10-28, so this workflow currently runs on 26.13.1, and this change moves it back to 24. That's fine if the intent is one runtime across all publish jobs, but the description should say so rather than "EOL". The same goes for 22.x: Node 22 is in maintenance LTS until April 2027.
…eases) Node shipped 24.22.3 (Nov 10) and 22.23.5 (Nov 11) as security releases. Move every pinned runtime onto them so CI, publish, and release builds stay on current, patched Node. - mcp-ci matrix -> [22.23.5, 24.22.3] - npm-publish / beta-release / bump-version / mcp-registry-publish -> 24.22.3 - bump-version: pin actions/setup-node to its v4.4.0 SHA (was moving @v4) - engines floor -> >=22.23.5 (advisory; no engine-strict) - .nvmrc -> 24.22.3 (was v22.1.0); README / llms-install doc floor refreshed Exact pins, no floating tags. Full build/test/boot verified on Node 22.23.5 and 24.22.3: 2112 tests, contract gate, tsc, and a stdio initialize+tools/list handshake (52 tools) all pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sarve-shreyas
left a comment
There was a problem hiding this comment.
Approved at 26c1216.
Re-reviewed d2e9c43..26c1216. At this head, npm ci, tsc --noEmit, vitest (143 files / 2112 tests) and npm run check:contract pass on Node 24.7.0.
Resolved:
- All six pins are now
22.23.5/24.22.3, the latest Node security releases as of today. .nvmrcis now24.22.3.- The README and
llms-install.mdgive the new minimum. - The lockfile root
enginesmatchespackage.json. bump-version.ymlpinssetup-nodeby SHA.- The description has the
engine-strict/Yarn caveat and the note on the in-client notice.
Accepted as-is: exact pins in each workflow rather than one node-version-file (the ticket requires exact pins), and the patch-precise >=22.23.5 minimum (advisory, documented). The follow-up for automated bumps (Renovate/Dependabot) is noted in the description.
Nit, no change needed to merge: the first line of the description still says "floating and EOL Node tags".
What
Stop building, testing, and publishing on floating and EOL Node tags, and raise the
enginesfloor. Changes:.github/workflows/mcp-ci.yml— test matrix[22.x]→[22.23.5, 24.22.3](stays a matrix; both run).github/workflows/npm-publish.yml—22.x→24.22.3.github/workflows/beta-release.yml—22.x→24.22.3.github/workflows/bump-version.yml—22.x→24.22.3, and pinactions/setup-nodeto itsv4.4.0SHA (was the moving@v4tag; now matches the other workflows).github/workflows/mcp-registry-publish.yml—"lts/*"→24.22.3package.json—engines.node">=20.9.0"→">=22.23.5".nvmrc—v22.1.0→24.22.3(local dev default now matches the target)README.md/llms-install.md— stated Node floor refreshed off20.9/22.15.0Target Node is 24.22.3; 22.23.5 is the supported floor. All pins are exact — no floating tags (
22.x,lts/*,@v4).Why
22.xandlts/*are floating: they resolve to whatever Node the runner last cached, andlts/*will roll onto the next LTS line on its own. That non-determinism is the problem — it can silently land CI/publish on an unpatched or wrong-major runtime. Pinning to the current patch releases (24.22.3 / 22.23.5, both shipped this week) makes CI, publish, and release builds deterministic and keeps them on supported, patched Node.Advisory, not breaking
The
enginesfield stays advisory — noengine-strict, no.npmrcchange:EBADENGINEwarning and install/run normally.engine-strict=true, will fail the install on the mismatch (--ignore-enginesoverrides). Rare for an npx-launched MCP server, but a real hard failure — called out here and worth a line in release notes.src/lib/node-version-notice.tsis intentionally left unchanged. Its in-client notice fires below major 22, which is looser than the>=22.23.5floor — users on 22.0–22.23.4 get npm's install warning but no in-client notice. Deliberate: the notice nudges off EOL majors; the exact patch floor is advisory viaengines.Pin maintenance
Exact pins go stale on each Node security release. This PR keeps explicit exact pins per the requirement (no floating tags). Centralizing future bumps — e.g. a Dependabot/Renovate rule for workflow
node-versionand theactions/*SHAs — is a sensible follow-up, out of scope here.Validation
Full build + test + boot run locally on both pinned versions (fresh
npm cieach):npm ciEBADENGINEnpm test(vitest)npm run check:contracttscbuildinitialize+tools/listnpm ciemits only anEBADENGINEwarning and installs.main(no conflicts).🤖 Generated with Claude Code