Skip to content

fix(arborist): skip extraneous orphans in strict-allow-scripts gate#9683

Open
Sanjays2402 wants to merge 1 commit into
npm:latestfrom
Sanjays2402:fix/issue-9680
Open

fix(arborist): skip extraneous orphans in strict-allow-scripts gate#9683
Sanjays2402 wants to merge 1 commit into
npm:latestfrom
Sanjays2402:fix/issue-9680

Conversation

@Sanjays2402

Copy link
Copy Markdown

Description

strict-allow-scripts aborts npm install with ESTRICTALLOWSCRIPTS on an extraneous (edgeless) registry node that lives only as a nested package-lock.json entry inside a workspace's node_modules. The reporter's table makes the asymmetry obvious: a real esbuild copy with 10 incoming edges is correctly denied by name, while the orphan esbuild copy (0 incoming edges, extraneous: true) trips the preflight as unreviewed. npm install-scripts ls, which walks the actual on-disk tree, reports the same project as fully covered — so the strict gate and the advisory listing disagree on the same node.

An extraneous node has no incoming dependency edge and is slated for pruning before reify runs any install script:

  • buildIdealTree drops extraneous nodes from the ideal tree (#idealTreePrune clears parent).
  • rebuild schedules install scripts only for nodes from loadActual() (the on-disk tree), and an extraneous orphan that exists only in the lockfile is not on disk.

In the workspace case the reporter hit, the orphan can survive the ideal-tree prune (top-level orphans are dropped, nested-in-workspace orphans are retained), but it still never executes a script because it is not present in the actual tree. The strict-allow-scripts gate therefore must not surface it.

The fix is a one-arm continue in collectUnreviewedScripts, alongside the existing inBundle and inert skips that protect the same property ("this node's install script is never going to run"). With that, the strict preflight and npm install-scripts ls agree on the same tree.

The repro from the issue (core-js standing in for esbuild) now installs cleanly under strict-allow-scripts=true + { "allowScripts": { "core-js": false } }. The matcher logic in script-allowed.js is unchanged — the orphan still has no resolved registry URL the matcher can verify, so the right place to short-circuit is the upstream filter, not the matcher.

Existing Issue

Fixes #9680

Screenshots / Test Coverage

Two regression tests added to workspaces/arborist/test/unreviewed-scripts.js:

  • skips extraneous (orphan) registry nodes — basic case, no policy.
  • skips extraneous nodes even when policy denies by name — covers the reporter's scenario where the orphan has no resolved URL the registry matcher can verify, so the deny falls through and the node would otherwise be reported as unreviewed.

Both fail on latest and pass with the fix:

$ tap --no-coverage workspaces/arborist/test/unreviewed-scripts.js
ok 1 - test/unreviewed-scripts.js   # 12/12 ok, was 10/12 before the fix

Adjacent suites stay green:

$ tap --no-coverage workspaces/arborist/test/script-allowed.js \
                    workspaces/arborist/test/install-scripts.js \
                    test/lib/utils/strict-allow-scripts-preflight.js \
                    workspaces/libnpmexec/test/strict-allow-scripts-preflight.js

AI disclosure

This change was written with the assistance of Claude (drafting the diff, the regression test, and this PR description). I reviewed the diff and the test and take responsibility for the code.

An extraneous registry node has no incoming dependency edge and is slated
for pruning before reify can run any install script. buildIdealTree
drops top-level orphans, but it can retain an orphan nested inside a
workspace, in which case the strict-allow-scripts preflight false-
positives on it (ESTRICTALLOWSCRIPTS) even though the install script
will never execute. Skip extraneous nodes in collectUnreviewedScripts so
the strict gate and the on-disk npm install-scripts ls listing agree.

Fixes npm#9680
@Sanjays2402 Sanjays2402 requested review from a team as code owners June 28, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] strict-allow-scripts false-positives on extraneous (edgeless) registry nodes

1 participant