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.
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]