Get safe and remain productive with can-i-ignore-scripts
Tags: javascript, security, npm
Published: 2021-08-24 09:10:39

So you've heard about supply chain security? You should no longer want to run `npm ci` without the `--ignore-scripts` flag. If you still need more convincing - I made a package that makes typescript compiler inject malicious code to your application. [See this video for more](https://www.youtube.com/watch?v=Y5gtOqPjUJM)

Now with the good advice to always run `npm ci --ignore-scripts` all that's left is to start using it. But wait! My app no longer works! Some of these scripts were necessary after all...  
All you need to do is `npm rebuild packagename`. If you know which package needs its scripts to run.

That's the problem with security best practices - there's always convenience that you need to give away. But that's where I come in! I enjoy making security best practices easier to deploy in your team. (That's why I wrote npm-audit-resolver but that's a different story)

## `--ignore-scripts` and no regrets 

Figuring out which of your packages actually need their postinstall scripts is not a candidate to make the list of "top 5 moments at work". I bet you'll be happy to hear there's a tool to do it for you.

[`can-i-ignore-scripts`](https://www.npmjs.com/package/can-i-ignore-scripts) is a commandline utility that scans your node_modules folder and lists all packages with scripts that run on installation. It then checks against a collection of known packages whose scripts were already evaluated before and lists suggestions.

You can use the suggestions to quickly choose which scripts to run after the installations have finished.  
There's nothing wrong with accepting some scripts you're not sure about. The goal of having an allowlist is to avoid running a script that was maliciously added where it wasn't before. The sooner you introduce `--ignore-scripts` to your app the better. Even if that means adding exceptions for ALL existing packages.

Quick roll out in your project? Here you go:

```
npm ci --ignore-scripts
npx can-i-ignore-scripts


█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
  ▄▄·  ▄▄▄·  ▐ ▄    ▄     ▪    ▄▄     ▐ ▄       ▄▄▄   ▄▄▄      ▄▄▄▄·
 ▐█ ▌ ▐█ ▀█ ·█▌▐█   ██    ██  ▐█ ▀    █▌▐█      ▐▄ █· █  ▀·  .▀  .█▌
 ██ ▄▄▄█▀▀█ ▐█▐▐▌   ▐█·   ▐█· ▄█ ▀█▄ ▐█▐▐▌ ▄█▀▄ ▐▀▀▄ ▐█▀      ▄█▀▀▀·
 ▐███▌▐█ ▪▐▌██▐█▌   ▐█▌   ▐█▌ ▐█▄ ▐█ ██▐█▌▐█▌.▐▌▐▄ █▌▐█▄▄▄▌   ▀
 ·▀▀▀  ▀  ▀ ▀▀ █▪   ▀▀▀   ▀▀▀ ·▀▀▀▀  ▀▀ █▪ ▀█▄▀▪.▀  ▀ ▀▀▀     ▀

▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
Found following packages with scripts:
[ ignore ] 'pre-commit' has scripts but they can be ignored 
             reason: used in local development
[ ignore ] 'core-js' has scripts but they can be ignored 
             reason: funding
[  keep  ] 'grpc' needs its scripts to run
[  keep  ] 'bignum' needs its scripts to run

▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
What now? Run rebuild after 'npm ci --ignore-scripts' to trigger scripts you need to keep. 

A suggestion to get you started:
npm rebuild bignum grpc
█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█
```
Then take a look at the recommendations and add the *rebuild* line after the installation in CI
```
npm rebuild bignum grpc
```

## Go hack yourself

Don't know if postinstall scripts actually run in your CI? Or maybe you need to convince someone it'a an issue? Hack yourself by installing [`@naugtur/pentest-my-ci`](https://www.npmjs.com/package/@naugtur/pentest-my-ci) as your dev dependency.  It contains a preinstall script that stops the CI and tries to scare the reader of the logs a bit.