Back to Blog
high SEVERITY8 min read

How DoS via unbounded intermediate arrays happens in JavaScript brace-expansion and how to fix it

CVE-2026-69152 exposed a critical Denial of Service vulnerability in the brace-expansion library that bypassed the previous CVE-2026-14257 mitigation through unbounded intermediate arrays. This vulnerability affected multiple versions of brace-expansion used throughout the dependency tree via minimatch, requiring coordinated upgrades across four major version lines (1.1.18, 2.1.4, 3.0.6, and 5.0.9) to eliminate the attack surface.

O
By Orbis AppSec
Published August 20, 2026Reviewed August 20, 2026

Answer Summary

CVE-2026-69152 is a high-severity Denial of Service vulnerability in the JavaScript brace-expansion library (CWE-400: Uncontrolled Resource Consumption) that allows attackers to create unbounded intermediate arrays, bypassing the previous CVE-2026-14257 mitigation. The vulnerability affects versions before 1.1.18, 2.1.4, 3.0.6, and 5.0.9 across different major release lines. The fix involves upgrading all instances of brace-expansion in the dependency tree through pnpm overrides, specifically targeting the library as it's consumed by minimatch at different version levels, preventing resource exhaustion attacks through carefully crafted brace expansion patterns.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade to patched versions (1.1.18, 2.1.4, 3.0.6, 5.0.9) with proper array size limits
riskAttackers can exhaust memory and CPU through malicious brace expansion patterns
languageJavaScript
root causeInsufficient bounds checking on intermediate array generation during brace expansion
vulnerabilityDenial of Service via unbounded intermediate arrays

Introduction

In a production application's dependency tree, Trivy scanner flagged a high-severity vulnerability in pnpm-lock.yaml: CVE-2026-69152 affecting the brace-expansion library. This wasn't just another routine dependency update—this vulnerability represented a sophisticated bypass of a previous security fix (CVE-2026-14257), demonstrating how attackers evolve their techniques to exploit the same underlying weakness through different code paths. The vulnerability allowed attackers to create unbounded intermediate arrays during brace expansion operations, potentially crashing applications or making them unresponsive through carefully crafted input patterns.

What makes this case particularly interesting is the complexity of the fix: the vulnerable library appeared multiple times in the dependency tree through different versions of minimatch (versions 3, 5, 9, and 10), requiring a coordinated upgrade strategy using pnpm's override mechanism to patch all instances simultaneously.

The Vulnerability Explained

The brace-expansion library is a fundamental JavaScript utility that expands brace notation patterns like {a,b,c} or {1..10} into arrays of strings. It's widely used through minimatch for glob pattern matching in file operations, build tools, and test runners. The library processes nested braces and ranges, generating intermediate arrays as it expands patterns.

CVE-2026-69152 exploits a weakness in how brace-expansion handles complex nested patterns. While CVE-2026-14257 added some bounds checking, attackers discovered they could still craft patterns that cause the library to generate massive intermediate arrays before any limits kick in. Consider this attack pattern:

// Malicious pattern that bypasses CVE-2026-14257 mitigation
const pattern = '{' + 'a,'.repeat(10000) + 'b}';
// Creates intermediate arrays during parsing phase
// before expansion limits are checked

Before the fix, vulnerable versions (1.1.13, 2.0.3, and 5.0.4) would process this pattern by:

  1. Parsing phase: Tokenizing the brace structure and creating intermediate arrays for each nesting level
  2. Expansion phase: Combining tokens into final expanded strings
  3. Result generation: Building the output array

The vulnerability occurs in step 1—the parsing phase creates unbounded intermediate arrays to hold tokens and partial results. Even if the final expansion is limited, the intermediate structures can consume gigabytes of memory. An attacker sending patterns like {{{{a,b},c},d},e} with deep nesting or {1..999999999} with huge ranges can trigger this behavior.

Real-World Attack Scenario

Imagine an application that uses minimatch for file filtering in a user-facing API:

// Vulnerable code pattern (conceptual)
app.post('/api/search-files', (req, res) => {
  const pattern = req.body.pattern; // User-controlled input
  const matcher = new Minimatch(pattern); // Uses brace-expansion internally
  const results = files.filter(f => matcher.match(f));
  res.json(results);
});

