fix: resolve high-severity npm audit vulnerabilities (brace-expansion DoS) - #755
Merged
Conversation
… 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the
npm audit --audit-level=highstep that failsBasic validationonmainand every dependabot PR (including #753).npm auditnow reports 0 vulnerabilities (was 31 high). Build, lint, format-check and tests (37/37) all pass.Root cause
GHSA-mh99-v99m-4gvg / CVE-2026-14257 —
brace-expansionDoS via unbounded expansion. The advisory has a single range>=0, <5.0.8, so everybrace-expansionbelow 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-arraypinsminimatch@3) → needseslint@10(usesminimatch@10)jest@30(glob@10.5→minimatch@9;babel-plugin-istanbul→test-exclude@6→glob@7→minimatch@3)@typescript-eslint@8.65.0already declareseslint: ^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 pullsminimatch@10+brace-expansion@5, clearing the eslint tree.eslint.config.jsas a pure flat config, dropping theFlatCompat/@eslint/eslintrclayer (eslint@10's@eslint/eslintrcwould otherwise still drag in vulnerableminimatch@3).eslint-plugin-github(never referenced by the config) — it pulled oldminimatch@3/@9, a stale bundledtypescript-eslint@8.16.0, and was itself flagged by the audit.eslint-config-prettier@10(previously only present transitively viaeslint-plugin-github) to preserve the previousextendsbehavior.overridesto 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— forceseslint-plugin-jest's older transitive copy to dedupe to the eslint@10-compatible release.no-useless-assignmentrule (see comment in config) to avoid churning the bundleddist/for an unrelated audit fix.src/anddist/are untouched, soCheck dist/remains valid.Verification (local, node 24.x)
npm ci --ignore-scriptsnpm run format-checknpm run lintnpm run buildnpm testnpm audit --audit-level=highRelationship to #753
This is intentionally kept separate from #753 (the
eslint-plugin-jest29.15.5 → 29.16.0 bump).eslint-plugin-jestis left at^29.15.5here (it already supports eslint@10). Once this merges, #753 rebases onto a greenmainand itsAudit packagesstep will pass.