npm v12 is now generally available and tagged latest. The release turns on the install-time security defaults GitHub announced in June and starts winding down the most sensitive uses of 2FA-bypass granular access tokens (GATs). Both changes landed in today's changelog.
The direction will be familiar to anyone who followed the past year of npm supply chain attacks. Almost every worm and credential stealer that hit the registry since late 2025 ran at install time, before any application code loaded. v12 makes that execution path opt-in.
Install-time execution is now opt-in#
Three npm install behaviors that used to run automatically now require explicit approval:
allowScripts defaults to off. preinstall, install, and postinstall scripts from dependencies do not run unless you allow them. This includes the implicit node-gyp rebuild npm triggers for any package that ships a binding.gyp, even when there is no explicit install script. prepare scripts from git, file, and link dependencies are blocked the same way.--allow-git defaults to none. Git dependencies, direct or transitive, no longer resolve unless allowed. This closes a path where a git dependency's .npmrc could override the git executable, which ran code even under --ignore-scripts. We covered this change when it first shipped behind a flag in February.--allow-remote defaults to none. Dependencies from remote URLs, such as https tarballs, no longer resolve unless allowed.
Attackers already moved to the implicit node-gyp path. The Miasma "Phantom Gyp" waves used a small binding.gyp file to run code during npm install with no lifecycle script in package.json, which let the payload slip past scanners that only watch preinstall and postinstall fields. Our team has tracked this technique across multiple waves. Blocking the implicit rebuild by default removes that gap.
npm is not first to turn install scripts off by default. pnpm blocked lifecycle scripts by default in version 10 and added a 24-hour minimum release age in version 11. Today's v12 release brings npm's default more in line with the rest of the ecosystem.
What the new default does at install time#
The v12 default is a soft skip, not a hard failure. An unapproved script is skipped, npm prints a warning, and the install still succeeds. A separate opt-in setting, strict-allow-scripts, turns that skip into a hard error and is aimed at CI. This question came up repeatedly in the community discussion that npm maintainers opened to help teams prepare for v12.
Native modules behave differently. A skipped node-gyp build does not fail the install. It fails later at runtime, when your code tries to load a module that was never compiled. Packages like sharp, better-sqlite3, bcrypt, and node-sass need approval, as do binary downloaders such as Cypress, Playwright, Puppeteer, and Electron.
vlt, the package manager and registry startup from former npm CLI team lead Darcy Clarke, recommends that authors ship platform-specific binaries through optional dependencies instead of install scripts, the model esbuild popularized. Clarke also has an accepted npm RFC that would make it a native package-distribution format.
Unknown .npmrc keys will warn instead of error#
One v12 breaking change that would have made the upgrade harder has been walked back. The change turned unknown configuration keys in .npmrc into a hard EUNKNOWNCONFIG error. A merged pull request from GitHub's @reggi restores the pre-v12 behavior: unknown file configs warn by default, with an opt-in strict-npmrc setting for anyone who wants the stricter check. Unknown CLI flags still error. It is a small change, but it removes a real barrier for teams carrying legacy or tool-specific keys in their config, which is exactly the kind of friction that stalls a security upgrade.
2FA-bypass tokens lose account and publishing powers#
npm is also beginning to deprecate granular access tokens configured to bypass 2FA.
The first step, expected in early August 2026, stops these tokens from performing sensitive account, package, and organization actions. That covers creating or deleting tokens, changing your password, email, profile, or 2FA settings, generating recovery codes, changing package access or maintainers, editing trusted publishing configuration, and managing org and team membership. Those operations will require an interactive session with 2FA.
A later step, expected around January 2027, removes direct publishing from 2FA-bypass tokens. Their publishing surface drops to reading private packages and staging a publish, where a package only goes public after a human approves it with 2FA. GitHub's guidance is to move automated publishing to trusted publishing (OIDC) or staged publishing with a human approval step, rather than a long-lived publish token. Teams can follow along in the GAT community discussion.
npm may backport v12 to Node 24 and 26#
The npm team said it is hoping to backport v12 to Node 24 and Node 26, though the call belongs to the Node release team. If that lands, the new defaults reach both active LTS lines rather than waiting for Node 27, which means a larger audience on a shorter timeline.
The community discussion also pointed to a gap in the approval tooling itself. npm approve-scripts --allow-scripts-pending lists which packages have scripts and the command each one runs, but not what those scripts do once they run: what files they pull in, whether they make network calls, read environment variables, or write outside the package directory. One contributor opened an RFC proposing a review-report mode that surfaces those signals and flags whether a script is new, changed, or unchanged since the last approved version.
The Shai-Hulud and Miasma attack waves that defined the past year ran from compromised maintainer accounts publishing through legitimate pipelines, some with valid provenance. Neither install-script blocking nor OIDC closes that entry point. What v12 removes is the default that let an injected install script or binding.gyp run the moment a package landed in node_modules, so a compromised version of a package you have not already approved no longer executes on its own.