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:
- Size limits on intermediate arrays: Patched versions enforce a maximum size on arrays created during expansion, preventing unbounded growth
- Early termination: When expansion would exceed safe limits, the algorithm terminates early rather than attempting infinite allocation
- 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
- CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion')
- OWASP: Vulnerable and Outdated Components (A06:2021)
- npm brace-expansion package
- Node.js Memory Management Documentation
- Semgrep: Resource Exhaustion Rules
- GitHub PR: fix: upgrade brace-expansion to 1.1.18, 2.1.4, 3.0.6, 5.0.9 (CVE-2026-69152)