CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-118764

CVE-2026-118764: Asymmetric Resource Consumption and Denial of Service in minimatch Pattern Preprocessing

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 31, 2026·9 min read·2 visits

Executive Summary (TL;DR)

Unbounded glob pattern splitting on repeated '**/..' segments combined with quadratic pairwise deduplication at optimizationLevel >= 2 allows attackers to trigger severe CPU and memory exhaustion in minimatch versions prior to 11.0.1.

CVE-2026-118764 (also tracked as GHSA-g3hv-75wg-m249) is an asymmetric resource consumption vulnerability (CWE-405) in the npm package minimatch prior to version 11.0.1. When pattern compilation is invoked with an optimizationLevel of 2 or higher, the internal preprocessing functions firstPhasePreProcess() and secondPhasePreProcess() in src/index.ts perform unbounded pattern splitting and quadratic pairwise deduplication. An attacker supplying a crafted glob string containing repeated **/.. segments can induce a combinatorial explosion of pattern permutations followed by an O(M^2) comparison routine, blocking the Node.js event loop and exhausting process memory.

Vulnerability Overview

minimatch is a foundational JavaScript and TypeScript utility used across the Node.js ecosystem to translate glob expressions into regular expressions (RegExp objects) and structured path-matching arrays. It serves as the primary matching engine for file-system traversal tools such as glob, build pipelines, linters, and web application routing frameworks. When applications accept user-supplied filter expressions or file search patterns and pass them to minimatch, the library's pattern compiler becomes directly exposed to untrusted input.

To optimize directory traversal performance, minimatch supports an optimizationLevel configuration option. While levels 0 and 1 perform basic token normalization, setting optimizationLevel to 2 or higher activates multi-pass pattern preprocessing in src/index.ts. This preprocessing stage rewrites complex traversal constructs and eliminates redundant pattern branches before regular expression compilation occurs.

In versions of minimatch prior to 11.0.1, this multi-pass preprocessor contains an asymmetric resource consumption flaw classified under CWE-405. Specifically, the firstPhasePreProcess() method expands **/.. path segments without enforcing an upper bound on the resulting pattern array size, while the subsequent secondPhasePreProcess() method executes an unguarded quadratic deduplication loop over the expanded array.

When an attacker provides a compact glob string containing consecutive **/.. sequences, the pattern set grows exponentially at a rate of $2^N$ and is immediately subjected to $O(M^2)$ pairwise comparisons. Because Node.js executes JavaScript on a single-threaded event loop, this synchronous computational spike halts request processing across the entire application instance or terminates the process via an out-of-memory fault.

Root Cause Analysis

The root cause of CVE-2026-118764 resides in the interaction between two sequential methods within the Minimatch class in src/index.ts: firstPhasePreProcess() and secondPhasePreProcess(). Both methods are invoked during pattern compilation when this.options.optimizationLevel is configured to 2 or greater. Their objective is to normalize globstar-parent traversal patterns (**/..) so that downstream file-system walkers can prune directory trees accurately.

During firstPhasePreProcess(globParts: string[][]), the engine searches each pattern array for the sequence <pre>/**/../<p>/<rest>, where <p> is a valid path segment other than ., .., **, or an empty string ''. Because ** does not follow symbolic links in minimatch semantics, <pre>/**/../<p>/<rest> is transformed into the equivalent brace-expanded representation <pre>/{..,**}/<p>/<rest>. In memory, the function achieves this by cloning the current pattern array, replacing **/.. with .. in one copy and ** in the second copy, and appending the new branch to globParts.

This splitting logic executes inside a do { ... } while (didSomething) fixpoint loop that iterates until no reducible **/.. sequences remain across any entry in globParts. Because each split duplicates the remainder of the pattern—including any unvisited **/.. segments further down the path—a pattern containing $N$ consecutive **/../<p> segments doubles the size of globParts at every expansion step, yielding $M = 2^N$ distinct patterns. Prior to version 11.0.1, although minimatch enforced a braceExpandMax limit (defaulting to 100,000) during initial {a,b} brace expansion, firstPhasePreProcess() failed to consult braceExpandMax when performing **/.. splits.

Once firstPhasePreProcess() completes, the inflated globParts array is passed directly to secondPhasePreProcess(globParts: string[][]). This second phase removes redundant patterns by running a nested loop (for (let i = 0; i < globParts.length - 1; i++) and for (let j = i + 1; j < globParts.length; j++)) that calls this.partsMatch(globParts[i], globParts[j]) on every unique pair. For an array of size $M$, this requires $\frac{M(M - 1)}{2}$ invocations of partsMatch(). When $M$ reaches tens or hundreds of thousands of elements via firstPhasePreProcess() or standard brace expansion, the quadratic execution time stalls the CPU prior to memory exhaustion.

Code Analysis

Commit 77a0f5c4b80bdc641c3c930a1d9edf5ad2db57f8 addresses both stages of the amplification chain in src/index.ts. In the vulnerable implementation of firstPhasePreProcess(), the inner loop checked whether the path segments surrounding **/.. were eligible for splitting, but never verified the current length of globParts against any resource cap.

// Vulnerable implementation in src/index.ts (prior to 11.0.1)
firstPhasePreProcess(globParts: string[][]) {
  let didSomething = false
  do {
    didSomething = false
    for (let i = 0; i < globParts.length; i++) {
      const parts = globParts[i]
      // ... segment iteration ...
      if (
        !p ||
        p === '.' ||
        p === '..' ||
        !p2 ||
        p2 === '.' ||
        p2 === '..'
        // Missing check on globParts.length allows unbounded 2^N growth
      ) {
        continue
      }
      // Splits parts into two branches and pushes to globParts
      didSomething = true
    }
  } while (didSomething)
}

In the patched version (11.0.1), firstPhasePreProcess() extracts braceExpandMax from this.options (defaulting to 100_000) and halts further **/.. splitting as soon as globParts.length >= braceExpandMax. Simultaneously, secondPhasePreProcess() introduces a hard ceiling of 1000 patterns, bypassing the $O(M^2)$ deduplication loop entirely if globParts.length > 1000.

// Patched implementation in src/index.ts (v11.0.1 - commit 77a0f5c4b80bdc641c3c930a1d9edf5ad2db57f8)
firstPhasePreProcess(globParts: string[][]) {
  // each **/.. split doubles the patterns, so stop at the brace max
  const { braceExpandMax = 100_000 } = this.options
  let didSomething = false
  do {
    didSomething = false
    for (let i = 0; i < globParts.length; i++) {
      const parts = globParts[i]
      // ... segment iteration ...
      if (
        !p ||
        p === '.' ||
        p === '..' ||
        !p2 ||
        p2 === '.' ||
        p2 === '..' ||
        globParts.length >= braceExpandMax // Enforces upper bound on pattern splitting
      ) {
        continue
      }
      // ... pattern splitting logic ...
    }
  } while (didSomething)
}
 
secondPhasePreProcess(globParts: string[][]): string[][] {
  // each pattern is compared to each other one, so skip this for
  // large sets. The patterns match the same paths either way.
  if (globParts.length > 1000) return globParts
  for (let i = 0; i < globParts.length - 1; i++) {
    for (let j = i + 1; j < globParts.length; j++) {
      const matched = this.partsMatch(globParts[i], globParts[j])
      // ...
    }
  }
}

> [!NOTE] > Assessment of Fix Completeness: The patch effectively neutralizes both the exponential memory expansion in firstPhasePreProcess() and the quadratic CPU bottleneck in secondPhasePreProcess(). Notably, capping secondPhasePreProcess() at 1,000 patterns also closes a secondary vector where an attacker could use standard brace expansion (e.g., {x,*}/{0..99999}, which stays below the 100,000 braceExpandMax limit) to feed 100,000 patterns directly into the $O(M^2)$ deduplication loop. However, generating 100,000 patterns via braceExpandMax still incurs non-trivial linear allocation overhead; security-sensitive applications processing untrusted globs should explicitly configure a lower braceExpandMax value.

