Summary
brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion
expand_() recurses once per level of brace nesting. Deeply nested input exhausts the native stack and crashes the process.
This is distinct from CVE-2026-14257 / GHSA-mh99-v99m-4gvg, which made the tail iterative (recursion on m.post, driven by how many groups are chained). Nesting depth drives a different recursion that the tail fix never touched, so the documented constant-stack-depth guarantee only ever covered chained input, not nested input.
It is also distinct from GHSA-6j4f-fj2g-mc7p, which fixed recursion in parseCommaParts(). Both payloads below still crash with that fix applied.
Two recursion sites
Comma members. Each alternative of a brace set is expanded by a recursive call, so nesting a set inside every alternative recurses once per level:
expand('{a,'.repeat(4000) + 'z' + '}'.repeat(4000))
// RangeError: Maximum call stack size exceeded
Crashes at depth 3,907 - about 15.6 KB of input.
Single set. A brace set whose body parses to a single part is expanded by a recursive call before being re-wrapped (x{{a,b}}y -> x{a}y x{b}y), which recurses once per nesting level:
expand('{'.repeat(3200) + 'a,b' + '}'.repeat(3200))
// RangeError: Maximum call stack size exceeded
Crashes at depth 3,125 - about 6.25 KB of input. This is the cheapest stack-exhaustion payload known against this package: roughly a quarter the input of GHSA-6j4f-fj2g-mc7p (29 KB), and about a tenth of minimatch's MAX_PATTERN_LENGTH (65,536).
Why max and maxLength do not help
Both crashes happen while recursing into sub-expansions, before the result set grows. The payloads produce almost no output - the single-set case yields 2 results - so neither bound is ever the limiter. expand(payload, { max: 1, maxLength: 1 }) still overflows.
Affected versions
Verified affected on 1.1.18, 2.1.4, 3.0.6 and 5.0.9, at near-identical depths on every line (single set: 3,125 on all four; comma members: 3,907-4,102). Not a regression from any recent fix - the gap predates them.
Impact
Any application passing an untrusted string to expand(), directly or through minimatch / glob as a user-supplied glob pattern, can be crashed. In Node a RangeError the application does not catch terminates the process, so a server globbing user input is exposed to remote unauthenticated denial of service.
Availability only. No code execution, no data exposure.
Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service. Typical impact: denial of service.
CVE-2026-102278 has a CVSS score of 7.5 (High). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (5.0.11, 3.0.8, 2.1.6, 1.1.20); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
A maxDepth bound (default EXPANSION_MAX_DEPTH) is threaded through expand_(). Past the cap a group is treated as non-expanding and returned literally, which is how the parser already handles a group that cannot expand. This matches the existing max / maxLength caps, which truncate rather than throw, so expand() continues never to throw on any input.
The default sits far above any realistic nesting depth and well below the crash threshold.
Frequently Asked Questions
- What is CVE-2026-102278? CVE-2026-102278 is a high-severity uncontrolled resource consumption vulnerability in brace-expansion (npm), affecting versions >= 4.0.0, < 5.0.11. It is fixed in 5.0.11, 3.0.8, 2.1.6, 1.1.20. Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service.
- How severe is CVE-2026-102278? CVE-2026-102278 has a CVSS score of 7.5 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of brace-expansion are affected by CVE-2026-102278? brace-expansion (npm) versions >= 4.0.0, < 5.0.11 is affected.
- Is there a fix for CVE-2026-102278? Yes. CVE-2026-102278 is fixed in 5.0.11, 3.0.8, 2.1.6, 1.1.20. Upgrade to this version or later.
- Is CVE-2026-102278 exploitable, and should I be worried? Whether CVE-2026-102278 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-102278 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-102278?
- Upgrade
brace-expansionto 5.0.11 or later - Upgrade
brace-expansionto 3.0.8 or later - Upgrade
brace-expansionto 2.1.6 or later - Upgrade
brace-expansionto 1.1.20 or later
- Upgrade