npm / npm/cli

[BUG] script-shell is resolved against cwd not workspace root or relative to .npmrc

Open
#9,970 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

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
script-shell=./local-cli-wrapper.sh

works as intended when npm run scriptname is executed in the workspace root dir, but fails in workspaces and lifecycle scripts

Expected Behavior

script-shell relative path should be resolved against either the location of .npmrc or workspace root.

The two should be equivalent when considered locally to the project, but npm also supports ~/.npmrc in which case a decision is needed whether it should look for the relative path to a shell wrapper relative to the workspace or the specific .npmrc that specifies the configuration.

Both are reasonable behaviors

Steps To Reproduce

setup

cd /tmp
mkdir a
cd a
npm init -y
printf '#!/bin/sh\necho "CALLED: $@"\n' > script-wrapper
chmod +x script-wrapper
echo "script-shell=./script-wrapper" > .npmrc

## regular nested folder
mkdir nested

## workspace setup
npm pkg set workspaces[]="packages/*"
mkdir -p packages/a
echo '{"name":"a", "scripts":{"test":"echo testing"}}' > packages/a/package.json

baseline works:

$ npm test

> a@1.0.0 test
> echo "Error: no test specified" && exit 1

CALLED: -c echo "Error: no test specified" && exit 1

$ cd nested
$ npm test

> a@1.0.0 test
> echo "Error: no test specified" && exit 1

CALLED: -c echo "Error: no test specified" && exit 1

Inside a workspace:

$ cd /tmp/a/packages/a
$ npm test
npm notice run test
npm notice run echo testing
npm error Lifecycle script `test` failed with error:
npm error code ENOENT
npm error syscall spawn ./script-wrapper
npm error path /tmp/a/packages/a
npm error errno -2
npm error workspace a
npm error location /tmp/a/packages/a
npm error enoent spawn ./script-wrapper ENOENT
npm error enoent This is related to npm not being able to find a file.
npm error enoent

likewise, lifecycle scripts:

setup:

npm i -D bcrypt
npm install-scripts approve bcrypt
rm -rf node_modules
$ npm ci --foreground-scripts
npm notice run bcrypt@6.0.0 install
npm notice run node-gyp-build
npm error code ENOENT
npm error syscall spawn ./script-wrapper
npm error path /tmp/a/node_modules/bcrypt
npm error errno -2
npm error enoent spawn ./script-wrapper ENOENT
npm error enoent This is related to npm not being able to find a file.
npm error enoent
Environment
  • npm: 12.0.2
  • Node.js: v26.8.1
  • OS Name: linux
  • npm config: part of the issue, see repro

Implementation considerations

Possible fixes:

  1. if script-shell starts with ./ - resolve against .npmrc location it's being read from in the @npmcli/config package logic
  • problem: other config sources are possible beyond .npmrc, which would complicate the logic/decision where to resolve a relative path against if it's coming from eg. a commandline flag.
  1. if script-shell starts with ./ - resolve against localPrefix location in the @npmcli/config package logic
  1. if script-shell starts with ./ - resolve against workspace root or INIT_CWD in the @npmcli/run-script package logic
  • run-scripts is a separate package and is not aware of settings and their specifics, doesn't seem like the best responsibility assignment to fix it there.
  1. [workaround] put INIT_CWD and potentially other npm-specific env variables in env before loading config files to allow them baing used so the wrapper definition would be script-shell=${INIT_CWD}/wrapper.sh
  • I didn't check, but feels like it'd be a big refactor

Same issue fixed in pnpm is resolving against workspace root, but the config only exists in workspace root.
https://github.com/pnpm/pnpm/issues/14422

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 reproduction in the issue, then read the @npmcli/config package logic and the related @npmcli/run-script responsibility discussion. Compare the proposed localPrefix and .npmrc-location approaches, including PR #9972, and verify behavior for workspace and lifecycle scripts. Done means a relative script-shell works from the demonstrated workspace and lifecycle contexts.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
cli, tooling
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.