Exploitation

Exploiting CVE-2026-118764 requires two specific preconditions: the target application must pass attacker-controlled strings into minimatch(target, pattern, options) or new Minimatch(pattern, options), and the options object must specify optimizationLevel: 2 (or a higher integer). No authentication or special privileges are required if the pattern input is exposed via a public API endpoint, CLI service, or configuration parser.

To trigger the vulnerability, an attacker constructs a glob string containing repeated sequences of **/../<dir1>/<dir2>. Two trailing path segments (a/b) are used after each **/.. to satisfy the adjacency conditions (p and p2 checks) inside firstPhasePreProcess(). With $N = 20$ repetitions (a string of approximately 200 bytes), firstPhasePreProcess() generates $2^{20} = 1,048,576$ pattern arrays, which then require approximately $5.49 \times 10^{11}$ pairwise comparisons in secondPhasePreProcess().

const { Minimatch } = require('minimatch');
 
// Construct a 299-character payload containing 30 repetitions of '**/../a/b'
// In vulnerable versions (< 11.0.1), this attempts to expand into 2^30 (1,073,741,824) patterns
const maliciousPattern = Array(30).fill('**/../a/b').join('/');
 
console.log(`Payload length: ${maliciousPattern.length} bytes`);
console.time('Compilation Time');
 
try {
  // Must be invoked with optimizationLevel >= 2 to enter firstPhasePreProcess()
  const mm = new Minimatch(maliciousPattern, { optimizationLevel: 2 });
  console.timeEnd('Compilation Time');
  console.log(`Compiled pattern set length: ${mm.set.length}`);
} catch (err) {
  console.error('Process fault encountered:', err);
}

The regression test added in commit 77a0f5c4b80bdc641c3c930a1d9edf5ad2db57f8 (test/preprocess-limits.ts) demonstrates both trigger mechanisms: Array(30).fill('**/../a/b').join('/') for exponential **/.. splitting, and {x,*}/{0..999} for large-set deduplication. On versions prior to 11.0.1, executing the 30-segment payload pins a CPU core at 100% utilization and terminates the Node.js runtime with a FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory exception.

Impact Assessment

The security impact of CVE-2026-118764 is confined to system availability, with no direct impact on confidentiality or integrity (VC:N/VI:N). Because the vulnerability is triggered synchronously during the instantiation of a Minimatch object, any single-threaded Node.js server handling concurrent client requests on the main event loop will become unresponsive for the duration of the pattern compilation or crash entirely if the V8 heap limit is exceeded.

GitHub's security advisory (GHSA-g3hv-75wg-m249) assigns a CVSS v4.0 base score of 6.9 (Medium) with the vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N, reflecting scenarios where availability degradation is partial or mitigated by process supervisors. However, OSV also records a High severity variant (8.7) under the vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N, which accurately reflects architectures where an unauthenticated network request blocks the primary Node.js event loop and causes complete service denial (VA:H).

According to FIRST EPSS telemetry, CVE-2026-118764 currently holds a low exploitation probability score of 0.00291 (0.291%, 21.74th percentile) and is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. The primary factor limiting widespread exploitation is that minimatch defaults to optimizationLevel: 1 when no options are provided, meaning only applications or downstream libraries that explicitly opt into optimizationLevel: 2 (or pass user-controlled options objects into minimatch) are vulnerable.

Remediation

To remediate CVE-2026-118764, upgrade minimatch to version 11.0.1 or later. Version 11.0.1 bounds **/.. expansion in firstPhasePreProcess() to braceExpandMax (100,000 by default) and skips pairwise deduplication in secondPhasePreProcess() whenever the expanded pattern set exceeds 1,000 elements.

# Update minimatch using npm
npm install minimatch@^11.0.1
 
# Verify that no older transitive versions remain in the dependency tree
npm ls minimatch

