4.6 KiB
name, description
| name | description |
|---|---|
| pnpm-supply-chain-security | Build-script approval (allowBuilds), minimum release age, trust policy, and exotic-subdep blocking for safer installs |
pnpm Supply-Chain Security
pnpm blocks several attack vectors by default. Agents installing dependencies must understand these, since installs can fail or prompt on them.
Build-script approval (allowBuilds)
By default pnpm does not run dependency lifecycle scripts (preinstall/install/postinstall). Packages must be explicitly approved. Approval lives in one allowBuilds map in pnpm-workspace.yaml.
allowBuilds:
esbuild: true
core-js: false
# version selectors are supported
nx@21.6.4 || 21.6.5: true
- Packages not listed are unreviewed and blocked by default.
strictDepBuilds: true(default) ⇒ unreviewed builds make install exit non-zero (ERR_PNPM_IGNORED_BUILDS). Setfalseto warn instead.- During install, unreviewed packages with build scripts are auto-added to
pnpm-workspace.yamlwith a placeholder so you can settrue/false.
allowBuildsreplaces the removedonlyBuiltDependencies,neverBuiltDependencies,ignoredBuiltDependencies,onlyBuiltDependenciesFile, andignoreDepScripts.
Approving builds
pnpm approve-builds # interactive prompt
pnpm approve-builds --all # approve all pending
pnpm approve-builds esbuild fsevents !core-js # ! = deny
pnpm add --allow-build=esbuild my-bundler # approve while adding
pnpm add -g --allow-build=esbuild esbuild # global (replaces approve-builds -g)
Escape hatch (dangerous)
dangerouslyAllowAllBuilds: true # runs ALL build scripts now and in the future — avoid
Minimum release age
Delay installing freshly published versions so malicious releases (usually pulled within an hour) are avoided. Applies to all deps, including transitive.
minimumReleaseAge: 1440 # minutes; default 1440 (1 day) since v11
minimumReleaseAgeExclude: # always install newest of these immediately
- webpack
- '@myorg/*'
- nx@21.6.5 # exempt a specific version
minimumReleaseAgeStrict— when no in-range version satisfies the age, fail (default when you setminimumReleaseAgeyourself) vs. fall back.minimumReleaseAgeIgnoreMissingTime— skip the check for registries that omit thetimefield (defaulttrue).
Trust policy
Fail if a package's trust level decreased vs earlier releases (e.g. was published by a trusted publisher, now only has provenance or nothing).
trustPolicy: no-downgrade # off (default) | no-downgrade
trustPolicyExclude:
- 'chokidar@4.0.3'
trustPolicyIgnoreAfter: 525600 # ignore the check for pkgs published > N minutes ago
Block exotic transitive sources
blockExoticSubdeps: true # default
When true, only direct dependencies may use exotic sources (git repos, direct tarball URLs); all transitive deps must come from a trusted source (registry, local path, workspace link, or trusted GitHub repos).
Lockfile integrity
Since v11, a downloaded tarball whose hash doesn't match pnpm-lock.yaml is a hard error (ERR_PNPM_TARBALL_INTEGRITY) — protecting committed lockfiles from a compromised registry/proxy. --force and pnpm update do not bypass it.
pnpm install --update-checksums # narrow opt-in after verifying the new bytes
Trusted store/cache
The content-addressable store, global virtual store, and metadata cache are part of pnpm's trust domain. Share them only between mutually trusting users/jobs and protect with filesystem permissions. verifyStoreIntegrity (default true) detects accidental corruption but does not make a writable-by-untrusted store safe.
Key Points
- Dependency build scripts are blocked until approved via
allowBuilds/pnpm approve-builds; unreviewed builds fail by default (strictDepBuilds). minimumReleaseAge(default 1 day in v11) delays new releases;trustPolicy: no-downgradeblocks trust regressions;blockExoticSubdepslimits transitive git/tarball sources.- Tarball integrity mismatches are fatal; use
--update-checksumsonly after verification. - Treat the store/cache as trusted shared state.