[BUG] Workspace Bin Hoisting Collision causes incorrect binary execution via npm exec
Nobody has claimed this yet.
- 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
When two workspaces each depend on a different package that exports a binary with the exact same name, Arborist hoists both dependencies to the root node_modules/. However, because bin-links uses a "first-wins" mechanism, only one shim gets created in root/node_modules/.bin/.
As a result, when running npm exec -w <loser-workspace> -- <bin>, libnpmexec falls back to the root .bin folder and inadvertently executes the wrong binary (the one belonging to the other workspace's dependency) because a local .bin folder was never created for the workspace.
Expected Behavior
npm exec -w <workspace> should completely isolate identical binary names in a monorepo and always execute the binary that belongs to the target workspace's dependency tree, regardless of hoisting rules at the root.
Steps To Reproduce
- Create a monorepo with two workspaces:
workspace-aandworkspace-b. - Install
dep-1(which exports a bin namedmy-cli) intoworkspace-a. - Install
dep-2(which also exports a bin namedmy-cli) intoworkspace-b. - Observe that both dependencies hoist to the root. Only one of them (e.g.,
dep-1) gets itsmy-clishim created inroot/node_modules/.bin/. - Run
npm exec -w workspace-b -- my-cli(the one that "lost" the race). - See that
dep-1's script is executed instead ofdep-2's script.
Environment
- npm:
12.0.0-pre.2 - Node.js:
v23.11.1 - OS Name:
macOS 15.7.7 - System Model Name:
MacBookPro18,1 - npm config:
; "user" config from /Users/arjun/.npmrc
//registry.npmjs.org/:_authToken = (protected)
; "project" config from /Users/arjun/Desktop/npm/.npmrc
package-lock = true
; node bin location = /Users/arjun/.nvm/versions/node/v23.11.1/bin/node
; node version = v23.11.1
; npm local prefix = /Users/arjun/Desktop/npm
; npm version = 12.0.0-pre.2
; cwd = /Users/arjun/Desktop/npm
; HOME = /Users/arjun
; Run `npm config ls -l` to show all defaults.
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 by reproducing the workspace setup described in the issue and inspect how bin-links creates root and workspace .bin shims. Trace the npm exec workspace path through libnpmexec, especially its fallback to the root .bin folder. Done means npm exec -w workspace-b -- my-cli runs dep-2's binary when dep-1 and dep-2 export the same name.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100