Skip to content

fix(arborist): don't load store packages' devDependencies as required edges#9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijk manzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes #9610
Part of #9608

@manzoorwanijk manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk manzoorwanijk requested review from a team as code owners June 24, 2026 08:44
@manzoorwanijk manzoorwanijk force-pushed the fix/linked-sbom-store-devdeps branch from f110560 to e38faa0 Compare June 24, 2026 14:35
@owlstronaut owlstronaut merged commit 851558c into npm:latest Jun 24, 2026
24 checks passed
@manzoorwanijk manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@owlstronaut

Copy link
Copy Markdown
Contributor

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
Contributor Author

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
Contributor Author

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)

Backport of #9626 to `release/v11`.

Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.

Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.

## References

Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.

`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.

Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.

This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.

## References

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants