Build Script Approval

A package's preinstall, install and postinstall scripts run arbitrary commands the moment it is installed. They compile native addons or fetch platform binaries, and they are also malware's favorite entry point (Supply-Chain Security). npm 2,036 runs them by default. pnpm 10 69,400 stopped running dependencies' scripts unless approved, and pnpm 11 made an unapproved script fail the install (strictDepBuilds: true). Add bcrypt, a password-hashing library with an install script, to a copy of BookNest.

An unapproved build script stops pnpm, then an explicit approvalShell
mkdir ~/v5-ch1/pnpm-build && cd ~/v5-ch1/pnpm-build && cp ../booknest/package.json .
pnpm add bcrypt; echo "exit=$?"; cat pnpm-workspace.yaml
pnpm approve-builds bcrypt; cat pnpm-workspace.yaml
Output
...
Progress: resolved 83, reused 83, downloaded 0, added 83, done
...
Error: ERR_PNPM_IGNORED_BUILDS
  × adding a new package
  ╰─▶ Ignored build scripts: bcrypt@6.0.0
  help: Run "pnpm approve-builds" to pick which dependencies should be allowed
        to run scripts.
exit=1
allowBuilds:
  bcrypt: set this to true or false
...
.../bcrypt@6.0.0/node_modules/bcrypt install$ node-gyp-build
.../bcrypt@6.0.0/node_modules/bcrypt install: Done
allowBuilds:
  bcrypt: true

pnpm installed the files, refused the script, exited with status 1 so CI would stop, and left a placeholder asking for a decision. pnpm approve-builds bcrypt recorded true and ran the script (!bcrypt records a denial). Commit that file, and a dependency that suddenly ships a script fails the build instead of running silently. A blocked script is not always a broken package: bcrypt 6 ships prebuilt binaries and worked here even while blocked, so read a script before approving it. pnpm 11 also added minimumReleaseAge, set by default to 1,440 minutes, which refuses package versions published less than a day ago, giving the registry and security scanners time to catch a malicious release before it reaches you.