Security
Getting rid of NPM scripts

by Eric Fortis

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 prefer the latter, so I don’t have to remember the flag. But for that, we will need something to replace NPM scripts. For example, 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 such as a makefile again.

Makefile

all: test lint slint build

build:
	sh -c "time ./MakeProduction.js"

install:
	rsync --times ./dist server-a:/home/www

dev:
	./MakeDev.js
test:
	mocha "src/**/*.test.js"
lint:
	eslint src
slint:
	stylelint "src/**/*.css"

.PHONY: test lint slint build install all
$ make test

If the package is not globally installed, you can prefix the path:

lint:
	node_modules/.bin/eslint src

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

Comments

Discussion at Hacker News.

Sponsored by: