Skip to main content

brace-expansion CVE-2026-69152

| EUVDEUVD-2026-52370 HIGH
Uncontrolled Resource Consumption (CWE-400)
2026-08-03 https://github.com/juliangruber/brace-expansion GHSA-rgw5-rvv9-x895
7.5
CVSS 3.1 · Vendor: https://github.com/juliangruber/brace-expansion
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Craft malicious brace pattern string
  2. Delivery
    Submit via exposed input channel
  3. Exploit
    expand_() builds unbounded intermediate arrays
  4. Execution
    combine() maxLength guard triggers too late
  5. Persist
    V8 heap exhausted
  6. Impact
    Node.js process terminates with fatal OOM

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A06:2025 - Insecure Design
ASVS 5.0
V2 - Validation and Business Logic Resource consumption limits
MITRE ATT&CK

1 technique across 1 tactic: Impact

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires that the target application passes attacker-controlled string data to expand() from the brace-expansion library, either directly or transitively through a glob or pattern-matching library such as minimatch or glob. No authentication, privileged access, or non-default configuration is required on the attacker's side - only the ability to supply input to an exposed string-processing endpoint (e.g., a file search field, log query interface, build artifact pattern, or CLI argument). The memory-exhaustion path requires an input of approximately 25 KB structured as many comma-separated alternatives; the event-loop-stall path requires approximately 400 KB structured as a single wide padded numeric sequence. Exploitation is limited to: the Node.js runtime (the V8 cons-string behavior that hides the CPU path's memory footprint is engine-specific); brace-expansion versions in the affected ranges across all four version lines (< 1.1.18, 2.0.0-2.1.3, 3.0.0-3.0.5, 4.0.0-5.0.8); and applications that expose any code path reaching expand() to external input. Applications that sanitize or reject large inputs upstream, or that never pass untrusted data into brace/glob evaluation, are not exploitable.

Impact

The vendor-assigned CVSS 3.1 score of 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) is consistent with the technical evidence: network reachability, low attack complexity, and no privileges required are all accurate for any application exposing brace-pattern input externally. The practical risk is elevated beyond what a mid-7 score might suggest for three independent reasons: the memory-exhaustion variant produces a fatal V8 OOM abort that bypasses try/catch entirely, making in-process resilience measures ineffective; a detailed proof-of-concept is publicly embedded in the GHSA advisory; and brace-expansion is a ubiquitous transitive dependency, meaning the blast radius extends to any Node.js application indirectly using npm, glob, or minimatch without necessarily knowing it. No EPSS score was provided and no CISA KEV listing is recorded, so widespread automated exploitation has not been confirmed - this signals targeted rather than opportunistic exploitation at present. The absence of a confidentiality or integrity impact keeps the CVSS score from reaching Critical, but the combination of published POC, uncatchable crash vector, and enormous transitive footprint makes this a genuine remediation priority rather than a theoretical high-CVSS-but-low-real-risk issue.

Exploit ScenarioDerived

An attacker submits a crafted ~25 KB HTTP request body containing a brace pattern composed of approximately 400 comma-separated alternatives, each embedding a padded numeric sequence (e.g., { + 400 repetitions of {00...01..100000} joined by commas + }), to any application endpoint that evaluates glob or file-path patterns using glob, minimatch, or a direct call to brace-expansion's expand(). The expand_() function allocates intermediate arrays totaling far beyond the default Node.js heap without triggering the combine() guard, causing a fatal V8 out-of-memory abort that kills the entire process; wrapping the call in try/catch does not prevent the crash. A working proof-of-concept demonstrating exactly this sequence is publicly available in the GHSA advisory.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
1 PoC candidate (unverified) Patch available 0.4% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Aug 03, 2026

Remote denial-of-service in the brace-expansion npm library (all active version lines prior to 1.1.18, 2.1.4, 3.0.6, and 5.0.9) allows unauthenticated attackers to either crash the Node.js process via an uncatchable out-of-memory error with a ~25 KB crafted input, or stall the event loop for over two minutes with a ~400 KB padded-sequence input. Both attack paths bypass the incomplete mitigation introduced in version 5.0.8 for CVE-2026-14257, meaning applications that already patched that predecessor vulnerability remain fully exposed. Publicly available proof-of-concept code is included in the GitHub security advisory; no CISA KEV listing is present at time of analysis.

RemediationAI

Upgrade brace-expansion to the appropriate fixed release for the installed version line: 1.1.18, 2.1.4, 3.0.6, or 5.0.9. Because brace-expansion is typically installed as a transitive dependency, run npm ls brace-expansion or npm audit to identify all installed copies and the parent packages pinning them to vulnerable versions; upgrade those parent packages accordingly. Patch commits are available at https://github.com/juliangruber/brace-expansion/commit/139d015104e71433ad52a41d19467c48ecbb2c7d and https://github.com/juliangruber/brace-expansion/commit/1e30c930238d7162802d88a94189182def178dac. If immediate upgrade is not possible, the advisory recommends passing an explicitly small max and maxLength together to expand() - for example { max: 1000, maxLength: 10000 } - as a compensating control; however, note that maxLength alone was insufficient on affected versions because it was enforced per-alternative rather than cumulatively, which is the root cause of the first bug. The most reliable workaround is to avoid passing untrusted input to any function that transitively calls expand(), including glob pattern evaluation.

Affected VersionsENISA

brace-expansion 2.0.0, < 2.1.4
brace-expansion 4.0.0, < 5.0.9
brace-expansion < 1.1.18
brace-expansion 3.0.0, < 3.0.6

Affected Packages

npm brace-expansion fix: 1.1.18, 2.1.4, 3.0.6, 5.0.9

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

brace-expansion (pkg:npm/brace-expansion) is a JavaScript library that expands Unix brace-notation patterns such as {a,b,c} and {1..5} into arrays of strings; it is a transitive dependency of npm itself, minimatch, glob, and thousands of downstream packages. CWE-400 (Uncontrolled Resource Consumption) applies through two distinct intermediate-data-structure paths inside expand_(). In the first path, each comma-separated alternative in a {a,b,...} pattern is expanded by its own recursive expand_() call, each receiving a full independent maxLength budget, and all results are concatenated into a single values array with no cumulative running total - allowing values to reach A × maxLength characters before combine() ever checks bounds. In the second path, expandSequence() accepted a max (result-count) bound but never consulted maxLength, so padded-numeric sequences of arbitrary width were fully generated before combine() discarded excess results; V8's cons-string representation kept heap flat, hiding the cost as wall-clock CPU time rather than memory pressure. Both paths were introduced by the design of the 5.0.8 fix, which guarded only the single accumulator in combine() rather than the two intermediate arrays that feed it.

Know when the next one hits your stack

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/juliangruber/brace-expansion) PRIMARY 7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
vuln.today AI 7.5 HIGH

Network vector and no privileges because any input channel suffices; High availability from uncatchable process crash; no confidentiality or integrity impact.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE HIGH
Red Hat 7.5 HIGH

Primary rating from Vendor (https://github.com/juliangruber/brace-expansion).

CVSS VectorVendor: https://github.com/juliangruber/brace-expansion

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

DescriptionCVE.org

Summary

The maxLength mitigation added in 5.0.8 for GHSA-mh99-v99m-4gvg / CVE-2026-14257 is incomplete. It bounds the accumulator where results are *combined*, but not the intermediate arrays that feed it. A ~25 KB input still crashes the Node process with an uncatchable out-of-memory error, so try/catch around expand() does not help.

A second, related path in the same function lets a ~400 KB input block the event loop for over two minutes without ever exceeding the memory bound.

Details

maxLength was enforced in combine(), the single place output grows. Two arrays are built *before* combine() runs, and neither was bounded.

1. Comma alternatives accumulate without a running total (memory exhaustion)

Each alternative in {a,b,c,...} is expanded by its own recursive expand_() call, so each receives a full, independent maxLength allowance. The results were then concatenated into a single values array with no cumulative limit:

js
values = []
for (let j = 0; j < n.length; j++) {
  values.push.apply(values, expand_(n[j], max, maxLength, false))
}

acc = combine(acc, pre, values, max, maxLength, ...)

With A alternatives, values can reach A * maxLength characters before combine() gets a chance to truncate it. At the default maxLength of 4,000,000 and 400 alternatives, that is well past any default heap.

2. Padded sequences ignore maxLength while generating (CPU exhaustion)

expandSequence() was bounded by max (the result *count*) but never consulted maxLength. A padded sequence's element width follows the input, so {0...01..100000} with a wide pad generates max elements, each as wide as the input, only for combine() to discard all but a handful.

Memory stays flat here, because V8 represents the padded strings as cons-strings, which is likely why this path was not caught alongside the original issue. The cost is time: work proportional to max * width.

pad widthinput bytesresults kepttime (5.0.8)time (patched)
20,00020 KB199~7.3 s~20 ms
100,000100 KB39~32 s~20 ms
400,000400 KB9~124 s~18 ms

Output is byte-identical before and after the fix; only the wasted work is removed.

Proof of concept

Memory exhaustion, against 5.0.8:

js
import { expand } from 'brace-expansion'

const part = '{' + '0'.repeat(50) + '1..100000}'
const input = '{' + Array(400).fill(part).join(',') + '}'  // ~25 KB

try {
  expand(input)
} catch (e) {
  // never reached - the process is already dead
}
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Aborted

Event-loop stall, against 5.0.8:

js
import { expand } from 'brace-expansion'

// ~400 KB input, returns 9 results after roughly two minutes of blocking CPU
expand('{' + '0'.repeat(400_000) + '1..100000}')

Impact

Denial of service. Any application that passes attacker-controlled input to expand(), directly or transitively through a glob or pattern-matching library, can be remotely crashed or stalled. The out-of-memory variant terminates the process and cannot be handled with try/catch.

Applications already on 5.0.8 are affected: the 5.0.8 mitigation does not cover these paths.

Patches

Both intermediate arrays are now bounded as they are built, using the same max and maxLength limits already applied in combine():

  • values tracks a running result count and character length while alternatives are appended, and stops once either bound is reached.
  • expandSequence() accepts maxLength and stops generating once the sequence's own characters reach it.

As with the existing limits, output is truncated rather than allowed to grow without bound, which matches how max already behaves. The defaults sit well above any realistic expansion, so legitimate input is unaffected.

Workarounds

If upgrading is not immediately possible, avoid passing untrusted input to expand() or to glob brace patterns, or pass an explicitly small max and maxLength.

Note that a small maxLength alone was not sufficient on affected versions: it was applied per alternative rather than cumulatively, which is the root of the first issue above.

Credits

The memory-exhaustion bypass was reported by Alessio Della Libera, CEO & Co-founder at Numyra.

The sequence-generation issue was found while verifying that report.

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 1 npm packages depend on brace-expansion (1 direct, 0 indirect)

Ecosystem-wide dependent count for version 2.0.0.

Latest POC

1 PoC candidate from github (unverified)

Sign in to open the public PoC links collected for this CVE.

Executive ViewAI

Why It Matters

Organizations using the brace-expansion npm library in production face immediate risk of service disruption through remote denial-of-service attacks requiring no authentication. Publicly available attack code eliminates technical barriers to exploitation, making this a business continuity concern that demands urgent remediation.

Business Impact: High
Compensating Controls

Vendor-released patch: versions 1.1.18, 2.1.4, 3.0.6, and 5.0.9 for respective version lines.

Threat Intelligence Overview

EPSS Score
0.4%
Top 71% exploitable
Prevalence
Ubiquitous
core transitive npm dependency of npm, glob, and minimatch
Threat Intel
1
1 sources
Social Media
2
Sightings
Data Quality
8 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA MSRC Vendor CIRCL GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC Yes
EPSS 0.4%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Out-of-Cycle
Exploitation
Poc
System Exposure· derived
Open
Automatable
Yes
Human Impact
High
Technical Impact
Partial

Priority Score

58
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.

Vendor StatusVendor

SUSE

Severity: Important
Product Status
SUSE Liberty Linux 10 Fixed
SUSE Liberty Linux 8 Fixed
SUSE Linux Enterprise Server 16.0 Affected
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.0 Affected

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy