CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-102278

CVE-2026-102278: Stack-Based Denial of Service via Uncontrolled Recursion in brace-expansion

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 30, 2026·7 min read·56 visits

Executive Summary (TL;DR)

Uncontrolled recursion in nested brace groups allows unauthenticated attackers to crash the Node.js process via a stack overflow using compact (~6KB) inputs.

A stack-based Denial of Service (DoS) vulnerability via uncontrolled recursion in the brace-expansion library prior to versions 1.1.20, 2.1.6, 3.0.8, and 5.0.11 allows unauthenticated remote attackers to trigger native stack exhaustion, terminating the Node.js process via a crafted payload containing deeply nested brace groups.

Vulnerability Overview

The brace-expansion npm package is a widely used utility designed to resolve shell-like brace patterns into expanded string arrays. It is commonly integrated into toolchains, file-matching utilities, and security-critical path parsing systems such as the minimatch and glob libraries. Because these utilities often ingest user-provided input to locate resources or map system actions, the expansion parser forms an important security boundary for incoming input strings.

This vulnerability belongs to the class of Uncontrolled Recursion (CWE-674) leading to Uncontrolled Resource Consumption (CWE-400). When the library is supplied with deeply nested brace groups, the internal parsing function executes recursively for each level of nesting. Without structural limits on recursion depth, this execution pattern exhausts the allocated call stack of the underlying runtime engine.

The resulting impact is a severe, process-terminating Denial of Service (DoS). Because Node.js operates on a single-threaded event loop, an unhandled stack overflow exception terminates the application process abruptly. In environments lacking automated process restoration, this completely disables the application's availability to all users.

Root Cause Analysis

To resolve shell-like brace patterns (such as a{b,c}d into abd and acd), the brace-expansion library evaluates individual structural components recursively. A prior vulnerability, CVE-2026-14257, was mitigated by converting tail-parsing recursion into an iterative loop. This adjustment protected the library against chained sequences of expansion groups (such as a{b,c}d{e,f}...), ensuring that sequentially parsed blocks did not consume call stack frames.

However, the previous mitigation left nested brace groups completely unconstrained. The internal expansion engine relies on the function expand_ to process subdivisions of nesting. Uncontrolled recursion occurs in two distinct parsing conditions:

  1. Comma-Member Sets: In structures containing alternative execution paths within comma-separated segments (such as {a,{b,c}}), the parser recursively expands the internal structures before mapping the parent sequence.

  2. Single-Part Set Wrapping: In structures where a set consists of a single part requiring subsequent re-wrapping (such as x{{a,b}}y mapping to x{a}y and x{b}y), the code initiates a recursion pass on the inner content.

The V8 JavaScript engine enforces a hard limit on the native call stack size to prevent runaway memory consumption. If an untrusted string containing several thousand nested brackets is passed to the parser, the continuous allocation of activation records exceeds this stack frame ceiling. The environment throws a RangeError: Maximum call stack size exceeded exception. Because the exception is generated within the native engine loop of the library, applications rarely wrap these utilities in exception handling blocks, leading to immediate process termination.

Code Analysis

To understand the precise vulnerability and its mitigation, we analyze the changes introduced across the package branches. The patch implements a recursion-tracking mechanism by passing and incrementing a depth variable through the call tree.

The vulnerable code path did not enforce any structural depth tracking. In the TypeScript implementation, the entry-point function invoked the parser with hardcoded execution parameters:

// Vulnerable invocation path
return expand_(escapeBraces(str), max, maxLength, true).map(
  unescapeBraces,
)

The modified code introduces a default safety constant EXPANSION_MAX_DEPTH = 1000 and configures the main execution path to pass a starting depth of 0 while exposing maxDepth to users:

// Patched entry-point configuration
export const EXPANSION_MAX_DEPTH = 1_000
 
export function expand(str: string, options: BraceExpansionOptions = {}) {
  // ...
  const {
    max = EXPANSION_MAX,
    maxLength = EXPANSION_MAX_LENGTH,
    maxDepth = EXPANSION_MAX_DEPTH,
  } = options
 
  return expand_(escapeBraces(str), max, maxLength, maxDepth, 0, true).map(
    unescapeBraces,
  )
}

Inside the recursive expand_ function, a strict guard is positioned at the very top of the function body. If the tracking parameter depth exceeds the configured maxDepth, the recursion terminates early and returns the string literally:

function expand_(
  str: string,
  max: number,
  maxLength: number,
  maxDepth: number,
  depth: number,
  isTop: boolean,
): string[] {
  // Guard clause against deep nesting exhaustion
  if (depth > maxDepth) {
    return [str]
  }
  // ...

The recursive calls for both comma-member processing and single-part re-wrapping are modified to increment the depth parameter:

// Single-part set wrapping recursion path
n = expand_(n[0], max, maxLength, maxDepth, depth + 1, false).map(
  embrace,
)
 
// ...
 
// Comma-member expansion recursion path
const expanded = expand_(
  n[j] as string,
  max,
  maxLength,
  maxDepth,
  depth + 1,
  false,
)

By transitioning the return type to a literal string array once the maximum depth is violated, the function avoids raising an exception entirely. This ensures that the function remains total (non-throwing) and executes deterministically regardless of input complexity.

Exploitation Methodology

Exploiting this vulnerability does not require authentication or specific configuration parameters. The attacker must only identify an application endpoint that accepts a string and passes it into a component utilizing brace-expansion. Because the library is a common dependency of glob-matching libraries, applications that accept search queries or route definitions are vulnerable.

Because the execution limiters introduced in prior patches only restricted total string length (EXPANSION_MAX_LENGTH) and total output item count (EXPANSION_MAX), they are ineffective at preventing this crash. A payload containing nested braces produces a final output of negligible size and length, bypassing both checks. For instance, {{{...a,b...}}} results in only a single expansion array with two strings, but the depth of the tree is what triggers the crash.

Two specific payload formats can be leveraged to trigger process termination depending on the targeted code-level handling:

// Payload A: Single-Part Nested Set Shape (~6KB)
const expand = require('brace-expansion');
const payload = '{'.repeat(10000) + 'a,b' + '}'.repeat(10000);
expand(payload); // Instantly triggers RangeError and crashes Node.js
// Payload B: Comma-Member Nested Set Shape (~15.6KB)
const expand = require('brace-expansion');
const payload = '{a,'.repeat(10000) + 'z' + '}'.repeat(10000);
expand(payload); // Crashes the process via native call stack exhaustion

These payloads are highly compact, meaning standard HTTP request body limiters (which typically allow up to 100KB or 1MB) will fail to block them. This disparity allows attackers to exhaust the host's capabilities with minimal network overhead.

Impact Assessment

The primary security impact of CVE-2026-102278 is a complete and low-cost Denial of Service (DoS) of the targeted Node.js process. In single-threaded JavaScript environments, an unhandled exception of this nature stops the entire event loop, dropping all active connections and preventing the server from handling subsequent requests.

The CVSS v3.1 base score for this vulnerability is assessed at 7.5 (High), with the vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. The severity is elevated because the attack can be launched remotely without credentials, is simple to execute, requires no user interaction, and results in a total loss of availability for the component.

In containerized or cloud-native environments, container runtimes may automatically restart the crashed process. However, if an attacker repeatedly sends the payload, the rapid loop of crashes and restarts—often called a crash-loop state—will quickly exhaust container resource limits, raise orchestration alerts, and degrade the performance of adjacent services sharing the same node.

Remediation and Mitigation

The definitive resolution for this vulnerability is upgrading the brace-expansion library to a patched release. Maintainers have released fixes across all major version branches. Organizations should audit their dependency trees and enforce the following upgrade paths:

  • In projects using 1.x branches, upgrade to 1.1.20 or higher.
  • In projects using 2.x branches, upgrade to 2.1.6 or higher.
  • In projects using 3.x branches, upgrade to 3.0.8 or higher.
  • In projects using 4.x or 5.x branches, upgrade to 5.0.11 or higher.

If upgrading is not immediately possible, applications should implement input-validation middleware to inspect string inputs for repeated brace patterns. Rejecting inputs that exceed a specific number of nested braces (for example, preventing sequences of more than 10 consecutive { or } characters) effectively mitigates the exploit path. Additionally, configuring a process manager such as pm2 or using clustered Node.js configurations can maintain service availability by automatically spawning worker processes when an unhandled crash occurs.

Official Patches

juliangruberNesting depth enforcement commit inside TypeScript implementation.
juliangruberNesting depth enforcement commit inside vanilla JS ESM module.
juliangruberNesting depth enforcement commit inside CommonJS legacy module.

Fix Analysis (3)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.35%
Top 74% most exploited

Affected Systems

Node.js applications processing untrusted shell-like patterns or glob vectors via brace-expansion.Libraries utilizing brace-expansion transitively, such as older versions of minimatch or glob parsers.

Affected Versions Detail

Product
Affected Versions
Fixed Version
brace-expansion
juliangruber
< 1.1.201.1.20
brace-expansion
juliangruber
>= 2.0.0, < 2.1.62.1.6
brace-expansion
juliangruber
>= 3.0.0, < 3.0.83.0.8
brace-expansion
juliangruber
>= 4.0.0, < 5.0.115.0.11
AttributeDetail
CWE IDCWE-674
Attack VectorNetwork (Unauthenticated)
CVSS7.5 (High)
EPSS0.0035 (26th percentile)
ImpactDenial of Service (Process Termination)
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-674
Uncontrolled Recursion

The software directs the code to recurse, but it does not limit or control the number of recursive loops, leading to stack exhaustion.

Known Exploits & Detection

GitHub AdvisorySecurity advisory details containing vulnerability mechanics and reproduction methods.

Vulnerability Timeline

Technical fix commits designed, implemented, and merged by maintainer Julian Gruber on repository branches.
2026-09-14
Security advisory published and CVE-2026-102278 assigned. Patched packages released.
2026-09-28
EPSS scores populated and threat models analyzed. No active exploitation identified.
2026-09-29

References & Sources

  • [1]Official GitHub Advisory GHSA-qhr7-859c-m2p7
  • [2]NVD CVE-2026-102278 Reference

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•3 minutes ago•CVE-2026-128087
3.7

CVE-2026-128087: Premature Key Exchange Callback Invocation Prior to Host Key Verification in russh

CVE-2026-128087 (GHSA-9264-jvgf-6w2f) is an incorrect behavior order (CWE-696) and improper authorization (CWE-863) vulnerability in the russh Rust SSH library, affecting versions 0.55.0 through 0.65.0. During the initial SSH key exchange (KEX) handshake, the client state machine invokes the client::Handler::kex_done() callback—providing the negotiated raw shared secret bytes—prior to validating the remote server's host key or certificate via check_server_key(). Consequently, an untrusted or rogue SSH server can complete cryptographic key agreement and force a connecting client to execute side-effecting application logic inside kex_done() before the server's identity is checked and rejected.

Amit Schendel
Amit Schendel
0 views•10 min read
•about 1 hour ago•CVE-2026-128082
7.5

CVE-2026-128082: Uncontrolled Recursion and Denial of Service in AutoMapper via Constructor Parameter Mapping

CVE-2026-128082 (GHSA-6vhm-j9h7-f9gh) is an uncontrolled recursion vulnerability (CWE-674) in AutoMapper, a convention-based object-object mapper for .NET. When mapping nested or self-referential types into destination models that rely on parameterized constructors, C# positional records, or recursive ConstructUsing expressions, AutoMapper evaluates child constructor arguments prior to incrementing the parent's recursion depth counter. This ordering flaw bypasses both explicit MaxDepth limits and the default depth limit of 64. An unauthenticated remote attacker can supply deeply nested input payloads to affected endpoints, exhausting the thread call stack and triggering an uncatchable System.StackOverflowException that terminates the hosting .NET process.

Amit Schendel
Amit Schendel
3 views•11 min read
•about 2 hours ago•CVE-2026-128080
5.8

CVE-2026-128080: Sensitive Query Parameter Disclosure on Incoming Server Spans in OpenTelemetry JavaScript (@opentelemetry/instrumentation-http)

An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.

Alon Barad
Alon Barad
3 views•10 min read
•about 3 hours ago•CVE-2026-128089
7.5

CVE-2026-128089: Uncontrolled Resource Consumption in dnspython WKS Record Parser

CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.

Amit Schendel
Amit Schendel
4 views•10 min read
•about 4 hours ago•CVE-2026-126347
3.1

CVE-2026-126347: Open Redirect via Triple-Slash Redirect Paths in Tornado RedirectHandler

CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.

Alon Barad
Alon Barad
4 views•11 min read
•about 5 hours ago•CVE-2026-128123
5.9

CVE-2026-128123: Uncaught Exception and Denial of Service in SvelteKit @sveltejs/adapter-node

A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.

Alon Barad
Alon Barad
4 views•9 min read