Skip to content

fix: resolve high-severity npm audit vulnerabilities (brace-expansion DoS) - #755

Merged
yxxhero merged 1 commit into
mainfrom
fix/npm-audit-brace-expansion
Jul 27, 2026
Merged

fix: resolve high-severity npm audit vulnerabilities (brace-expansion DoS)#755
yxxhero merged 1 commit into
mainfrom
fix/npm-audit-brace-expansion

Conversation

@yxxhero

@yxxhero yxxhero commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the npm audit --audit-level=high step that fails Basic validation on main and every dependabot PR (including #753).

npm audit now reports 0 vulnerabilities (was 31 high). Build, lint, format-check and tests (37/37) all pass.

Root cause

GHSA-mh99-v99m-4gvg / CVE-2026-14257brace-expansion DoS via unbounded expansion. The advisory has a single range >=0, <5.0.8, so every brace-expansion below 5.0.8 is vulnerable (no patched 1.x/2.x line). All 31 flagged packages were transitive dependents of it.

The patched 5.0.8 is API-incompatible with minimatch@3/@9, which are used by:

  • eslint@9 (@eslint/config-array pins minimatch@3) → needs eslint@10 (uses minimatch@10)
  • jest@30 (glob@10.5minimatch@9; babel-plugin-istanbultest-exclude@6glob@7minimatch@3)

@typescript-eslint@8.65.0 already declares eslint: ^8.57.0 || ^9.0.0 || ^10.0.0, so the eslint@10 path is supported.

Changes

  • eslint ^9 → ^10, @eslint/js ^9 → ^10 — natively pulls minimatch@10 + brace-expansion@5, clearing the eslint tree.
  • Rewrote eslint.config.js as a pure flat config, dropping the FlatCompat/@eslint/eslintrc layer (eslint@10's @eslint/eslintrc would otherwise still drag in vulnerable minimatch@3).
  • Removed unused eslint-plugin-github (never referenced by the config) — it pulled old minimatch@3/@9, a stale bundled typescript-eslint@8.16.0, and was itself flagged by the audit.
  • Added eslint-config-prettier@10 (previously only present transitively via eslint-plugin-github) to preserve the previous extends behavior.
  • Added overrides to clear the remaining jest-tree vulns:
    • brace-expansion ^5.0.8, glob ^11.0.1, test-exclude ^8.0.0
    • @typescript-eslint/utils ^8.65.0 — forces eslint-plugin-jest's older transitive copy to dedupe to the eslint@10-compatible release.
  • Disabled eslint@10's new no-useless-assignment rule (see comment in config) to avoid churning the bundled dist/ for an unrelated audit fix.

src/ and dist/ are untouched, so Check dist/ remains valid.

Verification (local, node 24.x)

step result
npm ci --ignore-scripts OK
npm run format-check OK
npm run lint OK
npm run build OK
npm test OK 37/37
npm audit --audit-level=high OK 0 vulnerabilities

Relationship to #753

This is intentionally kept separate from #753 (the eslint-plugin-jest 29.15.5 → 29.16.0 bump). eslint-plugin-jest is left at ^29.15.5 here (it already supports eslint@10). Once this merges, #753 rebases onto a green main and its Audit packages step will pass.

… DoS)

Root cause: GHSA-mh99-v99m-4gvg (CVE-2026-14257) — brace-expansion DoS via
unbounded expansion. The advisory affects every version < 5.0.8 (single
range `>=0, <5.0.8`), and 5.0.8+ is API-incompatible with the minimatch@3/@9
used by eslint@9 and jest. This left 31 transitive high vulns across the
jest/eslint/@typescript-eslint trees, and blocked every dependabot PR's
`npm audit --audit-level=high` CI step (main itself is affected).

The only patched brace-expansion (5.x) requires minimatch@10, which in turn
requires eslint@10 (eslint@9's @eslint/config-array pins minimatch@3).
@typescript-eslint@8.65.0 already declares `eslint: ^10.0.0` support.

Changes:
- eslint ^9 -> ^10, @eslint/js ^9 -> ^10 (natively use minimatch@10 +
  brace-expansion@5, clearing the eslint tree).
- Drop the FlatCompat/@eslint/eslintrc layer; rewrite eslint.config.js as a
  pure flat config (eslint@10's @eslint/eslintrc would otherwise still pull
  vulnerable minimatch@3).
- Remove unused eslint-plugin-github (never referenced by the config); it
  pulled old minimatch@3/@9 and a stale bundled typescript-eslint@8.16.0 and
  was itself flagged by the audit.
- Add eslint-config-prettier@10 (previously only present transitively via
  eslint-plugin-github) to preserve the prior `extends` behavior.
- Add overrides to clear the remaining jest-tree vulns:
    brace-expansion ^5.0.8, glob ^11.0.1, test-exclude ^8.0.0
  and force @typescript-eslint/utils ^8.65.0 so eslint-plugin-jest's older
  transitive copy dedupes to the eslint@10-compatible release.
- Disable eslint@10's new `no-useless-assignment` rule to avoid churning the
  bundled dist/ for an unrelated audit fix.

Result: `npm audit --audit-level=high` -> 0 vulnerabilities; build, lint,
format-check and tests (37/37) all pass; src/ and dist/ are untouched so
check-dist remains valid.
@yxxhero
yxxhero merged commit b1848ca into main Jul 27, 2026
12 checks passed
@yxxhero
yxxhero deleted the fix/npm-audit-brace-expansion branch July 27, 2026 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant