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
•Technically reviewed by Anupam Mediratta•Published September 7, 2026•Reviewed 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.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #329

Related Articles

critical

Lampa Desktop Auto-Update Heuristic Bypass: Execution of Unverified

Lampa Desktop's auto-update mechanism downloaded JavaScript and CSS from `raw.githubusercontent.com` using only heuristic validation—file size thresholds and string pattern matching—that attackers could trivially satisfy. The fix introduces cryptographic integrity verification by cross-referencing Git blob hashes from the GitHub Contents API, ensuring downloaded code matches the repository's authoritative state before execution.

high

adm-zip 0.6.0 Preserves SUID Bits From ZIPs: CVE-2026-102282

The `adm-zip` dependency resolved to 0.6.0 in this project's dependency tree, a version affected by CVE-2026-102282: during extraction it applies the Unix permission bits stored in each ZIP entry's external file attributes verbatim, including the setuid (`04000`), setgid (`02000`), and sticky bits. An attacker who controls an archive passed to `extractAllTo()` or `extractEntryTo()` can therefore have the extractor create a setuid binary owned by whatever user the extraction process runs as. The

high

requestInput() Type Confusion: NaN and Object Bypass in JavaScript

The `requestInput()` utility function lacked validation on its `type` parameter and failed to handle `NaN` results from float conversions, creating a type confusion weakness. An attacker could supply malformed inputs that propagate unhandled `NaN` values or unexpected object types through the type system. The fix adds explicit guards against `NaN` type parameters and rejects non-primitive type values.

critical

No Rate Limit on /api/uploads/presign Enables DoS

The `/api/uploads/presign` endpoint accepted unlimited concurrent requests to generate storage presigned URLs, giving an attacker a free lever to exhaust storage-provider quotas and server resources. The fix adds an `express-rate-limit` middleware capping each client to 30 requests per minute on that route.

high

CVE-2026-54673: builder-util-runtime Leaks Auth Headers on Redirect

electron-updater and electron-builder rely on builder-util-runtime to fetch update manifests and artifacts over HTTP. A flaw in that shared HTTP executor allowed credential headers attached to the original update-feed request to be re-sent after a redirect, exposing them to any host the redirect pointed to. The project fixes this by upgrading builder-util-runtime to 9.7.0 and collapsing a duplicate, older copy of the package that electron-updater had pinned on its own.

high

image-size 1.2.1 DoS: Zero-Valued Dimensions in Image Buffer Parser

A high-severity denial-of-service vulnerability in image-size 1.2.1 allows attackers to crash Node.js services using malicious image buffers with zero-valued dimensions. The fix removes the vulnerable `queue` dependency and tightens dimension validation in version 2.0.3.