Skip to content

chore(deps): update dependency brace-expansion@<1.1.13 to v1.1.16 [security] - #6385

Merged
renovate[bot] merged 1 commit into
mainfrom
renovate/npm-brace-expansion-1.1.13-vulnerability
Jul 27, 2026
Merged

chore(deps): update dependency brace-expansion@<1.1.13 to v1.1.16 [security]#6385
renovate[bot] merged 1 commit into
mainfrom
renovate/npm-brace-expansion-1.1.13-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
brace-expansion@<1.1.13 1.1.131.1.16 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


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

CVE-2026-13149 / GHSA-3jxr-9vmj-r5cp

More information

Details

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:

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
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.

Severity

  • CVSS Score: 7.7 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:P/S:N/AU:Y/R:U/V:D/RE:M/U:Amber

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

juliangruber/brace-expansion (brace-expansion@<1.1.13)

v1.1.16

Compare Source

v1.1.15

Compare Source


v1.1.14

Compare Source


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@alwaysmeticulous

alwaysmeticulous Bot commented Jul 26, 2026

Copy link
Copy Markdown

✅ Meticulous spotted 0 visual differences across 289 screens tested: view results.

Meticulous evaluated ~4 hours of user flows against your PR.

Expected differences? Click here. Last updated for commit 763b568 chore(deps): update dependency brace-expansion@<1.1.13 to v1.1.16 [secur.... This comment will update as new commits are pushed.

@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from 5410568 to 62281ab Compare July 26, 2026 05:14
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from 62281ab to c217e5c Compare July 26, 2026 08:41
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from c217e5c to 31f8e0e Compare July 26, 2026 12:45
@renovate renovate Bot changed the title chore(deps): update dependency brace-expansion@<1.1.13 to v5 [security] chore(deps): update dependency brace-expansion@<1.1.13 to v2 [security] Jul 26, 2026
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from 31f8e0e to c3fa901 Compare July 26, 2026 18:20
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from c3fa901 to b91464d Compare July 26, 2026 20:41
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from b91464d to 475e568 Compare July 27, 2026 00:44
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from 475e568 to c2db7f1 Compare July 27, 2026 04:46
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from c2db7f1 to 78350be Compare July 27, 2026 10:19
@renovate
renovate Bot force-pushed the renovate/npm-brace-expansion-1.1.13-vulnerability branch from 78350be to 763b568 Compare July 27, 2026 13:08
@renovate
renovate Bot enabled auto-merge (squash) July 27, 2026 13:08
@renovate renovate Bot changed the title chore(deps): update dependency brace-expansion@<1.1.13 to v2 [security] chore(deps): update dependency brace-expansion@<1.1.13 to v1.1.16 [security] Jul 27, 2026
@renovate
renovate Bot merged commit 5f28d35 into main Jul 27, 2026
36 checks passed
@renovate
renovate Bot deleted the renovate/npm-brace-expansion-1.1.13-vulnerability branch July 27, 2026 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants