Security
Getting rid of NPM scripts
In 2016, Sam Saccone, from Google, discovered a vulnerability that allows adversaries to run arbitrary scripts when installing an NPM package of theirs. As mitigation, NPM co‑founder Laurie Voss suggests:
-
Option 1: using
npm install --ignore-scripts
-
Option 2: adding
ignore-scripts=true
to.npmrc
I use the latter flag, so I don’t have to remember it. But for that, we will need something to replace NPM scripts. For example, a shell script or a Makefile.
Update 2021: Before NPM v7, enabling ignore‑scripts
disabled
NPM scripts. After v7, mentioned flag no longer disables them; it only prevents
the life cycle scripts, which are the attack surface of the vulnerability.
Update 2022: Feross Aboukhadijeh, discovered a vulnerability when running NPM scripts. Therefore, we need an alternative again.
Alternative 1: Shell script
#!/bin/sh case $1 in dev) ./make-dev.js ;; test) mocha "src/**/*.test.js" ;; lint) eslint src ;; slint) stylelint "src/**/*.css" ;; prod) time ./make-production.js ;; all) $0 test && $0 lint && $0 slint && $0 prod ;; *) echo "Invalid task $1" >&2; exit 1 ;; esac
Which can be ran as:
$ ./run test
If the package is not globally installed, you can prefix the path:
lint) node_modules/.bin/eslint src ;;
Alternative 2: Makefile
As suggested in Hacker News, a Makefile:
dev: ./make-dev.js test: mocha "src/**/*.test.js" lint: eslint src slint: stylelint "src/**/*.css" prod: sh -c "time ./make-production.js" all: test lint slint prod .PHONY: test lint slint prod all
$ make test
Overriding at installation
If you need packages that install binaries, or rely on running an NPM script, temporarily override the mitigation:
$ npm install --ignore-scripts=false package-i-trust
Or, trigger the installation script:
$ node node_modules/puppeteer/install.js
Overriding a project
If you can’t follow the above recommendations for certain project,
instead of allowing scripts globally, create an .npmrc
file next to the package.json
with the following line:
ignore-scripts=false