From 9d5c80eb2e5ee747eb198e4eaccded9b952355f4 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Tue, 3 Nov 2026 16:21:50 +0000 Subject: [PATCH] chore: require Node.js patched for CVE-2026-111497 The CLI ships no Brotli package, but fetch (undici) decompresses Content-Encoding: br responses with Node's bundled Brotli decoder, which CVE-2026-111497 (out-of-bounds write) affects. Raise engines to the first patched release of each supported line and drop Node 20, which is EOL and never received the fix. CI now tests on Node 22 and 24. Co-Authored-By: Claude Opus 5.5 --- .changeset/drop-node-20-brotli.md | 5 +++++ .github/workflows/ci.yml | 2 +- README.md | 2 +- SPECS/README.md | 1 + SPECS/deployment.md | 4 ++-- package-lock.json | 6 +++--- package.json | 2 +- 7 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 .changeset/drop-node-20-brotli.md diff --git a/.changeset/drop-node-20-brotli.md b/.changeset/drop-node-20-brotli.md new file mode 100644 index 0000000..c98ac18 --- /dev/null +++ b/.changeset/drop-node-20-brotli.md @@ -0,0 +1,5 @@ +--- +"@codacy/codacy-cloud-cli": minor +--- + +Require a Node.js runtime patched for CVE-2026-111497 (Brotli decoder out-of-bounds write): `^22.23.4 || ^24.22.1 || >=26.12.1`. Node.js 20 is end-of-life, never got the fix, and is no longer supported. The CLI decompresses Brotli-encoded HTTP responses through Node's bundled decoder, so upgrade Node.js if you are on an older release. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4e5165..4da66df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - node-version: [20, 22] + node-version: [22, 24] steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 diff --git a/README.md b/README.md index 7bd7653..7365a9f 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ npm run update-api # Update the auto-generated API client ### CI/CD -- **CI**: Runs on every push to `main` and on PRs. Builds, smoke-tests the built CLI, and runs the test suite across Node.js 20 and 22. +- **CI**: Runs on every push to `main` and on PRs. Builds, smoke-tests the built CLI, and runs the test suite across Node.js 22 and 24. - **Release**: Uses [changesets](https://github.com/changesets/changesets) for automated versioning and npm publishing. #### Publishing a new version diff --git a/SPECS/README.md b/SPECS/README.md index 41a1f75..34951f1 100644 --- a/SPECS/README.md +++ b/SPECS/README.md @@ -48,6 +48,7 @@ This is the single source of truth for all project tasks and specs. | Date | What was done | |---|---| +| 2026-11-03 | **Node.js engines raised for CVE-2026-111497** (Brotli decoder OOB write, bundled in Node). `engines` `>=20` → `^22.23.4 \|\| ^24.22.1 \|\| >=26.12.1`, the first patched release of each line; Node 20 is EOL and unpatched, so it is dropped. CI matrix `[20, 22]` → `[22, 24]`. No dependency change: the repo ships no Brotli package, but `fetch` (undici) decompresses `Content-Encoding: br` responses with Node's bundled decoder, so the runtime is the exposure. `engines` only warns on install; no runtime version check was added | | 2026-09-30 | (OD-590, OD-784) `fixedVersion` surfaced on `issue`/`issues`/`pull-request --issue`, now that `CommitIssue` carries it (first in API `57.7.9`; counterpart of `codacy-spa` #3145). **API bump: pinned `57.6.4` → `57.7.10`** — a diff of both bundled specs shows only `CommitIssue.fixedVersion` added, the organization webhook operations retagged `organization` → `webhooks` (the CLI uses none of them) and a `hasWebhooksEnabled` field on an organization schema; no operation signatures shifted, so `SPECS/repository-tokens.md`'s whitelist needed no changes. `57.7.9` and `57.7.10` bundle identical specs. `printIssueCard` (list) and `printIssueCodeContext` (detail, shared with `pull-request --issue` and `finding`'s linked-issue block) now pass `issue.fixedVersion` to the existing `formatDependencyChainsLine`/`formatDependencyChainsBlock`, so a direct dependency reads `Direct - Update to ` and a transitive one ends `(Fixed in )`, as on `finding`/`findings`. The param `finding` passes (`SrmItem.fixedVersion`) still wins when non-empty. An empty array (no fix available) renders as before — no version text — rather than adding a "no fix" phrase the other commands don't use. `fixedVersion` added to all three JSON projections (issue.test.ts 24→28, issues.test.ts 76→78, pull-request.test.ts +2) | | 2026-09-23 | (OD-748) `images` shows a **Tags** column (per-image `tagCount`) and an `Image tags: X of Y used` line under the header, read from `listOrganizationImages`' new `usage` object (OD-724, API 57.6.4 — `fetch-api` bumped from 57.4.17). Still one request per page. The line turns red at the cap, where new tags are rejected. Exact figures, not `formatCount`. `--output json` stays an array and gains `tagCount` only; `usage` is not in the JSON, since adding it would change the top-level shape The `image --delete --keep-latest` budget warning now reads that same `usage.limit` from the image-count request it already made, in place of the hardcoded `DEFAULT_ORG_TAG_CAP` (1,000), and drops its "this CLI cannot read the value in force" disclaimer Both commands tolerate a response without `usage`/`tagCount` (an API behind the client), and the exact-figure formatter is now shared as `formatExactCount` (5 new tests, 784 total) | | 2026-09-22 | (OD-710) **Fix: path parameters are now escaped per segment.** Every `image` subcommand 404'd against a namespaced image name — `codacy/codacy-website`, the shape of all seven images in `gh/codacy` — because the generated client falls back to `encodeURI` when `OpenAPI.ENCODE_PATH` is unset, and `encodeURI` leaves `/` intact by design: it encodes whole URLs, not the segments they are built from. The value expanded into two segments and hit a route that does not exist; verified against the API, where the raw slash returns 404 and `%2F` returns 200. `src/utils/api-path.ts` exports `encodePathSegment` (`encodeURIComponent`) and `src/index.ts` installs it beside `OpenAPI.BASE` — the generated client is untouched, so `npm run update-api` cannot undo it. The encoder is global, which is correct rather than incidental: `{branchName}` and `{filePath}` carry slashes for the same reason, though no shipped command sends either as a path parameter today, so nothing else changes shape. Confirmed end to end against `gh/codacy` after the fix: `images` lists 7, `image codacy/codacy-website` lists 84 tags, `--delete --keep-latest 10 --dry-run` reports 74 of 84 (5 new tests, 767 total) | diff --git a/SPECS/deployment.md b/SPECS/deployment.md index 3527044..18dd45a 100644 --- a/SPECS/deployment.md +++ b/SPECS/deployment.md @@ -7,7 +7,7 @@ - **Binary name:** `codacy` (registered in `package.json` under `bin`) - **Included files:** `dist/` and `README.md` (via `files` field) - **Pre-publish:** `prepublishOnly` runs `npm run update-api && npm run build` as a safety net for local publishes -- **Engines:** requires Node.js >= 20 +- **Engines:** requires Node.js `^22.23.4 || ^24.22.1 || >=26.12.1` — the first releases of each line with the bundled-Brotli fix for CVE-2026-111497 (Node 20 is EOL and was never patched) - **Install globally:** `npm install -g "@codacy/codacy-cloud-cli"` ## GitHub Actions @@ -16,7 +16,7 @@ Triggers on: push and pull requests to `main`. -Matrix: Node.js 20, 22. +Matrix: Node.js 22, 24. Jobs: - **build-and-test**: checkout → setup node → install → generate API client → type check → build → smoke test the built CLI → test diff --git a/package-lock.json b/package-lock.json index 3ed3250..b1ed13d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@codacy/codacy-cloud-cli", - "version": "1.9.0", + "version": "1.14.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@codacy/codacy-cloud-cli", - "version": "1.9.0", + "version": "1.14.0", "license": "ISC", "dependencies": { "@codacy/tooling": "0.23.0", @@ -38,7 +38,7 @@ "vitest": "4.0.18" }, "engines": { - "node": ">=20" + "node": "^22.23.4 || ^24.22.1 || >=26.12.1" } }, "node_modules/@apidevtools/json-schema-ref-parser": { diff --git a/package.json b/package.json index 3dd72a1..c826653 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "author": "Codacy (https://www.codacy.com)", "license": "ISC", "engines": { - "node": ">=20" + "node": "^22.23.4 || ^24.22.1 || >=26.12.1" }, "dependencies": { "@codacy/tooling": "0.23.0",