Skip to content

Correct brace-expansion ranges in GHSA-mh99-v99m-4gvg: fix was backported to 1.x, 2.x and 3.x - #8878

Open
TechPro01 wants to merge 1 commit into
github:TechPro01/advisory-improvement-8878from
TechPro01:techpro01-GHSA-mh99-v99m-4gvg
Open

Correct brace-expansion ranges in GHSA-mh99-v99m-4gvg: fix was backported to 1.x, 2.x and 3.x#8878
TechPro01 wants to merge 1 commit into
github:TechPro01/advisory-improvement-8878from
TechPro01:techpro01-GHSA-mh99-v99m-4gvg

Conversation

@TechPro01

Copy link
Copy Markdown

GHSA-mh99-v99m-4gvg / CVE-2026-14257 currently uses a single range for brace-expansion:

{ "introduced": "0" }, { "fixed": "5.0.8" }

Under npm/semver ordering that marks every version below 5.0.8 as vulnerable. But the fix was backported to the 1.x, 2.x and 3.x maintenance branches, so five already-patched releases are currently reported as vulnerable: 1.1.17, 2.1.3, 3.0.3, 3.0.4, 3.0.5.

The package carries maintenance-v1, maintenance-v2 and maintenance-v3 dist-tags, which is consistent with the backports.

Proposed ranges

{ "introduced": "0" },     { "fixed": "1.1.17" },
{ "introduced": "2.0.0" }, { "fixed": "2.1.3" },
{ "introduced": "3.0.0" }, { "fixed": "3.0.3" },
{ "introduced": "4.0.0" }, { "fixed": "5.0.8" }

Note the last pair is deliberate: 4.x has no patched release4.0.1 (2025-06-11) is the newest 4.x and is still vulnerable — so the range from 4.0.0 correctly continues to 5.0.8, i.e. a 4.x user's only fix is the 5.x major.

First patched version per branch

branch first patched published
1.x 1.1.17 2026-07-29
2.x 2.1.3 2026-07-28
3.x 3.0.3 2026-07-27
4.x (none) 4.0.1 is the last 4.x
5.x 5.0.8 2026-07-23

How this was determined

Behaviourally, per version, against the entry point npm actually resolves — not by grepping for a marker and not from advisory metadata. Each version was installed in an isolated project and exercised with an input whose unbounded expansion exceeds the new cap:

const { createRequire } = require('module');
const req = createRequire(require('path').join(process.cwd(), 'package.json'));
const m = req('brace-expansion');
const fn = typeof m === 'function' ? m : (m.expand || m.default);
const total = fn('a'.repeat(50000) + '{1..100}').reduce((s, x) => s + x.length, 0);
// unfixed -> 5,000,192 chars (100 items) | fixed -> 3,950,149 chars (79 items)

Results (all measured, not inferred):

version chars
1.0.0, 1.1.16 5,000,192 vulnerable
1.1.17 3,950,149 fixed
2.0.0, 2.1.2 5,000,192 vulnerable
2.1.3 3,950,149 fixed
3.0.0, 3.0.1, 3.0.2 5,000,192 vulnerable
3.0.3, 3.0.4, 3.0.5 3,950,149 fixed
4.0.0, 4.0.1 5,000,192 vulnerable
5.0.7 5,000,192 vulnerable
5.0.8 3,950,149 fixed

Cross-checking both ranges against those 16 measured versions with an OSV range evaluator: the current range mis-classifies 5 of 16; the proposed range mis-classifies 0 of 16.

Two notes for anyone verifying this themselves:

  • On the 1.x and 2.x lines, package.json is main: "index.js" with no exports. Some of those releases also ship a fixed build under dist/ that nothing resolves to, so the presence of a patched dist/ (or of an advisory file in the tarball) does not mean the installed entry point is fixed — 2.1.2 is exactly this case. Check the file require.resolve() returns.
  • The export shape changes across majors: 1.x/2.x export a function, 3.x/4.x use default, 5.x exports expand.

Not changed

database_specific.last_known_affected_version_range is left as <= 5.0.7. It's still defensible as an upper bound on the highest affected version, and I'd rather flag it than edit a field whose exact intended semantics I haven't confirmed — happy to update it if maintainers prefer.

One advisory, ranges only; no other fields touched.

…x and 3.x

The single range (introduced 0, fixed 5.0.8) reports 1.1.17, 2.1.3, 3.0.3,
3.0.4 and 3.0.5 as vulnerable, but all five carry the fix. Split into
per-branch ranges. 4.x has no patched release, so its range continues to
5.0.8.
@github-actions
github-actions Bot changed the base branch from main to TechPro01/advisory-improvement-8878 July 29, 2026 21:47
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.

1 participant