Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/drop-node-20-brotli.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [20, 22]
node-version: [22, 24]

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions SPECS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <pkg> to <version>` and a transitive one ends `(Fixed in <version>)`, 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) |
Expand Down
4 changes: 2 additions & 2 deletions SPECS/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"author": "Codacy <[email protected]> (https://www.codacy.com)",
"license": "ISC",
"engines": {
"node": ">=20"
"node": "^22.23.4 || ^24.22.1 || >=26.12.1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

Add an early startup check for the supported patched Node.js ranges before network or API initialization. The engines field is advisory and does not prevent execution on a vulnerable runtime; the guard should emit a clear upgrade message and exit nonzero for unsupported versions.

TIP React 👍 if this review is right, or reply with what's wrong and how it could be better to help improve the reviewer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not adding a guard in this PR, on purpose: a runtime version check was considered and left out. engines is meant to be advisory here. A hard exit would break the CLI for everyone on an unpatched 22/24 point release, and the realistic exposure (a malicious br body from app.codacy.com / cveawg.mitre.org over verified TLS) is low. If we want enforcement later, a warn-only check is the likely shape, in a separate PR.

🤖 Generated by /pr-fixup command

},
"dependencies": {
"@codacy/tooling": "0.23.0",
Expand Down
Loading