Repository navigation
fix: detect glob-star-in-branch and repetition overlap as ReDoS-risky extglobs (CVE-2026-112366) - #235
fix: detect glob-star-in-branch and repetition overlap as ReDoS-risky extglobs (CVE-2026-112366)#235ShlomoRussell wants to merge 1 commit into
Conversation
…ReDoS-risky extglobs Addresses CVE-2026-112366 (SNYK-JS-PICOMATCH-21248802) and the bypass reported in micromatch#175. Two classes of pattern escaped the existing `analyzeRepeatedExtglob` safeguard and produced regexes with catastrophic backtracking: 1. Single-branch (or any branch) containing a glob star, e.g. `+(*)`, `+(*a)`, `+(a*)`, `*(a*|b)`. The glob `*` compiles to `[^/]*?`, creating a nested quantifier inside the outer `+`/`*` group. 2. Multi-branch alternations where one branch is a repetition of another, e.g. `+(ab|abab)`, `+(abc|abcabc)`. The repeated-substring relationship creates exponential partition ambiguity. Fix: - Add `branchContainsGlobStar` — detects unescaped `*` outside bracket classes, distinguishing glob stars (`*x`) from extglob quantifiers (`*(x)`) by checking `branch[i+1] !== '('`. - Replace `hasRepeatedCharPrefixOverlap` (only caught single-char repeats like `a|aa`) with `hasBranchRepetitionOverlap` (catches any `short|short.repeat(k)` pair, e.g. `ab|abab`). - Both checks run before the existing star-sequence and recursion analysis, so the `maxExtglobRecursion: false` escape hatch still disables all safeguards for trusted patterns. Patterns like `+(js|jsx)` and `+(foo|foobar)` are correctly preserved as functional regexes — the shorter branch is not a divisor of the longer one, so no exponential partitioning occurs. Credit: maximilliangrand and Zachariah Mithani (Snyk advisory reporters), Raunak Gupta (micromatch#175 reporter).
|
Any timeline on when it will be merged? |
|
I might disable PRs permanently due to the volume of AI generated fake vulnerabilities. How many times do I have to explain that globs are regular expressions. The general star height problem, which has not been solved, describes why we cannot predict all patterns like this. It's not a vulnerability, it's nonsense. My recommendation to anyone who thinks this is a problem:
|
@jonschlinkert The CI at my job flagged this as a Snyk vulnerability that was blocking the builds. We had to request a waiver for the CI to pass. https://security.snyk.io/vuln/SNYK-JS-PICOMATCH-21248802. If it's really not a vuln, how can we get the CVE taken down? |
Problem
CVE-2026-112366 / SNYK-JS-PICOMATCH-21248802 (CVSS 8.7 High): Patterns
like
+(*),+(*a),+(a*), and*(a*|b)trigger exponential regexbacktracking, blocking the Node.js event loop with inputs as short as
25-30 characters.
This also addresses the multi-character prefix overlap bypass reported
in #175 — patterns like
+(ab|abab)that escaped the existinghasRepeatedCharPrefixOverlapsafeguard.Root cause
analyzeRepeatedExtglobhad two blind spots:Glob stars in branches — A glob
*inside a+()or*()branch compiles to
[^/]*?, creating a nested quantifier(
(?:[^/]*?X)+) with exponential partition ambiguity. The existingchecks only caught wildcard-only branches in multi-branch patterns.
Multi-char repetition overlap — The existing
hasRepeatedCharPrefixOverlaponly detected single-characterrepeats (e.g.,
a|aa). Multi-character cases likeab|abab— whereone branch is a whole-string repetition of another — were missed.
Fix
branchContainsGlobStar: detects unescaped*outside bracketclasses, distinguishing glob stars (
*x) from extglob quantifiers(
*(x)) viabranch[i+1] !== '('.hasBranchRepetitionOverlap: replaces the single-char-only checkwith a general "is one branch a repetition of another" test.
analyzeRepeatedExtglob, before the existingstar-sequence and recursion analysis. The
maxExtglobRecursion: falseescape hatch continues to disable all safeguards.
Common patterns like
+(js|jsx),+(foo|bar),*(foo|bar), and*.+(js|jsx)are not affected — the fix correctly identifies thatjsxis not a repetition ofjs.Evidence
Before fix (
+(*a)against'a'.repeat(30)+'!'): 8,744 msAfter fix: <0.1 ms
Before fix (
+(ab|abab)against'ab'.repeat(40)+'c'): 1,779 msAfter fix: <0.1 ms
Full test suite: 1986 passing, 0 failing.
Test changes
vulnerable patterns like
+(*)cand*(a*|b)would matchfunctionally. They now assert literalized behavior.
tests (including positive tests for safe patterns), and
extglob-quantifier-vs-glob-star distinction tests.
Credit
Vulnerability reported by maximilliangrand and Zachariah Mithani (Snyk
advisory). Multi-char overlap bypass reported by Raunak Gupta (#175).
Fixes #175