← All tasks
javascriptgoogleapis/google-cloud-node #8969Not a task: already works

google-gax: rimraf appears build-only but is published as a production dependency (pulls vulnerable brace-expansion chain)

envgap__googleapis__google-cloud-node-8969

01 / FAILURE SIGNATURE

As reported upstream

`TypeError: ... is not a function`. (`minimatch@10` bumped its major precisely
Not a benchmark task.
  • The project already builds and runs before the fix, so there is nothing to repair.

02 / ENVIRONMENT RECIPE

Base commit
dbffbc9b00e8edff6ab78cd01134d42d33efddf3
Manifest
core/packages/gax/package.json
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / ORIGINAL ISSUE TEXT

googleapis/google-cloud-node #8969 · read the original issue
### Summary

`google-gax` declares `rimraf` under `dependencies`, but `rimraf` does not appear
to be used by any shipped runtime code. Because `rimraf@5` transitively depends
on `glob@10 → minimatch@9 → brace-expansion@2`, every consumer of `google-gax`
currently inherits [GHSA-mh99-v99m-4gvg][adv] (`brace-expansion`, DoS via
unbounded expansion) in their **production** dependency tree.

If the declaration is indeed build-only or vestigial, moving it to
`devDependencies` (or removing it) would clear the advisory for all downstream
consumers without any code change.

[adv]: https://github.com/advisories/GHSA-mh99-v99m-4gvg

### Version

`google-gax@5.0.8` (current latest at time of writing).

### Dependency path

```text
@google-cloud/firestore@8.7.0
└─ google-gax@5.0.8
   └─ rimraf@5.0.10
      └─ glob@10.5.0
         └─ minimatch@9.0.9
            └─ brace-expansion@2.1.2   ← GHSA-mh99-v99m-4gvg
```

The same tail is reachable via `@google-cloud/pubsub` and `@google-cloud/tasks`,
which also depend on `google-gax`.

### Evidence that `rimraf` is not used at runtime

Against the published tarball / installed package for `google-gax@5.0.8`:

```console
$ npm view google-gax@5.0.8 dependencies.rimraf
^5.0.1

$ npm view google-gax@5.0.8 devDependencies.rimraf
                       # (empty — it is a production dependency)

$ npm view google-gax@5.0.8 scripts --json | grep -i rimraf
                       # (no matches — no script references rimraf either)

$ grep -rE "require\(.rimraf.\)|from .rimraf." node_modules/google-gax/build/
                       # (no matches across 47 .js files)
```

So the package neither imports `rimraf` in its shipped output nor invokes it
from a lifecycle/utility script.

### Why consumers cannot easily work around this

The obvious downstream mitigation — overriding `brace-expansion` to the patched
`5.0.8` — **breaks `google-gax` at runtime**. `minimatch@9.0.9` compiles to:

```js
const brace_expansion_1 = __importDefault(require("brace-expansion"));
return (0, brace_expansion_1.default)(pattern);
```

`brace-expansion@5.0.8`'s CommonJS build sets `__esModule: true` and exports only
a named `expand`, so `__importDefault` does not wrap it and
`brace_expansion_1.default` is `undefined`. Every brace-pattern match then throws
`TypeError: ... is not a function`. (`minimatch@10` bumped its major precisely
for this export-shape change.) Note that `brace-expansion`'s advisory range is
`<=5.0.7`, i.e. every 1.x/2.x/4.x backport is affected — `5.0.8` is the only
patched release, and `minimatch@9` cannot consume it.

Consumers are therefore left with a scoped override such as:

```jsonc
"overrides": {
  "google-gax": { "rimraf": "^6.1.3" }
}
```

which is safe only because nothing in `google-gax` actually calls `rimraf` — but
it is a workaround that every downstream project has to discover and justify
independently.

### Requested outcome

Whichever is correct for the package:

1. Move `rimraf` to `devDependencies` (or drop it) if it is build-only/unused; or
2. If it genuinely is required at runtime, bump the declared range to `rimraf@^6`,
   which resolves `glob@13 → minimatch@10 → brace-expansion@^5`.

### Related

- #8868 — `gcp-metadata` pins `gaxios` to an exact version; `gaxios@7.1.3`
  carries the same `rimraf: ^5.0.1` declaration (also unused in its shipped
  `build/`), reaching the tree through `google-auth-library → gcp-metadata`.
  `gaxios@7.3.0` dropped `rimraf` outright.

### Environment

- Node.js 22
- npm 10
- Reproducible from a clean install of `@google-cloud/firestore@8.7.0` alone.
Continue on GitHub ↗

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]