npm / npm/cli

[BUG] npm exec / npx forwards persistent user-level allow-scripts to children as npm_config_allow_scripts, failing project-scoped installs in the child (EALLOWSCRIPTS)

Open
#9,968 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
10.1k
Forks
4.7k
Avg merge
2d 2h
Merged PRs (30d)
19

Description

Summary

Setting allow-scripts in a user .npmrc (which npm's own warning recommends for global installs, and which is a valid config source for project installs) makes any tool launched via npx/npm exec that shells out to a project-scoped npm install fail with:

npm error code EALLOWSCRIPTS
npm error --allow-scripts is not allowed in project-scoped installs. Add the entries to the "allowScripts" field in package.json, or to .npmrc, instead.

npm exec exports the resolved npm config into the child process's environment as npm_config_* variables. Because the outer process read allow-scripts from a user .npmrc, the launched tool (and anything it spawns) inherits npm_config_allow_scripts, and when it reaches an inner project-scoped npm install, that inner npm resolves the value via its env source — which resolveAllowScripts groups with cli and rejects for non-global installs. The user never passed --allow-scripts; the value lives exactly where the error message tells them to put it.

This is the npm exec sibling of #9783 (git-dependency preparation) and #9912/#9913 (npm run-script lifecycle export). The #9913 fix keeps persistent allow-scripts out of lifecycle-exported config; the npm exec child env export still forwards it (verified on 12.0.2 below).

Environment

  • npm: 11.17.0 (full repro) and 12.0.2 (exec forwarding and EALLOWSCRIPTS both independently verified)
  • node: v24.19.0
  • OS: Windows 11 (Git Bash); the config/export mechanics are platform-independent

How the offending setting gets there

Same as #9783 / #9912 — the documented workflow. Installing a global package with an install script prints:

npm warn allow-scripts <pkg>@x.y.z (postinstall: node install.js)
npm warn allow-scripts Run `npm install -g --allow-scripts=<pkg>` to allow these scripts once, or `npm config set allow-scripts=<pkg> --location=user` to allow them for all global installs.

Following the second suggestion writes allow-scripts=<pkg> to the user .npmrc. From then on, every npx-launched tool that performs project-scoped npm installs fails.

Minimal, self-contained reproduction

Isolated --userconfig so the reporter's own .npmrc is not involved:

R=$(mktemp -d)
echo "allow-scripts=whatever" > "$R/userrc"   # exactly as `npm config set allow-scripts=... --location=user` writes it
mkdir "$R/app" && cd "$R/app"
echo '{"name":"app","private":true}' > package.json

# (A) Direct project-scoped install with the same user config — works
npm install is-even --userconfig "$R/userrc"

# (B) Same install reached through npx — fails
npx -y --userconfig "$R/userrc" -c 'npm install is-even'
Actual result (B)
npm error code EALLOWSCRIPTS
npm error --allow-scripts is not allowed in project-scoped installs. Add the entries to the "allowScripts" field in package.json, or to .npmrc, instead.
Export proof
npx -y --userconfig "$R/userrc" -c 'node -e "console.log(process.env.npm_config_allow_scripts)"'
# → whatever

On npm 12.0.2: npm exec still sets npm_config_allow_scripts in the child environment, and an inner install with that variable present fails with the same EALLOWSCRIPTS error.

Real-world impact

npx @robzolkos/lazypi — a community installer for the Pi coding agent that shells out to pi install, which runs npm install <pkg> --prefix <pi-dir> --legacy-peer-deps for each package — fails on all 23 npm-backed packages at once with this error on any machine whose user .npmrc carries the recommended allow-scripts entry. The same applies to any scaffolder/bootstrap tool driven via npx that runs nested project-scoped npm installs. Notably, running the identical installer from a global install (plain Node child, no npm exec env) works fine, which makes this particularly confusing to debug.

Expected result

The npx-launched tool's inner install completes. A persistent user-level allow-scripts policy is not a command-line flag; npm exec should not convert it into one by exporting it into the child environment.

Root cause (source pointers)

  • lib/utils/resolve-allow-scripts.jspolicyFromSources(npm, ['cli', 'env']) groups the env source with cli; a non-global, non-skipProjectConfig install throws EALLOWSCRIPTS when that layer has a policy.
  • npm exec exports resolved config (including user .npmrc values such as allow-scripts) to the child process as npm_config_*. #9913 excluded allow-scripts from lifecycle exports; the exec path's export still includes it.

Suggested fixes

  1. (Preferred) Apply the #9913 treatment to the npm exec child environment: keep persistent allow-scripts policy out of exec-exported config, so nested npm commands reload it from its original config source instead of treating it as an environment override.
  2. Alternatively, strip npm_config_allow_scripts from the child env in npm exec — it is a one-off/global-context flag by design, so there is no valid exec-child use for it.
  3. At minimum, fix the error message for the env-inherited case: telling the user to "add the entries to .npmrc" sends them in a circle — the entry already is in .npmrc.

Related

  • #9783 — same misclassification, reached via git-dependency preparation's inner install (open)
  • #9912 / #9913 — same via npm run-script lifecycle export; fixed for lifecycle exports only
  • RFC npm/rfcs#868

Workaround

Tools/launchers: don't reach the tool through npm exec (a globally installed copy runs with a clean environment and works). End users: keep allow-scripts out of persistent user config and pass it per-invocation for global installs only (npm install -g <pkg> --allow-scripts=<pkg>), or move the policy into each project's own package.json allowScripts field.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the npm exec child-environment export and lib/utils/resolve-allow-scripts.js, then run the self-contained reproduction with --userconfig to confirm the forwarding and EALLOWSCRIPTS failure. Done means a persistent user-level allow-scripts setting is not exported as an environment override to exec children, while the nested project-scoped install completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.