For environments where an immediate dependency upgrade is not feasible, developers can apply configuration-level workarounds. First, ensure that optimizationLevel is omitted, set to 0, or set to 1 when compiling untrusted glob strings, as the vulnerable preprocessing methods are only executed when optimizationLevel >= 2. Ensure that user input cannot overwrite the options object passed to minimatch.

const { Minimatch } = require('minimatch');
 
// Workaround 1: Restrict optimizationLevel to 1 (default)
const safeMatcher = new Minimatch(untrustedPattern, {
  optimizationLevel: 1,
  braceExpandMax: 1000
});

If optimizationLevel: 2 is strictly required on a patched version (>= 11.0.1) that accepts untrusted input, explicitly lower braceExpandMax from its default of 100,000 to a conservative ceiling such as 500 or 1,000. Additionally, implement pre-validation on user-supplied glob strings to reject inputs exceeding a strict character length (e.g., 256 characters) or containing repeated **/.. traversal sequences.

Official Patches

GitHub / isaacsOfficial patch commit limiting firstPhasePreProcess and secondPhasePreProcess in src/index.ts
GitHub / isaacsminimatch v11.0.1 release tag
GitHub Security AdvisoryOfficial GitHub Security Advisory GHSA-g3hv-75wg-m249

Fix Analysis (1)

Technical Appendix

CVSS Score
6.9/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
EPSS Probability
0.29%
Top 78% most exploited

Affected Systems

minimatch (npm package)

Affected Versions Detail

Product
Affected Versions
Fixed Version
minimatch
isaacs
< 11.0.111.0.1
AttributeDetail
Vulnerability IDCVE-2026-118764 / GHSA-g3hv-75wg-m249
Weakness ClassCWE-405: Asymmetric Resource Consumption (Amplification)
Affected Componentminimatch (src/index.ts: firstPhasePreProcess & secondPhasePreProcess)
CVSS v4.0 Score6.9 Medium (GitHub CNA) / 8.7 High (OSV Availability Variant)
EPSS Score0.291% (21.74th Percentile)
Trigger ConditionUntrusted glob pattern compiled with optimizationLevel >= 2
ImpactNode.js Event Loop Exhaustion & Out-of-Memory Denial of Service
Fixed Versionminimatch 11.0.1

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.003Application Exhaustion
Impact
CWE-405
Asymmetric Resource Consumption (Amplification)

The software does not properly restrict the size or amount of resources that can be requested or consumed by an attacker, allowing a small request to cause a disproportionately large consumption of system resources.

Known Exploits & Detection

GitHubOfficial fix commit including test/preprocess-limits.ts demonstrating the 30-segment '**/../a/b' trigger payload.

Vulnerability Timeline

CVE-2026-118764 and GHSA-g3hv-75wg-m249 published; minimatch v11.0.1 released with fix commit 77a0f5c4b80bdc641c3c930a1d9edf5ad2db57f8.
2026-10-29
CVE record metadata updated.
2026-10-31

References & Sources

  • [1]GitHub Security Advisory GHSA-g3hv-75wg-m249
  • [2]Official Fix Commit 77a0f5c4b80bdc641c3c930a1d9edf5ad2db57f8
  • [3]minimatch Release v11.0.1
  • [4]NVD Vulnerability Record for CVE-2026-118764
  • [5]CVE.org Authoritative Record for CVE-2026-118764

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•26 minutes ago•CVE-2026-118773
6.3

CVE-2026-118773: Asynchronous Control Flow Bypass and Uncontrolled Resource Consumption in node-glob

CVE-2026-118773 (GHSA-3g3m-2fjr-6pw4) is an uncontrolled resource consumption vulnerability in the node-glob npm package affecting versions 9.0.0 through 14.0.1. Due to missing return statements in the AbortSignal check routines within the directory traversal walker, aborted operations reject the caller promise as expected but continue executing background filesystem reads and pattern matching. Applications that rely on AbortSignal or AbortSignal.timeout() to enforce execution budgets on user-influenced glob operations remain susceptible to CPU, event loop, and disk I/O exhaustion.

Amit Schendel
Amit Schendel
2 views•10 min read
•about 2 hours ago•CVE-2026-119202
7.5

CVE-2026-119202: Regular Expression Denial of Service in @hapi/content Header Parsing

A regular expression denial of service (ReDoS) vulnerability exists in @hapi/content from version 3.0.6 prior to 6.0.3. The Content.disposition() function utilizes an unanchored parameter-name regular expression inside a global replacement scan. When processing a Content-Disposition header parameter containing a long token lacking an equals sign, the JavaScript regular expression engine undergoes quadratic O(N^2) backtracking. Because @hapi/content is invoked by @hapi/pez during multipart/form-data request parsing, unauthenticated remote attackers can send a crafted multipart request to any Hapi route with multipart payload parsing enabled, starving the single-threaded Node.js event loop.

Alon Barad
Alon Barad
4 views•9 min read
•about 3 hours ago•CVE-2026-118772
7.5

CVE-2026-118772: Regular Expression Denial of Service in Joi Email Validation

A Regular Expression Denial of Service (ReDoS) vulnerability exists in the joi schema description and data validation library for JavaScript. When validating multiple email addresses using the Joi.string().email({ multiple: true }) configuration, the library compiles a separator regular expression with an unanchored greedy leading whitespace quantifier. Supplying an input string containing a long sequence of whitespace characters without the expected delimiter triggers quadratic time complexity during String.prototype.split execution, blocking the single-threaded Node.js event loop.

Alon Barad
Alon Barad
5 views•11 min read
•about 4 hours ago•CVE-2026-119205
7.1

CVE-2026-119205: Denial of Service via Infinite Loop in pypdf DictionaryObject Cloning

CVE-2026-119205 (GHSA-mfr5-77xh-9j7h) is a Denial of Service (DoS) vulnerability in pypdf prior to version 6.21.4. The flaw occurs during the cloning or duplication of nested PDF dictionary structures. Because the cycle-detection algorithm within DictionaryObject._clone() tracked generated destination object references rather than the original source indirect references, cyclic reference graphs in source PDFs evaded detection, resulting in an infinite loop and CPU exhaustion.

Alon Barad
Alon Barad
4 views•9 min read
•about 5 hours ago•CVE-2026-119204
7.1

CVE-2026-119204: Uncontrolled Resource Consumption in pypdf Page Tree Flattening

CVE-2026-119204 (also tracked as GHSA-cggf-277g-3q54) is a Denial of Service (DoS) vulnerability in pypdf prior to version 6.21.4. The vulnerability stems from uncontrolled resource consumption (CWE-400) during the flattening of a PDF document's page tree. By supplying a compact PDF containing a hierarchical amplification structure of shared `/Pages` and `/Page` nodes with dense dictionary entries or inherited resources, an unauthenticated attacker can cause pypdf to copy millions of dictionary entries into individual `PageObject` instances without enforcing a document-wide entry budget. This triggers severe heap memory exhaustion and process termination via Out-Of-Memory (OOM) kills.

Alon Barad
Alon Barad
4 views•11 min read
•about 6 hours ago•CVE-2026-119203
7.1

CVE-2026-119203: Infinite Loop in pypdf Standard Cross-Reference Table Parser

CVE-2026-119203 is a denial-of-service vulnerability affecting the pypdf library in versions prior to 6.21.4. The flaw occurs within the standard cross-reference (xref) table parsing routine when processing truncated or malformed PDF streams that terminate before a valid trailer dictionary is encountered. Because the parser attempts to rewind the stream pointer by a fixed offset whenever the trailer token is absent without verifying forward progress, hitting the end-of-file (EOF) or non-advancing tokens causes the parser to re-read the same byte offset indefinitely. An unauthenticated attacker can exploit this flaw by supplying a crafted PDF document to an application using pypdf, resulting in continuous CPU consumption and thread exhaustion.

Amit Schendel
Amit Schendel
4 views•9 min read