SIGN IN SIGN UP

fix(arborist): audit the non-isolated tree under the linked strategy (#9625)

In continuation of our exploration of using `install-strategy=linked` in
the [Gutenberg
monorepo](https://github.com/WordPress/gutenberg/pull/75814), which

Under `install-strategy=linked`, `npm install --audit` reported `found 0
vulnerabilities` even with a known-vulnerable package installed, while
standalone `npm audit` reported it correctly. Only the install-time
audit was affected.

## Why

A linked reify swaps `idealTree` for the isolated tree
(`createIsolatedTree()`) before the quick audit runs, so
`_submitQuickAudit()` audited the isolated tree. That tree cannot be
audited: its inventory had a stub `query()` that always returned `[]`,
and its edges route through symlink `Link`s instead of real package
nodes. So `AuditReport.prepareBulkData()` produced an empty bulk request
and the registry was never asked about any installed version. Standalone
`npm audit` was unaffected because it audits the regular tree loaded
from the lockfile.

## How

`reify.js` stashes the original non-isolated ideal tree in
`#linkedIdealForAudit` during the linked swap, and `_submitQuickAudit()`
now audits `this.#linkedIdealForAudit || this.idealTree` — the same tree
standalone `npm audit` uses, with a queryable inventory and real package
nodes. The `_diffTrees()`/`#reifyPackages()`/orphan-sweep block is
wrapped in `try/finally` that restores `idealTree` and clears the
stashed references even if reify throws, so a reused Arborist never
audits or diffs a stale isolated tree. `isolated-classes.js` drops the
now-unused `IsolatedInventory` class (its only caller was the rerouted
audit path) in favor of a plain `Map`; the `query()` stub returning `[]`
was the silent-empty behavior behind this bug.

## References

Fixes #9609
Part of #9608
M
Manzoor Wani committed
989f571fe9064d170f2a4d7c4b1ed238be3851a9
Parent: 971500f
Committed by GitHub <noreply@github.com> on 6/24/2026, 2:22:03 PM