Introduction
In the exia-invasion project, a high-severity Denial of Service vulnerability was identified in the package-lock.json dependency tree. The brace-expansion package at version 1.1.12—used transitively through minimatch and readdir-glob—contained a flaw that allowed crafted brace patterns to generate unbounded intermediate arrays, exhausting system memory and crashing the application.
What makes CVE-2026-69152 particularly dangerous is that it bypasses the earlier CVE-2026-14257 mitigation. The prior fix added limits to final expansion output, but the new vulnerability exploits the intermediate expansion steps where arrays grow without bounds before any size check is applied. This means projects that believed they were patched against brace-expansion DoS attacks remained vulnerable.
The vulnerability was present in two locations within exia-invasion/package-lock.json: the top-level brace-expansion at version 1.1.12 and a nested instance under readdir-glob/node_modules/brace-expansion at version 2.0.2.
The Vulnerability Explained
How brace-expansion works
The brace-expansion package expands shell-like brace patterns into arrays. For example:
"{a,b}{c,d}" → ["ac", "ad", "bc", "bd"]
This is used by minimatch for glob pattern matching, which in turn powers file system operations in many Node.js applications.
The unbounded intermediate array problem
During expansion, brace-expansion processes nested patterns iteratively. Each level of nesting multiplies the intermediate result array. The CVE-2026-14257 fix added a check on the final output size, but CVE-2026-69152 exploits the fact that intermediate arrays generated between expansion steps have no such bounds.
Consider a crafted input like:
"{a{1..9999},b{1..9999}}{c{1..9999},d{1..9999}}"
Before the final output check kicks in, the intermediate expansion of inner braces creates massive temporary arrays. An attacker can craft patterns where these intermediate arrays grow exponentially while the final output appears bounded—effectively bypassing the prior mitigation.
The vulnerable dependency tree
In exia-invasion/package-lock.json, the vulnerable versions were:
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="
}
And the nested version under readdir-glob:
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="
}
Attack scenario
If the exia-invasion application processes user-supplied glob patterns (e.g., for file selection, search filtering, or path matching), an attacker could submit a specially crafted brace pattern that triggers exponential intermediate array growth. This would cause:
- Memory exhaustion: The Node.js process allocates gigabytes of memory for intermediate arrays
- Process crash: The system runs out of memory, triggering an OOM kill
- Service unavailability: The application becomes unresponsive to legitimate requests
Even if the application doesn't directly expose glob matching to users, any code path where minimatch or readdir-glob processes partially user-influenced patterns (directory names, file filters) could be exploited.
The Fix
Changes made
The fix upgrades brace-expansion across the entire dependency tree to version 1.1.18, which enforces bounds on intermediate array growth during expansion.
Before — vulnerable brace-expansion 1.1.12 at the top level:
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="
}
After — patched brace-expansion 1.1.18:
"node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw=="
}
Eliminating the nested vulnerable version
The fix also removes the nested brace-expansion 2.0.2 under readdir-glob/node_modules/ and replaces it with a properly scoped 1.1.18 instance under readdir-glob/node_modules/minimatch/node_modules/:
Before — vulnerable nested version:
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"dependencies": {
"balanced-match": "^1.0.0"
}
}
After — patched version scoped correctly:
"node_modules/readdir-glob/node_modules/minimatch/node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
}
Why both changes matter
- Top-level upgrade (1.1.12 → 1.1.18): Fixes the primary
brace-expansionused by most of the dependency tree - Nested version restructuring (2.0.2 removed, 1.1.18 added under minimatch): Ensures
readdir-glob'sminimatchdependency also uses a patched version, preventing the vulnerability from lurking in a transitive dependency
The version 1.1.18 adds intermediate array size checks that abort expansion before memory can be exhausted, regardless of how the pattern is structured.
Prevention & Best Practices
Dependency management
- Pin and audit dependencies regularly: Use
npm auditor dedicated tools like Trivy to scanpackage-lock.jsonfor known vulnerabilities - Understand transitive dependencies: The nested
brace-expansion2.0.2 underreaddir-globdemonstrates how vulnerabilities hide in transitive dependencies - Use lock file integrity checks: The
integrityfield inpackage-lock.jsonensures you're getting the exact expected package bytes
Input validation
- Limit pattern complexity: If your application processes user-supplied glob patterns, enforce maximum length and nesting depth before passing to
minimatch - Timeout pattern expansion: Wrap glob operations in timeouts to prevent runaway expansion from blocking the event loop
Monitoring
- Memory usage alerts: Set up monitoring for sudden memory spikes that could indicate DoS exploitation
- Rate limiting: Apply rate limits to endpoints that process glob or pattern-matching operations
Relevant standards
- CWE-400: Uncontrolled Resource Consumption
- OWASP: Application Denial of Service prevention guidelines
- Node.js Security Best Practices: Regular dependency updates and auditing
Key Takeaways
- Bypass vulnerabilities are real: CVE-2026-69152 specifically bypasses CVE-2026-14257's mitigation by exploiting intermediate array growth rather than final output size—always verify that security fixes cover all code paths
- Nested dependencies in
package-lock.jsoncan harbor separate vulnerable versions: Thereaddir-glob/node_modules/brace-expansionat 2.0.2 was a distinct vulnerable instance from the top-level 1.1.12 - Even "utility" packages like
brace-expansioncan be high-severity attack vectors: This package is used byminimatch, which is one of the most depended-upon packages in the npm ecosystem - Lock file restructuring may be necessary: Simply bumping a version number isn't always sufficient—the fix required removing a nested dependency and re-scoping it under the correct parent
- DoS vulnerabilities in pattern expansion libraries affect any application processing user-influenced file paths or glob patterns
How Orbis AppSec Detected This
- Source: User-influenced input reaching glob pattern processing (file paths, search patterns, or directory filters passed to
minimatchorreaddir-glob) - Sink:
brace-expansionexpansion function innode_modules/brace-expansion/index.jswhere intermediate arrays are generated without bounds - Missing control: No intermediate array size limit during brace expansion steps—only final output was bounded by the CVE-2026-14257 fix
- CWE: CWE-400 (Uncontrolled Resource Consumption)
- Fix: Upgraded
brace-expansionfrom 1.1.12 and 2.0.2 to 1.1.18 across the dependency tree, which enforces intermediate array bounds during expansion
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 stark reminder that security patches aren't always complete on the first attempt. The original CVE-2026-14257 fix addressed final output bounds but left intermediate arrays unchecked—a gap that attackers could exploit to achieve the same DoS effect. By upgrading brace-expansion to 1.1.18 and restructuring the nested dependency tree, the exia-invasion project eliminates both the direct and transitive exposure to this vulnerability.
For any Node.js project using minimatch, readdir-glob, or any package that depends on brace-expansion, verify your package-lock.json contains version 1.1.18+, 2.1.4+, 3.0.6+, or 5.0.9+ depending on your major version line. Run npm audit today to check.