npm, the package manager maintained by GitHub and distributed with Node.js, has released npm 12 with security-focused changes that turn three previously automatic installation behaviors into opt-in actions. The update, announced in June and available behind warnings since version 11.16.0, also deprecates granular access tokens that bypass two-factor authentication. The flagship change sets allowScripts to off by default, meaning dependency preinstall, install, and postinstall scripts won't execute unless developers explicitly permit them in a project — including implicit node-gyp builds for packages with a binding.gyp file, even when no install script is declared.

The other two default settings target non-registry sources. The --allow-git flag now defaults to none, closing a code execution pathway where a Git dependency's own .npmrc file could override the Git executable even with --ignore-scripts enabled, and --allow-remote defaults to none, blocking https tarball dependencies. The related --allow-file and --allow-directory flags remain unchanged. JFrog data shows the three vectors accounted for roughly 53% of malicious npm attacks observed in the past year. Developers review pending scripts, approve those they trust, and commit the resulting allowlist in package.json, though global installs and npx can't use approve-scripts and require the config instead.

GitHub's migration discussion recommends allowing what's already in the tree first, then tightening restrictions, and provides recipes for native modules, Cypress, Playwright, Puppeteer, Electron, and Husky. Commenters flagged that an existing ignore-scripts=true setting takes precedence and silently defeats the allowlist, and that newly installed packages create a chicken-and-egg problem since npm approve-scripts reads from node_modules and errors with ENOMATCH if the package isn't yet installed. Community reaction has been largely supportive — the Hacker News thread drew 484 points and more than 200 comments, with one user writing that "postinstall scripts should've been removed long time ago." Others were less convinced, pointing to legitimate use cases such as patch-package, while one argued the allowlist "has no scope" and leaves it "unpredictable if any of your dependencies of dependencies needs a script."

Security researchers have raised approval fatigue as the bigger risk, noting that esbuild, sharp, core-js, puppeteer, and bcrypt all rely on lifecycle scripts and warning that repeated broken builds will turn deny-by-default into "a click-through prompt" while pushing attacker activity onto surfaces with less visibility. npm is also the last major package manager to adopt these controls — pnpm has offered install script allowlisting for years and shipped minimumReleaseAge in version 10.16, yarn added npmMinimalAgeGate in 4.10.0, and bun followed in 1.3, ahead of npm's own min-release-age in 11.10.0. The changes reflect the tension between locking down a critical infrastructure layer and maintaining the workflow velocity that made npm the default for Node.js development. Teams that rely heavily on native bindings or automation hooks will need to weigh the overhead of managing allowlists against the reduced attack surface, particularly as threat actors shift tactics in response to tighter defaults.