Skip to content

High security vulnerability from brace-expansion dependency when installing @percy/cli #2354

Open

Description

@euanblack

The problem

A high severity vulnerability has been introduced with the brace-expansion package that is a dependency for percy-cli:

GHSA-mh99-v99m-4gvg

npm audit fix + npm audit fix --force can't circumvent this.

When pinning the patched version in package overrides, Percy crashes when attempting to start.

added 159 packages in 8s

22 packages are looking for funding
  run `npm fund` for details
PS C:\Users\EuanBlack\source\repos\npm test repo> npm audit
npm audit report

brace-expansion  <=5.0.7
Severity: high
brace-expansion: DoS via unbounded expansion length causing an out-of-memory process crash - https://github.com/advisories/GHSA-mh99-v99m-4gvg
fix available via `npm audit fix --force`
Will install @percy/cli@1.31.9, which is a breaking change
node_modules/brace-expansion
node_modules/glob/node_modules/brace-expansion
  minimatch  2.0.0 - 10.0.2
  Depends on vulnerable versions of brace-expansion
  node_modules/glob/node_modules/minimatch
  node_modules/minimatch
    @percy/cli-doctor  *
    Depends on vulnerable versions of @percy/cli-command
    Depends on vulnerable versions of @percy/core
    Depends on vulnerable versions of minimatch
    node_modules/@percy/cli-doctor
      @percy/cli  1.31.10-alpha.0 - 1.32.5-beta.1
      Depends on vulnerable versions of @percy/cli-app
      Depends on vulnerable versions of @percy/cli-build
      Depends on vulnerable versions of @percy/cli-command
      Depends on vulnerable versions of @percy/cli-config
      Depends on vulnerable versions of @percy/cli-doctor
      Depends on vulnerable versions of @percy/cli-exec
      Depends on vulnerable versions of @percy/cli-snapshot
      Depends on vulnerable versions of @percy/cli-upload
      node_modules/@percy/cli
      @percy/core  *
      Depends on vulnerable versions of @percy/cli-doctor
      Depends on vulnerable versions of fast-xml-parser
      Depends on vulnerable versions of rimraf
      node_modules/@percy/core
        @percy/cli-command  1.31.15-alpha.0 - 1.32.5-beta.1
        Depends on vulnerable versions of @percy/core
        node_modules/@percy/cli-command
          @percy/cli-app  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          Depends on vulnerable versions of @percy/cli-exec
          node_modules/@percy/cli-app
          @percy/cli-build  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          node_modules/@percy/cli-build
          @percy/cli-config  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          node_modules/@percy/cli-config
          @percy/cli-exec  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          node_modules/@percy/cli-exec
          @percy/cli-snapshot  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          node_modules/@percy/cli-snapshot
          @percy/cli-upload  1.31.15-alpha.0 - 1.32.5-beta.1
          Depends on vulnerable versions of @percy/cli-command
          node_modules/@percy/cli-upload
    glob  4.3.0 - 10.5.0
    Depends on vulnerable versions of minimatch
    node_modules/glob
      rimraf  2.3.0 - 3.0.2 || 4.2.0 - 5.0.10
      Depends on vulnerable versions of glob
      node_modules/rimraf

fast-xml-parser  <5.7.0
Severity: moderate
fast-xml-parser XMLBuilder: XML Comment and CDATA Injection via Unescaped Delimiters - https://github.com/advisories/GHSA-gh4j-gqv2-49f6
fix available via `npm audit fix --force`
Will install @percy/cli@1.31.9, which is a breaking change
node_modules/fast-xml-parser

15 vulnerabilities (8 moderate, 7 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force`

Environment

  • Node version: node: '20.17.0',
  • @percy/cli version: 1.32.4
  • Version of Percy SDK you’re using:
  • If needed, a build or snapshot ID:
  • OS version:
  • Type of shell command-line [interface]: powershell

Steps to reproduce

  1. Create new repo
  2. Run npm install @percy/cli
  3. Run npm audit - observe stated vulnerabilities
  4. Run npm audit fix - note vulnerability still present
  5. Pin v5.0.8 of brace-expansion in package.json overrides
  6. Run percy exec start - note error

Activity

  1. prklm10 commented on Jul 27, 2026

    @prklm10
    Contributor

    Thanks @euanblack for raising this. We will evaluate and get back to you on this.

  2. rishigupta1599 commented on Aug 5, 2026

    @rishigupta1599
    Contributor

    Hi @euanblack — thanks for the detailed report, and sorry for the delay. We dug into this and can unblock you on both findings today, on your current @percy/cli version. We also found the specific reason your brace-expansion pin crashed Percy.

    1. brace-expansion (high) — GHSA-mh99-v99m-4gvg / CVE-2026-14257

    Use the maintenance releases of each major line rather than 5.0.8:

    // package.json (npm)
    "overrides": {
      "brace-expansion@1": "1.1.17",
      "brace-expansion@2": "2.1.3"
    }
    // package.json (yarn 1.x)
    "resolutions": {
      "brace-expansion@1": "1.1.17",
      "brace-expansion@2": "2.1.3"
    }

    Then reinstall clean (rm -rf node_modules package-lock.json && npm install) and run percy exec -- <your command> once to confirm startup.

    These versions do contain the fix. Both add an EXPANSION_MAX_LENGTH bound (4,000,000 characters) on top of the existing 100,000-result cap, and their source cites CVE-2026-14257 — this advisory — by name. That closes the unbounded-expansion OOM.

    Why they don't crash Percy, unlike 5.0.8. 1.1.17 and 2.1.3 are still CommonJS, still export a bare callable (module.exports = expandTop), and set no engines constraint — so they drop straight into both consumers in the tree (minimatch@3 via glob@7, and minimatch@9).

    5.0.8 is a rewrite: it's ESM-first, its CommonJS build exports a named expand (exports.expand = expand), and it requires Node 20 || >=22. The older minimatch@3 does var expand = require('brace-expansion') and then calls it directly, so under your override it received an object where it expected a function — that's the TypeError: expand is not a function behind the percy exec start crash. Nothing you did wrong; there simply is no 5.x that stays API-compatible with the older consumers.

    One caveat: npm audit will still flag this

    The advisory records a single vulnerable range, <= 5.0.7, and hasn't been split per major line — so 1.1.17 and 2.1.3 still fall inside the recorded range even though they carry the patch. The vulnerability is genuinely closed by those versions; the database entry just doesn't reflect the backports yet.

    If you need a green gate in CI, we'd suggest allowlisting this one advisory rather than lowering your severity threshold, so the suppression stays visible and scoped:

    npx audit-ci --moderate --allowlist GHSA-mh99-v99m-4gvg

    (audit-ci accepts a GHSA identifier as an advisory allowlist record, or an allowlist array in audit-ci.jsonc. Plain npm audit has no per-advisory ignore — --audit-level filters by severity only, so it can't hide this one without also hiding genuine highs.)

    For context on the residual risk while it's allowlisted: the issue is a denial-of-service that requires an attacker-controlled brace/glob pattern. Percy CLI globs your own project files rather than untrusted input, so practical exposure in this context is low.

    2. fast-xml-parser (moderate) — GHSA-gh4j-gqv2-49f6

    You're on Node 20.17.0, so you can take the 5.x line in your own project:

    // npm
    "overrides": { "fast-xml-parser": "5.10.1" }
    // yarn 1.x
    "resolutions": { "fast-xml-parser": "5.10.1" }

    Pin 5.10.1 specifically — 5.9.3 through 5.10.0 carry a separate high-severity advisory (GHSA-8r6m-32jq-jx6q). We checked 5.10.1 and all six of its transitive dependencies: no outstanding advisories.

    This is safe for how Percy uses the library: we only parse XML (XMLParser) and never use XMLBuilder, which is the component this advisory affects. We compared v4 and v5 output across our parser fixtures and saw no differences. Note 5.x needs Node ≥16, which your Node 20 satisfies — that's also why we can't simply ship it ourselves yet (see below).

    What we're doing on our side

    • A fix that removes these chains entirely is in review (#2356): it drops rimraf@3 from @percy/core and minimatch@9 from @percy/cli-doctor, so brace-expansion, glob, minimatch, inflight, and rimraf no longer appear in what you install. Once that ships you won't need the brace-expansion overrides at all.
    • We're planning to raise our minimum supported Node version to 20. We're reviewing usage data for customers still on older Node versions before we commit to it, so we don't break anyone mid-flight — that review is what gates the timing. Raising the floor is what lets us adopt fast-xml-parser 5.x directly and drop the second override too. Today our packages declare engines: >=14, and 5.x pulls a transitive dependency requiring Node ≥16, so publishing it now would break installs for users on older Node.

    One thing to avoid

    Please don't run npm audit fix --force here — it "resolves" this by downgrading to @percy/cli@1.31.9, which is a breaking downgrade from your 1.32.4.

    Happy to help if either override behaves unexpectedly in your setup — just let us know.

  3. github-actions commented on Sep 29, 2026

    @github-actions
    Contributor

    This issue is stale because it has been open for more than 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    🍞 staleClosed due to inactivity🔒 securityPRs or issues related to security

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions