Skip to content

Protect dependency installation process with allow-scripts

@lavamoat/allow-scripts is a CLI tool for instructing your package manager to execute only the dependency lifecycle hooks specified in an allowlist.

Prerequisites

Install

  • npm: npm i -D @lavamoat/allow-scripts
  • Yarn: yarn add -D @lavamoat/allow-scripts

Note that installation of the dependency is likely to cause your other dependencies to be installed. You could install @lavamoat/allow-scripts globally and use it to set up a project without triggering installing dependencies before the setup and the allowlist is in place.

Setup

Initialization

The setup command will initialize your project for use with @lavamoat/allow-scripts.

  • npm: npm exec allow-scripts setup
  • Yarn: yarn allow-scripts setup

Configuration

Configuration can be done automatically or manually.

Automatic Allow-listing

The auto command will generate and write a configuration to the lavamoat property of package.json.

  • npm: npm exec allow-scripts auto
  • Yarn: yarn allow-scripts auto

Manual Allow-listing

@lavamoat/allow-scripts’s configuration is stored in the lavamoat property of package.json within its allowScripts property.

The value is of type Record<PackageName, boolean> where PackageName is a dependency which is either allowed or disallowed to run lifecycle scripts. To allow script execution, use a value of true; to disallow, use a value of false. Items missing from the list will cause a warnings so that you know when you might need to add a newly installed item to the list.

Example Configuration

package.json
{
"lavamoat": {
"allowScripts": {
"keccak": true,
"core-js": false
}
}
}

Running Lifecycle Scripts

When invoked without a command (or with the run command), allow-scripts will execute all lifecycle scripts for the packages specified in @lavamoat/allow-scripts’s configuration:

  • npm: npm exec allow-scripts run
  • Yarn: yarn allow-scripts run

allow-scripts will fail if it detects dependencies attempting to run scripts which haven’t yet been configured; you will be advised to run allow-scripts auto to rectify the situation.

Yarn plugin

To comfortably work with Yarn Berry (specifically yarn v3 or above) it’s recommended that you use a simple plugin to execute allow-scripts after installation.

Yarn plugins are installed via public URLs.

Terminal window
yarn plugin import https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js

Show Configured Packages

Use the list command to print information about configured packages and scripts, specifying allowed and disallowed packages.

  • npm: npm exec allow-scripts list
  • Yarn: yarn allow-scripts list

Usage Tips

Consider adding a setup lifecycle script for all your post-install steps. This can be just a regular script (no magic needed!). Also, it is a good place to add other post-processing commands you want to use.

In the future, when you add additional post-processing scripts, e.g. husky, you can add them to this setup script.

Example setup script
{
"scripts": {
"setup": "npm install && npm exec allow-scripts && tsc -b"
}
}

Mitigating bin script confusion

Bin script confusion is a shell injection attack (wiki) where a dependency causes a malicious script to run by declaring a bin script (in package.json) matching an executable in the user’s PATH. ignore-scripts does not protect against this attack.

To enable protection against bin script confusion, use the --experimental-bins flag when executing allow-scripts.

What does --experimental-bins do?

  • allow-scripts setup will add a new configuration option to your project’s package manager RC file (.npmrc/.yarnrc) to disable automatic linking bin scripts
  • allow-scripts auto will generate an allowlist of bin scripts allowed for execution
  • allow-scripts run will link only the allowed scripts and replace disallowed scripts with a trivial executable that exits with a non-zero exit code.

When a disallowed bin script is attempted to be executed, the command will fail with an error providing guidance.