Skip to content

ci: swap broken npm audit for OSV-Scanner + remediate transitive vulns - #5

Merged
pchuri merged 3 commits into
mainfrom
fm/cce-ci-audit-fix
Jul 26, 2026
Merged

pchuri merged 3 commits into
mainfrom
fm/cce-ci-audit-fix

Conversation

@pchuri

@pchuri pchuri commented Jul 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes the broken security CI job and remediates the real vulnerabilities it was hiding.

Root cause of the broken gate

npm audit --audit-level high is unusable against the public npm registry. The advisories/bulk endpoint returns a gzip body without a Content-Encoding header, so npm parses raw gzip as JSON and fails on every npm version:

  • npm 10 → falls back to the retired audits/quick endpoint → 400 Invalid package tree (misleading; unrelated to the lockfile).
  • npm 11+ → surfaces the gzip parse error directly (Unexpected token … is not valid JSON).

Pinning npm or switching to audit-ci/better-npm-audit does not help — they all hit the same broken endpoint.

The swap (ci:)

Replace the npm audit step in the security job with google/osv-scanner-action, pinned to v2.3.8. It scans the committed package-lock.json against the independent OSV.dev database (sidestepping the broken npm endpoint) and blocks the job on discovered vulnerabilities, preserving a real security gate. The node setup / npm ci steps are dropped since the scanner only needs the lockfile.

Vulnerabilities fixed by bumps/overrides (fix(deps):)

The gate was legitimately red — there were real high/critical advisories in the tree. Cleared via npm update (in-range patches) plus targeted overrides:

Package Action Why
tar override ^7.5.22 critical/high in the sqlite3 → node-gyp chain (no 6.x fix exists)
brace-expansion override ^5.0.8 high ReDoS; fix only in 5.0.8
@tootallnate/once override 2.0.1 transitive advisory
@typescript-eslint/typescript-estree → minimatch scoped override 9.0.7 high; scoped to avoid forcing glob's minimatch 3.x
many others (minimatch 3.x/5.x, js-yaml, lodash, handlebars, picomatch, flatted, fast-uri, diff, ajv, glob, ip-address, tar-fs …) npm update in-range patches

All production and non-bundled dev advisories are cleared. type-check, lint, build, and the full test suite (39/39) remain green.

Six documented-ignored advisories (ci: — maintainer decision, 2026-07-26)

Six findings could not be remediated because they live inside npm's frozen bundledDependencies, reached solely through the release-time devDependency @semantic-release/npm → npm. Bundled deps are pinned at npm's own publish time and cannot be changed by npm update or overrides from this repo. (Forcing a newer npm bundle was tested and rejected: it still trails these advisories and requires Node ≥22, breaking the Node 16/18/20 test matrix.)

Per maintainer decision, these are ignored in osv-scanner.toml, scoped to the exact 13 advisory IDs on these six release-only packages — no blanket dev/ecosystem/severity ignore. Each entry carries a written justification (dev/release-only, not in the shipped runtime or build/test path, unfixable from this repo).

Package (bundled via npm) Version Severity Advisory IDs ignored
tar 7.5.11 9.2 critical GHSA-23hp-3jrh-7fpw, GHSA-8x88-c5mf-7j5w, GHSA-gvwx-54wh-qm9j, GHSA-r292-9mhp-454m, GHSA-vmf3-w455-68vh, GHSA-w8wr-v893-vjvp
brace-expansion 2.0.2 7.7 high GHSA-3jxr-9vmj-r5cp, GHSA-f886-m6hf-6m8v, GHSA-mh99-v99m-4gvg
picomatch 4.0.3 7.5 high GHSA-3v7f-55p6-f55p, GHSA-c2c7-rcm5-vvqj
sigstore 3.1.0 7.5 high GHSA-52v5-jr5w-gjxr
@sigstore/core 2.0.0 5.4 moderate GHSA-jfc7-64v2-mr8c
ip-address 10.1.0 5.3 moderate GHSA-v2v4-37r5-5v8g

Gate remains real: verified locally that OSV-Scanner now passes on this repo (exit 0) and still fails (exit 1) on a hypothetical unrelated high (e.g. lodash@4.17.11) — the narrow ID scoping means any new or different advisory, runtime or dev, still blocks the job.

Files changed

  • .github/workflows/ci.yml — audit → OSV-Scanner
  • package.json / package-lock.json — dependency bumps + overrides
  • osv-scanner.toml — narrowly-scoped ignore of the 6 bundled-npm advisories

pchuri added 3 commits July 26, 2026 17:27
npm audit is unusable against the public npm registry: the
advisories/bulk endpoint returns a gzip body without a
Content-Encoding header, so npm fails to parse it on every npm
version (npm 10 falls back to the retired quick endpoint and 400s;
npm 11+ surfaces the gzip parse error). Pinning npm or using
audit-ci/better-npm-audit does not help - they hit the same endpoint.

Swap the audit step for google/osv-scanner-action, which reads the
committed package-lock.json against the independent OSV.dev database
and blocks the job on discovered vulnerabilities, keeping a real
security gate. The node setup / npm ci steps are dropped since the
scanner only needs the lockfile.
Bump in-range dependencies via npm update and add targeted overrides
for transitive advisories that upstream ranges do not yet pull in:

- tar -> ^7.5.22 (fixes critical/high in the sqlite3 -> node-gyp chain)
- brace-expansion -> ^5.0.8
- @tootallnate/once -> 2.0.1
- @typescript-eslint/typescript-estree/minimatch -> 9.0.7

All production and non-bundled dev advisories are cleared. Build,
lint, type-check and the full test suite remain green.

The only findings left are inside npm's frozen bundledDependencies,
pulled in solely by the release-time devDependency @semantic-release/npm.
Those cannot be remediated by bumps or overrides from this repo and are
release-only; they are surfaced for a maintainer decision.
Add osv-scanner.toml scoped to ONLY the 13 advisory IDs affecting the
six packages frozen inside npm's bundledDependencies (reached solely via
the release-time devDependency @semantic-release/npm -> npm): tar 7.5.11,
brace-expansion 2.0.2, picomatch 4.0.3, sigstore 3.1.0, @sigstore/core
2.0.0, ip-address 10.1.0.

Each ignore carries a written justification: dev/release-only, not in the
shipped runtime or the build/test path, and unfixable via bump/override
because bundled deps are frozen at npm's publish time.

No blanket dev/ecosystem/severity ignore is used, so any new or different
advisory still fails the gate. Verified: osv-scanner passes (exit 0) on
this repo and still fails (exit 1) on a hypothetical unrelated high.

Maintainer decision, 2026-07-26.
@pchuri
pchuri merged commit a78e1b4 into main Jul 26, 2026
4 checks passed
pchuri added a commit that referenced this pull request Jul 26, 2026
The security job in ci.yml was migrated to google/osv-scanner-action in
PR #5, but release.yml's own `npm audit --audit-level=high` step was
missed and keeps failing (broken npm-registry advisories endpoint + real
high advisories). Swap it for the identical osv-scanner step (same action
version, same --lockfile arg, same repo-root osv-scanner.toml ignores),
keeping the gate blocking on high/critical. release.yml is now consistent
with ci.yml; semantic-release/publish config unchanged.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant