Alta

brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups

  • Publicada: 20.07.2026
  • Actualizado: 11.10.2026 10:22

Summary

brace-expansion's expand() exhibits exponential-time - O(2ⁿ) - behavior in the number of consecutive non-expanding {} groups. A short, all-ASCII input (~90 bytes/30 groups) blocks the calling thread for minutes; a slightly longer input hangs it effectively indefinitely. Because the dominant consumers run on Node's single-threaded event loop, one small input can fully stall a worker/process.

In expand_, post is computed unconditionally at the top of the function, before the early-return branches that don't use it:

js
const post = m.post.length ? expand_(m.post, max, false) : [''];   // always recurses
  ...
if (!isSequence && !isOptions) {
  if (m.post.match(/,(?!,).*\}/)) {
    str = m.pre + '{' + m.body + escClose + m.post;
    return expand_(str, max, true); // restart — `post` discarded
  }
  return [str];
}

For input like a{},{},…, the first {} is non-expanding, so control reaches the {a},b} rewrite branch - but expand_ has already recursed into post over the entire remaining tail, only to throw the result away. Each level therefore spawns two recursive expansions over essentially the same remaining work: T(n) = 2·T(n−1) ⇒ O(2ⁿ).

The max option does not mitigate this: max only bounds the output-building loops; neither the post recursion nor the rewrite recursion consults it.

Measured on 5.0.6:

groups (n) input bytes time
20 60 130 ms
24 72 1.9 s
26 78 7.8 s
30 (PoC) 90 ~2 min

Proof of concept

js
const { expand } = require('brace-expansion');
// 30 non-expanding groups, ~90 bytes — blocks for minutes:
expand('a{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}');

Impact

Any application that passes attacker-influenced strings to brace-expansion.expand() - directly or transitively via minimatch/glob brace patterns - can be driven into a multi-minute-to-indefinite CPU hang by a tiny request, denying service on that thread/process.

Remediation

Upgrade to a patched release. The fix:

  1. Defers computing post until after the early-return branches (and computes it locally in the $-suffix branch), so post is only expanded when a brace set actually expands and the value is used. This alone removes the exponential.
  2. Converts the {a},b} rewrite from recursion to an in-function loop, so a long run of rewrites cannot grow the call stack.

Verified: the PoC drops from ~2 min to 0.55 ms, 5,000 groups complete in ~344 ms, and output is identical to 5.0.6 across a behavioral-equivalence suite (sequences, padding, $-prefix, a{},b}c, {},a}b, x{{a,b}}y, etc.). Post-fix complexity is ~O(n²) on this input class - acceptable for the security fix; a linear rewrite can be a non-urgent follow-up.

If immediate upgrade isn't possible, avoid passing untrusted input to expand() / glob brace patterns, or run such expansion under a timeout/worker.

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm brace-expansion >= 3.0.0, < 5.0.7, < 1.1.16, >= 2.0.0, < 2.1.2 5.0.7, 1.1.16, 2.1.2

Referencias

Puntuación CVSS 5.3/10
Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Debilidad (CWE)
CWE-400, CWE-407
Plataforma
npm
Paquete
brace-expansion
Publicada
20.07.2026
Actualizado
11.10.2026 10:22

Fuentes y licencias

OSV / GitHub Advisory Database - GHSA-3jxr-9vmj-r5cp - CC BY 4.0

Historial de vulnerabilidades: brace-expansion

Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (10) en el archivo
Entradas en total
10
Primera → última
01.2018 09.2026
Sin corrección
0
Explotada en ataques
0

Distribución por gravedad

  • Alta 6
  • Media 3
  • Baja 1

Divulgaciones por año

  1. 2018: 1
  2. 2019: 0
  3. 2020: 0
  4. 2021: 0
  5. 2022: 0
  6. 2023: 0
  7. 2024: 0
  8. 2025: 1
  9. 2026: 8
Gravedad:
  1. Alta · 7.5 CVE-2026-102278 >= 4.0.0, < 5.0.11, >= 3.0.0, < 3.0.8, >= 2.0.0, < 2.1.6, < 1.1.20 5.0.11, 3.0.8, 2.1.6, 1.1.20
  2. Alta · 7.5 CVE-2026-102276 >= 4.0.0, < 5.0.10, >= 3.0.0, < 3.0.7, >= 2.0.0, < 2.1.5, < 1.1.19 5.0.10, 3.0.7, 2.1.5, 1.1.19
  3. Alta · 7.5 CVE-2026-69152 < 1.1.18, >= 2.0.0, < 2.1.4, >= 3.0.0, < 3.0.6, >= 4.0.0, < 5.0.9 1.1.18, 2.1.4, 3.0.6, 5.0.9
  4. Alta · 7.5 CVE-2026-14257 >= 4.0.0, < 5.0.8, >= 3.0.0, < 3.0.3, >= 2.0.0, < 2.1.3, < 1.1.17 5.0.8, 3.0.3, 2.1.3, 1.1.17
  5. brace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups esta entrada
    Alta · 5.3 CVE-2026-13149 >= 3.0.0, < 5.0.7, < 1.1.16, >= 2.0.0, < 2.1.2 5.0.7, 1.1.16, 2.1.2
  6. Alta · 7.5 CVE-2017-18077 < 1.1.7 1.1.7

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.