Skip to content

fix: CVE-2026-112366 prevent ReDoS in single-branch repeated extglobs - #237

Open
seeibt wants to merge 1 commit into
micromatch:masterfrom
seeibt:fix/redos-single-branch-extglob
Open

seeibt wants to merge 1 commit into
micromatch:masterfrom
seeibt:fix/redos-single-branch-extglob

Conversation

@seeibt

@seeibt seeibt commented Oct 22, 2026 •

Copy link
Copy Markdown

Summary

Fixes GHSA-fc5q-39xc-vjpf / CVE-2026-112366.

analyzeRepeatedExtglob skipped single-branch repeated extglobs such as +(*) or +(*a), so they compiled to nested unbounded quantifiers (e.g. (?:[^/]*?a)+), causing exponential backtracking on short inputs.

Fix

A single branch containing a top-level * (with no /, groups, alternation, nested extglobs or globstar) absorbs its own repetition, so:

  • +(P) → (?:P)
  • *(P) → (?:P)?

These are semantically equivalent and remove the nested quantifier. Other cases keep the existing risky-extglob handling. The rewrite is skipped when maxExtglobRecursion: false.

Pattern Before After
+(*a) (?:[^/]*?a)+ (?:[^/]*?a)
*(*a) (?:[^/]*?a)* (?:[^/]*?a)?

Before the fix, matching 'a'.repeat(24) + 'b' against +(*a) took ~107ms and doubled with each extra char. With the fix it takes ~0ms.

Tests

Added cases in test/options.maxExtglobRecursion.js covering:

  • no nested quantifiers in the generated regex
  • a timing bound on malicious input
  • matching semantics preserved (+(*)c, +(*a), +(a*b), *(*.js))

All 1999 tests pass.

@lppedd

lppedd commented Oct 22, 2026

Copy link
Copy Markdown

See #235 (comment).

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.

2 participants