Skip to content

feat: add an opt-in nesting depth limit - #77

Closed
Adam-Aghili wants to merge 1 commit into
micromatch:masterfrom
Adam-Aghili:security/bounded-patterns-draft
Closed

Adam-Aghili wants to merge 1 commit into
micromatch:masterfrom
Adam-Aghili:security/bounded-patterns-draft

Conversation

@Adam-Aghili

Copy link
Copy Markdown

Summary

Add an optional maxDepth setting for brace and parenthesis nesting. The setting is enforced while parsing strings and while walking caller-supplied ASTs through compile(), expand(), and stringify().

The option is deliberately opt-in: leaving it undefined preserves the existing 3.0.3 behavior and output for normal callers. Invalid values are rejected as a non-negative integer contract.

Behavior

  • parse(pattern, { maxDepth: n }) throws SyntaxError before accepting a delimiter beyond n.
  • compile(ast, { maxDepth: n }), expand(ast, { maxDepth: n }), and stringify(ast, { maxDepth: n }) throw RangeError when an AST container exceeds n.
  • expand() carries the active depth into invalid/dollar and empty-range stringify fallbacks, so caller-supplied subtrees cannot reset the limit by being stringified independently.
  • Default parent handling, escapeInvalid, range expansion, glob patterns, and direct AST APIs remain unchanged when the option is omitted.

This is a bounded traversal control for callers that have a trust boundary. It does not claim to cap regular-expression compiler state, expansion cardinality, or every resource-exhaustion pattern, and it is not a universal fix for regex denial of service.

Tests

  • Parse brace and parenthesis boundaries at exact limits.
  • Reject fractional and negative values.
  • Reject deeply nested caller ASTs through all three walkers.
  • Reject over-depth dollar, invalid, and empty-range fallback subtrees while preserving the exact depth boundary.
  • Reject 4000-level strings and 5000-level ASTs before deep recursion when maxDepth: 100 is supplied.
  • Compare bounded and default compile/expand/stringify results for a normal glob pattern.

npm test passes with 900 tests on Node 22.22.0.

Downstream note

Consumers must explicitly pass the option. In particular, chokidar 3.6.0 calls braces.expand(path) without options, while micromatch's ordinary matching path uses picomatch. A published release and parent-package configuration are required before this option can affect those dependency paths.

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