[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)
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
EALLOWSCRIPTSboth 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.js—policyFromSources(npm, ['cli', 'env'])groups theenvsource withcli; a non-global, non-skipProjectConfiginstall throwsEALLOWSCRIPTSwhen that layer has a policy.npm execexports resolved config (including user.npmrcvalues such asallow-scripts) to the child process asnpm_config_*. #9913 excludedallow-scriptsfrom lifecycle exports; the exec path's export still includes it.
Suggested fixes
- (Preferred) Apply the #9913 treatment to the
npm execchild environment: keep persistentallow-scriptspolicy out of exec-exported config, so nested npm commands reload it from its original config source instead of treating it as an environment override. - Alternatively, strip
npm_config_allow_scriptsfrom the child env innpm exec— it is a one-off/global-context flag by design, so there is no valid exec-child use for it. - 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-scriptlifecycle 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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