Skip to content

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

Description

@manzoorwanijk

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

This is not just a request to bump a dependency for a CVE

  • This is not solely a request to bump a dependency for a CVE

Current Behavior

With strict-allow-scripts=true and a name-only deny entry such as "allowScripts": { "esbuild": false }, npm install aborts with ESTRICTALLOWSCRIPTS, claiming a package has an install script "not covered by allowScripts" — even though that package is explicitly denied by name and is extraneous (no incoming edges, slated for pruning, its install script will never run). The extraneous node exists only as a nested package-lock.json entry, not on disk.

npm error code ESTRICTALLOWSCRIPTS
npm error --strict-allow-scripts: 1 package(s) have install scripts not covered by allowScripts:
npm error   esbuild@0.25.12 (install: (install scripts present))

This reproduces under the default (hoisted) install strategy. The precondition is a registry node nested under a workspace's node_modules that nothing depends on: buildIdealTree prunes such an orphan when it is top-level, but retains it when it is nested inside a workspace, so the strict preflight sees it.

The strict gate and the advisory listing disagree on the identical node: npm install-scripts ls reports the tree as fully covered ("No packages with unreviewed install scripts" — it walks the loaded actual tree), while the strict preflight (which walks buildIdealTree) surfaces the orphan as unreviewed.

The bug was first observed with two esbuild nodes in a workspace monorepo, where one copy is depended on and another is an orphan leftover:

node edgesIn isRegistryDependency extraneous isScriptAllowed verdict
esbuild@0.27.2 (depended on) 10 true false false (deny matches — OK)
esbuild@0.25.12 (orphan, nested under a workspace) 0 false true null (unreviewed → error)

The orphan's lockfile entry has a valid registry tarball URL (https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz) and "extraneous": true.

Expected Behavior

A package that is explicitly denied by a name-only allowScripts entry, or that is extraneous and will be pruned before any script runs, must not gate the install under strict-allow-scripts. The strict gate and npm install-scripts ls should agree on the same node.

Steps To Reproduce

Self-contained CLI reproduction. core-js stands in for esbuild (zero dependencies, declares a postinstall). The nested orphan lockfile entry is injected to model the stale entry that real workspace installs can leave behind; the bug is that npm install then false-positives on it.

mkdir -p /tmp/sas-repro/packages/app && cd /tmp/sas-repro

# 1. a workspace project on the default (hoisted) install strategy
cat > package.json <<'JSON'
{ "name": "root", "version": "1.0.0", "private": true, "workspaces": ["packages/app"] }
JSON
cat > packages/app/package.json <<'JSON'
{ "name": "app", "version": "1.0.0", "dependencies": { "left-pad": "1.3.0" } }
JSON
npm install --ignore-scripts --no-audit --no-fund

# 2. inject an orphan registry node nested under the workspace (nothing depends on it)
npm install core-js@3.38.0 --ignore-scripts --no-audit --no-fund --prefix ./.tmp
node -e '
const fs = require("fs");
const cj = JSON.parse(fs.readFileSync(".tmp/package-lock.json")).packages["node_modules/core-js"];
const l = JSON.parse(fs.readFileSync("package-lock.json"));
l.packages["packages/app/node_modules/left-pad/node_modules/core-js"] = cj;
fs.writeFileSync("package-lock.json", JSON.stringify(l, null, 2));
'
rm -rf .tmp node_modules

# 3. deny core-js install scripts + enable the strict gate
cat > package.json <<'JSON'
{ "name": "root", "version": "1.0.0", "private": true, "workspaces": ["packages/app"], "allowScripts": { "core-js": false } }
JSON
echo 'strict-allow-scripts=true' > .npmrc

# 4. install fails, even though core-js is denied and is an extraneous orphan
npm install --no-audit --no-fund

Observed:

npm error code ESTRICTALLOWSCRIPTS
npm error --strict-allow-scripts: 1 package(s) have install scripts not covered by allowScripts:
npm error   core-js@3.38.0 (install: (install scripts present))

while the advisory listing reports the same tree as clean:

$ npm install-scripts ls
No packages with unreviewed install scripts.

For contrast, when the same core-js is reached through a real dependency edge (so isRegistryDependency=true), the name-only deny matches and npm install succeeds under the strict gate.

Environment

  • npm: 12.0.0-pre.1 (latest branch), happens in v11 as well
  • Node.js: v24.17.0
  • OS Name: macOS (Darwin 25.5.0)
  • System Model Name: Mac17,6
  • install strategy: default (hoisted); a workspace is required to retain the orphan

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugthing that needs fixingNeeds Triageneeds review for next steps

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions