Back to Blog
high SEVERITY7 min read

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.

O
By Orbis AppSec
Published September 7, 2026Reviewed September 7, 2026

Answer Summary

CVE-2026-69152 is a denial of service vulnerability in the brace-expansion npm package (used in Node.js and build tools) where unbounded intermediate arrays could be allocated during pattern expansion, bypassing the previous CVE-2026-14257 mitigation. The fix upgrades brace-expansion to patched versions (1.1.18, 2.1.4, 3.0.6, 5.0.9) that implement stricter bounds checking and prevent excessive array allocation during expansion operations, reducing the attack surface against both manual and automated exploitation.

Vulnerability at a Glance

cweCWE-770 (Allocation of Resources Without Limits or Throttling)
fixUpgrade brace-expansion to versions that implement bounded intermediate array handling with strict limits on expansion size
riskAttackers can cause application crashes or resource exhaustion by providing malicious brace expansion patterns that allocate excessive memory
languageJavaScript/Node.js
root causebrace-expansion library failed to properly limit intermediate array allocation during pattern expansion, allowing circumvention of the CVE-2026-14257 mitigation
vulnerabilityDenial of Service via Unbounded Intermediate Arrays (CVE-2026-69152)

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

Introduction

In build pipelines and Node.js applications worldwide, the brace-expansion library quietly handles string pattern expansion—converting patterns like {a,b,c} into arrays of possible values. This simple utility is depended upon by thousands of npm packages. But in CVE-2026-69152, researchers discovered a critical flaw: the library could be abused to allocate unbounded intermediate arrays during expansion, causing denial of service attacks that crash applications or exhaust memory. Worse, this vulnerability bypassed the mitigation implemented for the previous CVE-2026-14257, demonstrating that the original fix was incomplete.

This matters because brace-expansion appears deep in dependency trees—it's pulled in by glob patterns, test runners, and build tools. An attacker who can influence the input to a brace expansion operation (through a filename, configuration value, or command-line argument) can trigger this vulnerability without your code ever directly calling the library.

The Vulnerability Explained

What Makes This Different: Bypassing the Previous Fix

The brace-expansion library had already been patched once for CVE-2026-14257, which addressed unbounded expansion. However, CVE-2026-69152 reveals that the previous fix didn't account for intermediate arrays created during the expansion algorithm itself.

Here's the critical distinction: when brace-expansion processes a pattern like {1..1000000}, it doesn't just create one massive final array. The internal algorithm creates temporary arrays at each step of expansion. The previous fix might have capped the final result, but the intermediate working arrays could still consume all available memory before that cap was reached.

The Attack Scenario

Consider a build system that accepts user-provided glob patterns:

// Vulnerable code path (simplified)
const braceExpand = require('brace-expansion');

// Attacker provides this pattern via a config file or CLI argument
const userPattern = '{0..999999999999999}';

// This creates unbounded intermediate arrays during expansion
const expanded = braceExpand(userPattern);
// Result: Application crashes as intermediate array allocation fails
// or memory is exhausted before the function completes

An attacker could craft patterns with deeply nested expansions or extremely large ranges. Each intermediate step of the algorithm would allocate temporary arrays. In the vulnerable version (prior to 1.1.18 / 2.1.4 / 3.0.6 / 5.0.9), there was no mechanism to bound these intermediate allocations, allowing memory exhaustion.

Real-World Impact

For applications that:
- Process user-provided glob patterns in build systems
- Accept filename patterns from external sources
- Use brace-expansion indirectly through glob, minimatch, or similar libraries
- Run in memory-constrained environments (containers, serverless functions)

...an attacker could trigger a denial of service simply by providing a maliciously crafted brace expansion pattern. In a CI/CD pipeline, this could block all builds. In a web service, this could crash worker processes.

The Fix

The fix addresses this vulnerability by implementing bounded intermediate array allocation with strict limits on expansion size at every step of the algorithm, not just the final result.

