-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Current Behavior
Intro
NPM is a package manager used in our CI/CD environments, We are using it to download and install all our different dependencies inside our building phase for production.
In order to use it safely, we use some precautions, We try to minimize as much as possible its exposure to secrets but still sometimes we have no choice but to add them.
Reading the documentation here and best practices using the cli around the internet it is best to run in ci environments with npm ci --ignore-scripts
which should not run any scripts, additionally, we saw that npm sees bypassing this command as a high severity
Researching this subject we found out that a developer or malicious actor with access to the codebase can in fact force npm to run scripts although we configured it explicitly to ignore scripts.
Talking with the bounty team the response was that this is not eligible for bounty and is not considered a risk as this is the intended behavior of npm.
We agree that this is a design issue, but nevertheless, this can be used as an attack vector by actors, we want to raise the issue here and understand what mitigations can we have in the meantime, and if this design will be changed in the near future?
The Issue
When adding a .npmrc file to our repo, npm will pick up the file and read its configuration. This means that any command using npm will automatically pick up the configuration file.
It is possible to inject a configuration that will then execute code in the installation context and attempt to attack the installation environment by two vectors:
- Adding
git=${PWD}/rce.sh
to .npmrc and adding an installation from git to the package.json, such as"dependencies": { "ini":"git://github.com./npm/ini.git#v2.0.0" }
will execute the rce.sh script when runningnpm install
version 7,8 - Adding
onload-script=${PWD}/rce
to .npmrc will invoke the rce.js script in the library when running ANY npm version 6 command
Expected Behavior
As we are not expecting to run any scripts when running with "--ignore-scripts" this is can and will affect our devops installations if a malicious actor gains access to parts of our codebase.
I understand that this was not the intended behavior of the flag,
but it became the only security measure in use and implies that there will be no unintended scripts running
Steps To Reproduce
Using npm version 7,8
- npm init
- npm i --save "git://github.com./npm/ini.git#v2.0.0"
- echo "git=${PWD}/test.sh" > .npmrc
- echo 'echo "HACKED!!!" > poc.txt && git $@' > test.sh
- rm -rf node_modules
Attack phase
- npm ci --ignore-scripts
- cat poc.txt
Using npm version 6
- npm init
- echo "onload-script=${PWD}/rce" > .npmrc
- echo "console.log('Hacked") > rce.js
Attack phase
- npm ci --ignore-scripts
Environment
- npm: 8.1.4
- Node: v14.15.5
- OS: OSX
- platform: Macbook Pro
- npm config:
; "user" config from /Users/rotembar/.npmrc
registry = "https://registry.npmjs.org/"
; "project" config from fuzz/npm-lion/.npmrc
git = "npm-lion/test.sh"