How to configure and use package managers securely¶
Recently there has been greater prominence given to supply-chain attacks where malicious packages run a payload at install time to exfiltrate credentials from CI pipelines or individual developer machines. While the most prominent examples have centred on the JavaScript and TypeScript ecosystem, the issue is not unique to those languages.
This how-to guide shows you how to securely configure your language-specific package managers to guard against supply chain attacks. Generally speaking we try to use the following tactics:
- Disable the ability to run "post-install" or similar scripts. While a compromised package may still have a malicious payload which activates at runtime, we tend to run applications locally inside containers which have few credentials available. Developers tend to install packages locally to enable IDE code intelligence features and a developer's machine may have far more credentials available for a payload to exfiltrate.
- Enforce a minimum release age. The recent spate of supply-chain vulnerabilities have been focussed on "get as much as possible as quickly as possible" and so they have been rapidly discovered. As such by imposing a minimum age of releases considered for install we give ourselves a window where compromised packages can be discovered and removed before we install them. (Our renovatebot instance does this. It's default configuration is to require a minimum age of 3 days for releases from npm.)
JavaScript and TypeScript¶
We recommend using yarn as a package manager because its defaults include both disabling scripts
and a minimum release age of 3 days but only if you are running a recent version of yarn. This
section will cover other popular package managers in addition to yarn since we use a variety.
In summary, if you have no other requirements on which package manager you use:
- Use
yarn. - Use
corepackto make sure you are using the most recent version ofyarn(see below). - Explicitly set
enableScriptsandnpmMinimalAgeGateglobally (see below). - Explicitly set
enableScriptsandnpmMinimalAgeGatein your package (see below). - Explicitly set the version of
yarnused by your package (see below). - Use
yarn dlxinstead ofnpxto run ad hoc scripts from a command.
yarn¶
The yarn tool has the enableScripts and
npmMinimalAgeGate settings. The default values for these are to disable
script running and to gate packages to those which were released at least 3 days ago.
However, you need to make sure you are running the most recent version of yarn as these
defaults have changed.
To ensure you are running the most recent yarn:
$ npm install --global corepack
$ corepack prepare yarn@stable --activate
$ yarn --version # should be >= 4.0.0
4.14.1
To set secure defaults for the yarn command:
$ yarn config set --home enableScripts false
➤ YN0000: Successfully set enableScripts to false
$ yarn config set --home npmMinimalAgeGate 3d
➤ YN0000: Successfully set npmMinimalAgeGate to 4320
To check that yarn is correctly configured:
$ yarn config get enableScripts
false
$ yarn config get npmMinimalAgeGate
4320
To make sure that your JavaScript or TypeScript package has secure defaults, firstly ensure that
package.json has a packageManager field. E.g.:
{
"packageManager": "yarn@4.14.1"
}
Important
The packageManager field specifies the exact version of yarn to use and renovatebot will
keep this fresh for you.
Then, within the directory containing package.json, run:
$ yarn config set enableScripts false
➤ YN0000: Successfully set enableScripts to false
$ yarn config set npmMinimalAgeGate 3d
➤ YN0000: Successfully set npmMinimalAgeGate to 4320
This should create a .yarnrc.yml file with the following contents:
enableScripts: false
npmMinimalAgeGate: 3d
npm¶
Warning
Because of its secure defaults, we recommend that you use yarn for package management unless
you need features only available in npm.
The npm tool has the ignore-scripts and
min-release-age settings. The default values for these are to allow
running scripts from packages and to have no minimum package age gate.
Firstly, ensure that you are running version 11 or greater of npm:
$ npm --version
11.12.1
Set the ignore-scripts and min-release-age settings globally by adding the following lines to
~/.npmrc:
ignore-scripts=true
min-release-age=3
Note
npm config set --global does not, as you might expect, set values in $HOME/.npmrc, it tries
to set them system-wide which may required elevated privileges.
Check that these settings have taken effect:
$ npm config get ignore-scripts
true
$ npm config get before
{ ... some date three days ago ... }
To configure your package similarly, add the ignore-scripts and min-release-age to a .npmrc
file in the same directory as your package.json file.
pnpm¶
Warning
Because of its secure defaults, we recommend that you use yarn for package management unless
you need features only available in pnpm.
The pnpm tool has the ignoreScripts and
minimumReleaseAge] settings. The default values for these are to
allow running scripts and, post version 11 of pnpm to have a minimum age gate of 1 day.
Warning
Even if you set ignoreScripts to true, pnpm will still execute arbitraty code from the
.pnpmfile.{mjs,cjs} files. Because of this we do not recommend using
pnpm unless you require pnpm-specific features.
To set the enableScripts and minimumReleaseAge settings globally:
pnpm config set --location global ignore-scripts true
pnpm config set --location global minimum-release-age 4320
Check that these settings have taken effect:
$ pnpm config get ignore-scripts
true
$ pnpm config get minimum-release-age
4320
To set the enableScripts and minimumReleaseAge settings within your project, change to the
directory containing package.json and run:
pnpm config set --location project ignore-scripts true
pnpm config set --location project minimum-release-age 4320
If you require pnpm to install your package, also set packageManager in package.json
accordingly.
Other languages¶
If you feel other languages' package managers are missing in this document and if you know how to configure them securely, please consider updating this page.
Summary¶
In this guide you learned how to securely configure various package managers to avoid certain categories of supply chain attacks.