Back to Blog
high SEVERITY7 min read

How Denial of Service via Unbounded Brace Expansion happens in Node.js and how to fix it

The brace-expansion library in Node.js contained a critical denial-of-service vulnerability where specially crafted input could trigger unbounded array expansion, consuming all available memory and crashing the process. This vulnerability affected multiple versions across the library's version branches. The fix upgrades brace-expansion to patched versions that implement strict limits on intermediate array sizes.

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

Answer Summary

CVE-2026-69152 is a Denial of Service vulnerability in the Node.js brace-expansion library (CWE-400: Uncontrolled Resource Consumption) caused by unbounded intermediate array expansion during brace pattern parsing. The vulnerability allows attackers to craft malicious input patterns that consume excessive memory, crashing the application. The fix upgrades brace-expansion from versions 1.1.11, 2.x, 3.x, and 5.x to their patched counterparts (1.1.18, 2.1.4, 3.0.6, 5.0.9) that implement resource consumption limits.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade brace-expansion to 1.1.18, 2.1.4, 3.0.6, or 5.0.9 with resource consumption limits
riskProcess crash due to out-of-memory condition; service unavailability
languageJavaScript/Node.js
root causeUnbounded intermediate array creation during brace pattern expansion without resource limits
vulnerabilityDenial of Service via Unbounded Brace Expansion

How Denial of Service via Unbounded Brace Expansion happens in Node.js and how to fix it

Introduction

In projects using the brace-expansion library through their yarn.lock dependency tree, a HIGH severity denial-of-service vulnerability (CVE-2026-69152) was discovered that could crash Node.js processes through memory exhaustion. The vulnerability exists in how brace-expansion handles brace patterns—a common feature for expanding strings like {a,b,c} into multiple values. When processing specially crafted malicious input, the library would create unbounded intermediate arrays during pattern expansion, consuming all available memory and terminating the process.

This vulnerability affects a critical component used throughout the JavaScript ecosystem, making it essential for developers to understand the attack vector and apply the necessary upgrades immediately.

The Vulnerability Explained

What is brace-expansion?

The brace-expansion library is a widely-used Node.js package that expands brace patterns in strings. For example:

// Normal usage
expand('{a,b,c}') // Returns: ['a', 'b', 'c']
expand('file{1..3}.txt') // Returns: ['file1.txt', 'file2.txt', 'file3.txt']

This functionality is used in build tools, CLI applications, glob pattern matching, and file system operations throughout the JavaScript ecosystem.

The Attack Vector

CVE-2026-69152 exploits how the library creates intermediate arrays during the expansion process. When processing complex nested patterns, the library would generate temporary arrays to hold intermediate results without enforcing any size limits. An attacker could craft a malicious input pattern that forces exponential growth in these intermediate arrays.

Consider this attack scenario:

// Malicious input that triggers unbounded expansion
const maliciousPattern = '{0..999999999}{0..999999999}{0..999999999}';
expand(maliciousPattern); // Attempts to create massive intermediate arrays
// Result: Out of memory error → Process crash

The vulnerable versions (1.1.11, 2.x pre-2.1.4, 3.x pre-3.0.6, 5.x pre-5.0.9) would attempt to allocate memory for all combinations without checking resource limits, leading to:

  • Immediate memory exhaustion: The process allocates gigabytes of RAM in seconds
  • Process termination: Node.js crashes with FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
  • Service unavailability: Any application using brace-expansion becomes unresponsive
  • Cascading failures: In microservices architectures, a single compromised input can take down multiple services

Real-World Attack Scenario

If your application accepts file patterns from users or external sources:

// Example: CLI tool that accepts glob patterns
const { expand } = require('brace-expansion');

app.post('/api/files', (req, res) => {
  const pattern = req.body.filePattern; // User-controlled input
  const files = expand(pattern); // VULNERABLE: No size validation
  res.json(files);
});

// Attacker sends:
// POST /api/files
// {"filePattern": "{0..999999}{0..999999}{0..999999}"}
// 
// Result: Server crashes with out-of-memory error

The Fix

The vulnerability was patched by upgrading brace-expansion to versions that implement strict resource consumption limits:

Before (Vulnerable):

brace-expansion@^1.1.7:
  version "1.1.11"
  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==

After (Patched):

brace-expansion@^1.1.7:
  version "1.1.18"
  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.18.tgz#3ce74d89885136be1535341f8c3d4425c29a5cab"
  integrity sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==

What Changed in the Patched Versions:

The fix implements resource consumption limits at the core of the expansion algorithm:

  1. Size limits on intermediate arrays: Patched versions enforce a maximum size on arrays created during expansion, preventing unbounded growth
  2. Early termination: When expansion would exceed safe limits, the algorithm terminates early rather than attempting infinite allocation
  3. Graceful degradation: Invalid or dangerous patterns are rejected with clear error messages instead of crashing the process

Affected Version Ranges:

The vulnerability was fixed across multiple version branches:

Version Branch Vulnerable Patched
1.1.x 1.1.11 and earlier 1.1.18+
2.x 2.1.3 and earlier 2.1.4+
3.x 3.0.5 and earlier 3.0.6+
5.x 5.0.8 and earlier 5.0.9+

Behavior Preservation:

The patched versions maintain backward compatibility with all legitimate use cases. Valid brace patterns continue to work as expected:

// All of these still work correctly in patched versions
expand('{a,b,c}')           // ['a', 'b', 'c']
expand('file{1..5}.txt')    // ['file1.txt', 'file2.txt', ..., 'file5.txt']
expand('{a,{b,c}}')         // ['a', 'b', 'c']

// Only malicious patterns that would cause unbounded expansion are blocked
expand('{0..999999}{0..999999}') // Now throws safe error instead of crashing

Prevention & Best Practices

1. Immediate Action: Update Dependencies

Run these commands to upgrade brace-expansion:

# Using npm
npm install brace-expansion@latest

# Using yarn
yarn upgrade brace-expansion

# Verify the version
npm list brace-expansion

Check your package.json to ensure you're using compatible versions:

{
  "dependencies": {
    "brace-expansion": "^1.1.18"
  }
}

2. Input Validation for Pattern Matching

If your application accepts user-provided patterns, implement validation:

const { expand } = require('brace-expansion');

function safeExpand(pattern, maxLength = 1000) {
  // Validate input length
  if (pattern.length > maxLength) {
    throw new Error('Pattern exceeds maximum length');
  }

  // Validate pattern structure
  if (!isValidBracePattern(pattern)) {
    throw new Error('Invalid brace pattern');
  }

  try {
    const result = expand(pattern);

    // Validate output size
    if (result.length > 10000) {
      throw new Error('Expansion results exceed safe limits');
    }

    return result;
  } catch (error) {
    throw new Error(`Failed to expand pattern: ${error.message}`);
  }
}

function isValidBracePattern(pattern) {
  // Basic validation: check for balanced braces
  let braceCount = 0;
  for (const char of pattern) {
    if (char === '{') braceCount++;
    if (char === '}') braceCount--;
    if (braceCount < 0) return false;
  }
  return braceCount === 0;
}

3. Resource Limits in Production

Configure Node.js process limits to prevent catastrophic failures:

# Limit memory to 512MB
node --max-old-space-size=512 app.js

# In Docker
docker run -e NODE_OPTIONS="--max-old-space-size=512" node:18 node app.js

4. Monitoring and Alerting

Implement monitoring for memory usage patterns:

const os = require('os');

setInterval(() => {
  const memUsage = process.memoryUsage();
  const heapUsedPercent = (memUsage.heapUsed / memUsage.heapTotal) * 100;

  if (heapUsedPercent > 90) {
    console.warn(`WARNING: Heap usage at ${heapUsedPercent.toFixed(2)}%`);
    // Alert ops team, gracefully shutdown, etc.
  }
}, 5000);

5. Security Standards Reference

This vulnerability relates to:
- CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion')
- CWE-776: Improper Restriction of Recursive Calls
- OWASP A06:2021: Vulnerable and Outdated Components

Key Takeaways

  • Unbounded intermediate arrays in brace-expansion created a direct path to memory exhaustion: The library's expansion algorithm had no limits on temporary array sizes, allowing attackers to trigger exponential memory allocation with crafted input patterns.

  • The vulnerability affects all major version branches: CVE-2026-69152 impacts brace-expansion 1.1.x, 2.x, 3.x, and 5.x versions, meaning it's likely present in your dependency tree unless recently updated.

  • Patched versions implement resource consumption limits without breaking legitimate use cases: Upgrading to 1.1.18, 2.1.4, 3.0.6, or 5.0.9 stops the attack while preserving normal functionality for valid patterns.

  • User-controlled pattern input requires additional validation: Even with patched brace-expansion, applications accepting external patterns should implement length checks and output size limits to prevent resource exhaustion.

  • This vulnerability demonstrates why dependency management is critical security infrastructure: A single compromised library can cascade failures across your entire application stack, making regular updates and vulnerability scanning essential.

How Orbis AppSec Detected This

Source: Dependency declaration in package.json and transitive dependencies in yarn.lock (brace-expansion package version 1.1.11)

Sink: Any call to expand() function in brace-expansion that processes user-influenced input or external patterns

Missing control: Absence of resource consumption limits on intermediate array allocations during brace pattern expansion; no validation of pattern complexity before processing

CWE: CWE-400 - Uncontrolled Resource Consumption ('Resource Exhaustion')

Fix: Upgrade brace-expansion from 1.1.11 to 1.1.18 (and equivalent patches for other version branches: 2.1.4, 3.0.6, 5.0.9) which implement strict limits on intermediate array sizes and early termination for dangerous patterns.

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 represents a critical reminder that even widely-used, well-maintained libraries can contain resource exhaustion vulnerabilities. The brace-expansion DoS demonstrates how missing resource limits in pattern-processing algorithms can become attack vectors for service disruption.

The good news: the fix is straightforward. By upgrading to patched versions (1.1.18, 2.1.4, 3.0.6, or 5.0.9) and implementing input validation in your application layer, you eliminate this attack surface entirely. The patched versions maintain full backward compatibility, making this one of the easiest security updates to deploy.

Make dependency updates a regular part of your security practice. Use tools like Trivy, Snyk, or npm audit to identify vulnerable versions automatically, and implement them as part of your CI/CD pipeline. Your production systems will thank you.


References

Frequently Asked Questions

What is a Denial of Service via unbounded resource consumption?

A DoS vulnerability where an attacker provides input that causes the application to allocate unbounded memory or CPU resources, exhausting system capacity and crashing the service.

How do you prevent unbounded resource consumption in brace-expansion?

Implement strict limits on the size of intermediate arrays created during pattern expansion, validate input length before processing, and upgrade to patched versions that enforce these limits.

What CWE is this vulnerability?

CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion'), which covers vulnerabilities where applications fail to properly limit resource allocation.

Is input validation enough to prevent this vulnerability?

Input validation alone is insufficient; you must also implement hard limits on intermediate data structures and upgrade to versions with built-in protections against resource exhaustion.

Can static analysis detect this vulnerability?

Yes, security scanners like Trivy can detect known vulnerable versions of brace-expansion in dependency trees, and code analysis tools can identify unbounded loops and array allocations.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #211

Related Articles

high

How Unauthenticated Denial of Service happens in React Router and how to fix it

CVE-2026-55685 is a high-severity Denial of Service vulnerability in React Router's `@remix-run/server-runtime` that allows unauthenticated attackers to exhaust server resources by sending crafted requests to the manifest endpoint. The fix upgrades `react-router` from version 7.17.0 to 7.18.0, which tightens handling of untrusted input in route matching logic. Developers using any React Router 7.x application with server-side rendering should apply this patch immediately.

high

How package_managers.pnpm.pnpm-missing-minimum-release-age.pnpm-minimum-release-age happens in pnpm and how to fix it

A pnpm workspace configuration in `site-astro/pnpm-workspace.yaml` was missing critical supply chain security settings including `minimumReleaseAge`, `trustPolicy`, and `blockExoticSubdeps`. Without these protections, the project could install freshly published malicious packages within minutes of their release. The fix adds a 7-day quarantine period, downgrade protection, and exotic subdependency blocking.

critical

How Command Injection happens in Node.js shell-quote and how to fix it

A critical command injection vulnerability (CVE-2026-9277) was discovered in shell-quote versions prior to 1.8.4, where unescaped line terminators allowed attackers to inject arbitrary shell commands through crafted input strings. The fix pins shell-quote to version 1.9.0 via a `package.json` overrides directive in the FabricExample project, ensuring all transitive dependencies resolve to the patched version. Left unaddressed, this vulnerability could have allowed arbitrary code execution on any

high

How Command Injection happens in Node.js child_process calls and how to fix it

A high-severity command injection vulnerability was discovered in `tools/utils/lang/helpers.ts` where the `prettier()` function passed a user-controllable `fileName` argument directly into a shell command string via `exec()`. By replacing `exec()` with `execFile()` and passing arguments as an array, the fix eliminates shell interpolation entirely, preventing attackers from injecting arbitrary shell commands through malicious filenames.

high

How Infinite Loop Denial of Service happens in nanoid custom alphabet generation and how to fix it

A high-severity infinite loop vulnerability (CVE-2026-67213) was discovered in nanoid versions before 5.1.6 and 3.3.17, affecting the custom alphabet generation feature. When processing certain malformed alphabet configurations, nanoid would enter an infinite loop, causing a complete denial of service. This vulnerability was fixed by upgrading from nanoid 3.3.16 to 3.3.17 and implementing dependency overrides to ensure the patched version is used throughout the dependency tree.

high

How Quadratic CPU Consumption in !!omap Resolution Happens in js-yaml and How to Fix It

A high-severity denial-of-service vulnerability in js-yaml (GHSA-5p4m-2wfm-xmqj) caused quadratic CPU consumption when resolving `!!omap` (ordered map) YAML tags, affecting both the 3.x and 4.x release lines. Upgrading to js-yaml 4.3.1 or 3.15.1 closes the gap by fixing the algorithmic inefficiency in `!!omap` duplicate-key detection. Any application that parses untrusted YAML input is at risk of resource exhaustion leading to service unavailability.