chore(deps): update dependency brace-expansion to v5.0.9 [security] #22
No reviewers
Labels
No labels
idea
points
1
points
13
points
2
points
3
points
5
points
8
priority
p0
priority
p1
priority
p2
priority
p3
state
blocked
state
done
state
in-progress
state
ready
state
review
state
triage
status
declined
status
in-progress
status
planned
status
proposed
status
shipped
status
under-review
type
bug
type
epic
type
feature
type
spike
type
story
type
task
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
tti/tti-ux!22
Loading…
Reference in a new issue
No description provided.
Delete branch "renovate/npm-brace-expansion-vulnerability"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR contains the following updates:
5.0.8→5.0.9brace-expansion: DoS via unbounded intermediate arrays, bypassing the CVE-2026-14257 mitigation
CVE-2026-69152 / GHSA-rgw5-rvv9-x895
More information
Details
Summary
The
maxLengthmitigation added in5.0.8for 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, sotry/catcharoundexpand()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
maxLengthwas enforced incombine(), the single place output grows. Two arrays are built beforecombine()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 recursiveexpand_()call, so each receives a full, independentmaxLengthallowance. The results were then concatenated into a singlevaluesarray with no cumulative limit:With
Aalternatives,valuescan reachA * maxLengthcharacters beforecombine()gets a chance to truncate it. At the defaultmaxLengthof 4,000,000 and 400 alternatives, that is well past any default heap.2. Padded sequences ignore
maxLengthwhile generating (CPU exhaustion)expandSequence()was bounded bymax(the result count) but never consultedmaxLength. A padded sequence's element width follows the input, so{0...01..100000}with a wide pad generatesmaxelements, each as wide as the input, only forcombine()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.Output is byte-identical before and after the fix; only the wasted work is removed.
Proof of concept
Memory exhaustion, against
5.0.8:Event-loop stall, against
5.0.8: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 withtry/catch.Applications already on
5.0.8are affected: the5.0.8mitigation does not cover these paths.Patches
Both intermediate arrays are now bounded as they are built, using the same
maxandmaxLengthlimits already applied incombine():valuestracks a running result count and character length while alternatives are appended, and stops once either bound is reached.expandSequence()acceptsmaxLengthand 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
maxalready 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 smallmaxandmaxLength.Note that a small
maxLengthalone 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.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.
⚠️ Artifact update problem
Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.
♻ Renovate will retry this branch, including artifacts, only when one of the following happens:
The artifact failure details are included below:
File name: package-lock.json
AI review · advisory
Verdict: 1 thing worth fixing (1 medium).
Findings that didn't map to a diff line:
package.json:108· MEDIUM — Lockfile out of sync after dependency version bumpThe override for "brace-expansion" is updated to 5.0.9, but the lockfile (package-lock.json) is not updated, risking inconsistent dependency resolution across environments.
⚑ panel: GPT-OSS 120B · Gemma 4 31B · Devstral 2 123B · Laguna S 2.1 — 1 distinct, 1 confirmed, 0 refuted · web: not used · context: 1 files · 90 codebase · 14 standards chunks (best-grounded: GPT-OSS 120B; smaller windows saw less)
Panel debate — how this review was reached
Grounding — context: 1 files · 90 codebase · 14 standards chunks (best-grounded: GPT-OSS 120B; smaller windows saw less)
Round 1 — independent reviews
brace-expansionwithin the package overrides, which is correct and consistent with agency security standards.Round 2 — cross-examination
GPT-OSS 120B#1Lockfile out of sync after dependency version bump · confirmed: Laguna S 2.1 · refuted: Gemma 4 31B, Devstral 2 123BSynthesis — Devstral 2 123B wrote the final review from 1 confirmed finding.
Transcript
rv-20260806165959-096542— full round outputs, web results, and model reasoning are viewable by anyone with access to this repository via the AI gateway.Advisory — never a merge gate. Disagree with a finding? Reply on it, or use the finding board under this review. Transcript
rv-20260806165959-096542.Superseded by #29. This PR was a pre-2026-08-06 Renovate artifact: it bumped package.json but could not rewrite the lockfile (the github.com toolchain artifactError fixed by our own Renovate image, forgejo-stack PR #36) — merging it as-is would have desynced the lockfile.
Pull request closed