Skip to content

Guard: no caller runs minimatch's level-2 preprocessing - #79

Merged
Skill-Klan merged 1 commit into
mainfrom
sk/minimatch-11.0.1
Nov 3, 2026
Merged

Skill-Klan merged 1 commit into
mainfrom
sk/minimatch-11.0.1

Conversation

@Skill-Klan

Copy link
Copy Markdown
Owner

Owner's decision 2026-11-03 for Dependabot alert #100 (minimatch, medium): dismiss as "vulnerable code not used" and keep a guard, the same way as #78 sprintf-js. The alert is dismissed after this PR lands, with a link here. No dependency changes.

Why the code is not used

  • GHSA-g3hv-75wg-m249: at optimizationLevel ≥ 2, each **/.. split in firstPhasePreProcess() doubles the pattern set, and secondPhasePreProcess() then compares it pairwise, which costs CPU and memory. The range is < 11.0.1. The fix is only in 11.0.1, a major: no 10.x or 3.x backport.
  • Two copies in the lock, both dev, not in the image:
  • No package in node_modules other than minimatch itself passes optimizationLevel. There is no glob in the tree, and our code doesn't import minimatch.
  • Probe on clean installs, using the pattern from the fix's own test (Array(n).fill('**/../a/b').join('/'), level 2):
    • 10.2.5: n = 14 → 2.1 s, n = 16 → over 30 s, n = 30 → out of memory (2 GB heap).
    • 11.0.1: n = 30 → 0.5 s.
    • 3.1.5: 0 ms.
    • 10.2.5 at level 1: 1 ms.
  • Why not override to 11: it goes past the parents' declared majors. 11.0 removed makeRe(), Minimatch#regexp and AST, and it adds a new package (@isaacs/nonrecursive-glob-match). The 3.x copy can't move to 11 anyway, so the alert would stay open.

The guard: __tests__/minimatchLevelTwoUnused.spec.ts

  • Every copy below 11.0.1 is dev in the lock. This fails if one becomes a runtime dependency.
  • No package that declares minimatch passes optimizationLevel. The scan covers their own source files, without nested packages.
    • Anchor: the scan includes typescript-estree and sees its require("minimatch").
    • Paired case: the same scan finds optimizationLevel in minimatch itself, so an empty result really means "not passed".
  • Red checks, each done with a file copy and restored after (cmp):
    • dev removed from node_modules/minimatch in the lock → expected [ 'node_modules/minimatch@3.1.5' ] to deeply equal [].
    • optimizationLevel: 2 added to the typescript-estree call → fails with that file.
    • require("minimatch") hidden in that file → the anchor fails.

Checked locally

  • Baseline on c00c53b: 366 files, 4348 tests, 0 failing.
  • This branch: 367 files, 4351 tests ✅. npm run lint ✅, npx tsc --noEmit ✅, prettier ✅.

🤖 Generated with Claude Code

Owner's decision 2026-11-03 for Dependabot alert #100 (minimatch,
GHSA-g3hv-75wg-m249, medium): dismiss as "vulnerable code not used" and
keep a guard. The fix exists only in minimatch 11.0.1; eslint (^3) and
@typescript-eslint/typescript-estree (^10.2.2) do not accept it.

The test fails if a minimatch copy below 11.0.1 becomes a runtime
dependency, or if a package that declares minimatch starts passing
optimizationLevel (the vulnerable code runs only at level 2 or higher).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Skill-Klan
Skill-Klan merged commit a67c8cc into main Nov 3, 2026
7 checks passed
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