Changes Made

The PR updated dependency versions across multiple package management files:

In package.json:

   "pnpm": {
     "overrides": {
-      "whatwg-url": "13.0.0"
+      "whatwg-url": "13.0.0",
+      "brace-expansion": "1.1.18"
     },

In pnpm-lock.yaml:

 overrides:
   whatwg-url: 13.0.0
+  brace-expansion: 1.1.18

And crucially, the vulnerable versions were removed from the lock file:

-  brace-expansion@1.1.12:
-    resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
-
-  brace-expansion@5.0.5:
-    resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==}
-    engines: {node: 18 || 20 || >=22}
+  brace-expansion@1.1.18:
+    resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==}

How This Solves the Problem

The patched versions (1.1.18, 2.1.4, 3.0.6, and 5.0.9) implement checks that:

  1. Limit intermediate array size: During the expansion algorithm, before allocating a temporary array, the code now checks if the size would exceed a reasonable bound
  2. Fail early: If a pattern would require excessive expansion, the function raises an error rather than attempting to allocate unbounded memory
  3. Preserve valid expansions: Legitimate brace expansion patterns still work correctly—only pathologically large patterns are rejected

The use of npm overrides ("brace-expansion": "1.1.18" in package.json) ensures that even if other dependencies specify older versions, they will all receive the patched version. This is crucial because brace-expansion appears transitively in many dependency chains.

The change is "behavior preserving" for legitimate inputs—all valid, real-world brace expansion patterns continue to work as expected. Only attack patterns are rejected.

Prevention & Best Practices

1. Keep Dependencies Updated Regularly

The most direct prevention is to maintain current versions of all dependencies. Set up automated dependency scanning with tools like:
- npm audit (built-in)
- Snyk (continuous monitoring)
- Trivy (the scanner that detected this CVE)

2. Use npm Overrides for Transitive Dependencies

When a vulnerability exists in a transitive dependency (as with brace-expansion), use overrides to enforce a patched version:

{
  "pnpm": {
    "overrides": {
      "brace-expansion": "1.1.18"
    }
  }
}

This prevents any version of brace-expansion other than the patched one from being installed, even if a different version is requested by a dependent package.

3. Validate External Input

Even with patches applied, apply defense-in-depth:

// Validate patterns before expansion
function safeBraceExpand(pattern) {
  // Reject obviously malicious patterns
  if (!pattern || pattern.length > 1000) {
    throw new Error('Pattern too long');
  }

  // Reject patterns with excessive nesting depth
  const nestingDepth = (pattern.match(/\{/g) || []).length;
  if (nestingDepth > 5) {
    throw new Error('Pattern too deeply nested');
  }

  try {
    return braceExpand(pattern);
  } catch (error) {
    // Handle expansion failures gracefully
    console.error('Brace expansion failed:', error);
    return [pattern]; // Return pattern as-is if expansion fails
  }
}

4. Monitor Resource Usage

In production, monitor memory usage during pattern expansion operations:

const memBefore = process.memoryUsage().heapUsed;
const expanded = braceExpand(userPattern);
const memAfter = process.memoryUsage().heapUsed;

if (memAfter - memBefore > THRESHOLD) {
  console.warn('Suspicious memory allocation during expansion');
}

5. CWE and OWASP References

This vulnerability relates to:
- CWE-770: Allocation of Resources Without Limits or Throttling — the root cause
- OWASP A06:2021 Vulnerable and Outdated Components — the attack vector
- OWASP A01:2021 Broken Access Control — if pattern source is untrusted

Key Takeaways

  • CVE-2026-69152 is not just a regression: This vulnerability specifically bypasses the previous CVE-2026-14257 fix, demonstrating that the original mitigation was incomplete. If you patched only CVE-2026-14257, you're still vulnerable.

  • Intermediate arrays are the culprit: The attack doesn't rely on the final expanded array size—it exploits the temporary arrays created during the expansion algorithm itself. Bounds checking must occur at every step, not just at the end.

  • npm overrides are essential for transitive dependencies: Because brace-expansion appears deep in dependency trees (often indirectly), you can't rely on direct dependency updates alone. Use pnpm overrides or npm resolutions to enforce the patched version globally.

  • Legitimate patterns continue to work: The fix doesn't change behavior for real-world brace expansion use cases—only pathologically large patterns designed for exploitation are rejected.

  • Defense-in-depth applies here too: Even with the patch installed, validating user-provided patterns and monitoring resource usage adds extra protection against DoS attacks.

How Orbis AppSec Detected This

Source: Untrusted brace expansion patterns originating from user-provided filenames, configuration values, or CLI arguments that eventually reach brace-expansion library calls through glob(), minimatch, or direct function invocations.

Sink: The internal expansion algorithm in brace-expansion package, specifically the array allocation loops within the expansion handler (pre-1.1.18 versions).

Missing control: Input validation on pattern length and nesting depth; bounds checking on intermediate array allocation during the expansion algorithm; no early-exit mechanism when allocation would exceed reasonable limits.

CWE: CWE-770 (Allocation of Resources Without Limits or Throttling)

Fix: Upgrade brace-expansion to 1.1.18, 2.1.4, 3.0.6, or 5.0.9 (depending on your major version in use) which implements strict bounds on intermediate array allocation and fails early when patterns would cause excessive memory use.

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 is a sobering reminder that security fixes sometimes require iterative refinement. The first patch for brace-expansion addressed one attack vector, but attackers adapted by exploiting intermediate array allocation. This vulnerability demonstrates the importance of:

  1. Following up on previous CVEs — if you fixed CVE-2026-14257, ensure you also fix CVE-2026-69152
  2. Automated dependency scanning — catching these issues before they reach production
  3. Defense-in-depth — combining multiple protective layers (patched code, input validation, monitoring)
  4. Transitive dependency management — using npm overrides to enforce security patches across your entire dependency tree

By upgrading brace-expansion and implementing the practices outlined above, you eliminate a critical denial of service vector in your applications. Security is an ongoing process, and staying current with patches is the foundation of that process.


References

Frequently Asked Questions

What is CVE-2026-69152?

CVE-2026-69152 is a high-severity denial of service vulnerability in brace-expansion that allows attackers to crash applications or exhaust system memory by providing specially crafted brace expansion patterns that generate unbounded intermediate arrays, bypassing the previous CVE-2026-14257 mitigation.

How do you prevent DoS vulnerabilities in brace-expansion?

Upgrade brace-expansion to the patched versions (1.1.18, 2.1.4, 3.0.6, 5.0.9 or later), use npm overrides to enforce the patched version across your dependency tree, and validate untrusted input before passing it to expansion functions.

What CWE is this vulnerability?

CWE-770: Allocation of Resources Without Limits or Throttling describes this class of vulnerability where resources (memory arrays) are allocated without proper bounds checking.

Is the previous CVE-2026-14257 fix enough to prevent this attack?

No—CVE-2026-69152 specifically exploits patterns that bypass the CVE-2026-14257 mitigation by using a different code path or expansion technique, which is why a new fix was required.

Can static analysis detect CVE-2026-69152?

Yes, security scanners like Trivy can detect this vulnerability by analyzing dependencies in package.json and pnpm-lock.yaml files, identifying outdated brace-expansion versions vulnerable to this specific CVE.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #329

Related Articles

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

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.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.

critical

How Denial of Service via Gzip Bomb happens in Node.js and how to fix it

A critical Denial of Service vulnerability (CVE-2026-59873) in the `tar` npm package allowed attackers to craft malicious gzip archives that could exhaust memory or CPU during decompression. The fix upgrades `tar` from 7.5.11 to 7.5.21 across `package.json` and `package-lock.json`, closing the resource-exhaustion path without changing any application code.