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.

We recommend using the globally installed @lavamoat/allow-scripts for the initial setup. This avoids triggering installation of your other dependencies before the setup and the allowlist is in place.

Terminal window
npm i -g @lavamoat/allow-scripts

Be sure to include the @lavamoat/ namespace in the package name.

Now without triggering an installation in the project you’re setting up, you can go to the project folder and run:

Terminal window
allow-scripts setup

Install as a project-local development dependency to enable contributors to execute allowed scripts.

  • npm: npm i -D @lavamoat/allow-scripts
  • Yarn: yarn add -D @lavamoat/allow-scripts
  • pnpm: pnpm 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.

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 can be done automatically or manually.

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

@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 (with a #version suffix by default) 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 warnings so that you know when you might need to add a newly installed item to the list.

package.json
{
"lavamoat": {
"allowScripts": {
"keccak#3.0.4": true,
"rezeplayer>core-js#3.49.0": false,
"some-package-denied-for-all-versions": false
}
}
}

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.

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

Use the list command (alias: debug) to print all information allow-scripts uses to populate and run the allowed scripts, including the list of changes it would make if allow-scripts auto was executed.

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

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"
}
}

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.

  • 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.