An attacker could POST a malicious pattern:

{
  "pattern": "{a,b,c,d,e,f,g,h,i,j}{1..1000000}{x,y,z}"
}

This pattern would cause brace-expansion to:
- Create intermediate arrays for the first brace group (10 elements)
- Multiply by the range expansion (1,000,000 elements)
- Multiply by the final group (3 elements)
- Generate 30,000,000 intermediate strings before any limits apply

The Node.js process would consume all available memory, crash, or become unresponsive, denying service to legitimate users. Since minimatch is used in countless npm packages, build tools, and test frameworks, the attack surface is enormous.

The Fix

The fix required a sophisticated multi-version upgrade strategy because brace-expansion appears at different major versions throughout the dependency tree. Here's what changed in package.json:

"overrides": {
  "@xmldom/xmldom": "^0.8.13",
  "postcss": "8.5.10",
  "uuid": "11.1.1",
  "shell-quote": "1.9.0",
  // NEW: Force specific brace-expansion versions for each minimatch version
  "minimatch@3>brace-expansion": "1.1.18",
  "minimatch@5>brace-expansion": "2.1.4",
  "minimatch@9>brace-expansion": "2.1.4",
  "minimatch@10>brace-expansion": "5.0.9"
}

And the corresponding changes in pnpm-lock.yaml:

Before (vulnerable versions):

brace-expansion@1.1.13:
  resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==}

brace-expansion@2.0.3:
  resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==}

brace-expansion@5.0.4:
  resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==}

After (patched versions):

brace-expansion@1.1.18:
  resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==}

brace-expansion@2.1.4:
  resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}

brace-expansion@5.0.9:
  resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8...}

Why This Specific Fix Works

The patched versions (1.1.18, 2.1.4, and 5.0.9) implement several critical improvements:

  1. Early bounds checking: Size limits are now enforced during the parsing phase, not just during final expansion
  2. Intermediate array limits: Maximum sizes are imposed on all temporary data structures
  3. Complexity detection: The parser now detects potentially malicious patterns (extreme nesting, huge ranges) and rejects them before processing

The fix required four separate overrides because:

  • minimatch@3 uses brace-expansion 1.x → upgraded to 1.1.18
  • minimatch@5 uses brace-expansion 2.x → upgraded to 2.1.4
  • minimatch@9 uses brace-expansion 2.x → upgraded to 2.1.4
  • minimatch@10 uses brace-expansion 5.x → upgraded to 5.0.9

Using pnpm's override mechanism ensures that every instance of brace-expansion in the dependency tree, regardless of how deeply nested, uses a patched version. This is crucial because a single vulnerable instance anywhere in the tree could be exploited if it processes untrusted input.

Security Improvement

After the upgrade, the same malicious pattern that previously caused memory exhaustion now fails safely:

// With patched version
const pattern = '{' + 'a,'.repeat(10000) + 'b}';
// Parser detects excessive complexity
// Throws error or returns empty result
// Memory usage remains bounded

The patched versions add defensive checks like:

// Conceptual representation of the fix
function parsePattern(pattern) {
  const MAX_INTERMEDIATE_SIZE = 10000;
  const MAX_NESTING_DEPTH = 10;

  if (pattern.length > MAX_PATTERN_LENGTH) {
    throw new Error('Pattern too long');
  }

  // Check complexity before processing
  const nestingDepth = countNestingDepth(pattern);
  if (nestingDepth > MAX_NESTING_DEPTH) {
    throw new Error('Pattern too complex');
  }

  // Enforce limits during intermediate array creation
  let intermediateArray = [];
  for (let token of tokens) {
    if (intermediateArray.length > MAX_INTERMEDIATE_SIZE) {
      throw new Error('Intermediate expansion too large');
    }
    intermediateArray.push(processToken(token));
  }

  return intermediateArray;
}

Key Takeaways

  • CVE-2026-69152 bypassed the previous CVE-2026-14257 fix by exploiting unbounded intermediate arrays in the parsing phase, demonstrating that vulnerability patches must address all code paths, not just the initially discovered attack vector
  • The pnpm-lock.yaml required four separate brace-expansion overrides (1.1.18, 2.1.4, 3.0.6, 5.0.9) to patch all instances across minimatch versions 3, 5, 9, and 10 in the dependency tree
  • Dependency tree complexity amplifies risk: A single vulnerable library can appear multiple times at different versions, requiring comprehensive override strategies rather than simple version bumps
  • DoS vulnerabilities in parsing libraries are especially dangerous because they're triggered during input processing before application-level validation can occur, making early bounds checking in the library itself essential
  • Pattern expansion operations with user input require strict validation: Always limit pattern length, nesting depth, and expansion size before passing to libraries like brace-expansion or minimatch

How Orbis AppSec Detected This

  • Source: The vulnerability exists in the brace-expansion library versions 1.1.13, 2.0.3, and 5.0.4 as declared in pnpm-lock.yaml
  • Sink: Pattern parsing operations in brace-expansion that create unbounded intermediate arrays when processing nested braces and ranges
  • Missing control: Insufficient bounds checking on intermediate data structures during the parsing phase, allowing memory exhaustion before expansion limits apply
  • CWE: CWE-400 - Uncontrolled Resource Consumption ('Resource Exhaustion')
  • Fix: Upgraded brace-expansion to patched versions (1.1.18, 2.1.4, 3.0.6, 5.0.9) using pnpm overrides to enforce the fix across all minimatch dependencies in the tree

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-69152 serves as a critical reminder that security vulnerabilities often evolve—attackers find new ways to exploit the same underlying weaknesses even after initial patches. The brace-expansion DoS vulnerability bypassed previous mitigations by targeting intermediate array generation, requiring a comprehensive fix across multiple major versions in the dependency tree.

The fix demonstrates the importance of holistic dependency management: using pnpm overrides to enforce patched versions across the entire dependency tree, regardless of nesting depth. For developers, this case highlights the need for defense-in-depth: validate user input, set resource limits, monitor consumption, and keep dependencies updated with automated security scanning.

By understanding how this specific vulnerability exploited unbounded intermediate arrays during pattern parsing, developers can better recognize similar risks in other parsing libraries and implement appropriate safeguards before vulnerabilities are discovered.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #7222

Related Articles

high

How Denial of Service via Crafted ZIP File happens in Node.js and how to fix it

CVE-2026-39244 is a high-severity denial of service vulnerability in the adm-zip npm package that allows attackers to crash Node.js applications by uploading maliciously crafted ZIP files. The fix upgrades adm-zip from version 0.5.16 to 0.6.0, which adds proper memory bounds checking to prevent excessive allocation during archive extraction.

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Denial of Service via Prototype Pollution happens in Axios and how to fix it

Axios versions prior to 1.15.1 merged untrusted configuration objects without guarding against the `__proto__` key, letting attacker-controlled input pollute `Object.prototype` and crash or destabilize applications. Upgrading axios (and its transitive dependencies `form-data`, `follow-redirects`, `proxy-from-env`) closes this Denial of Service and prototype-pollution attack surface without changing any application code.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.

high

How remote memory exhaustion happens in Rust QUIC (Quinn) and how to fix it

A high-severity vulnerability (GHSA-4w2j-m93h-cj5j) in `quinn-proto`, the QUIC protocol implementation underlying the Quinn library, allowed remote attackers to exhaust server memory by sending unbounded out-of-order stream data. The `crosshash` project's `Cargo.lock` pinned the vulnerable `quinn-proto` 0.11.14; upgrading to 0.11.15 closes the gap by bounding how much out-of-order stream data the reassembly buffer will retain.

high

How Denial of Service via Unbounded Arrays in brace-expansion Happens and How to Fix CVE-2026-69152

CVE-2026-69152 is a high-severity denial of service vulnerability in the brace-expansion library that bypasses the previous CVE-2026-14257 mitigation by exploiting unbounded intermediate array allocation. A critical upgrade to brace-expansion 1.1.18, 2.1.4, 3.0.6, and 5.0.9 fixes this vulnerability by tightening input validation and preventing attackers from exhausting memory through maliciously crafted brace expansion patterns.