Skip to content

npm v12 Is About to Stop Running Your Install Scripts — Here's What to Audit

The next npm major flips lifecycle scripts, Git, and remote-URL dependencies from opt-out to opt-in. The warnings are already live in 11.16.0, so you have until July to find out what breaks.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Jun 9, 2026 · 6 min read

For as long as most of us have been typing npm install, the package manager has been quietly running arbitrary code on our machines. preinstall, install, and postinstall hooks fire automatically, native modules get compiled, and a transitive dependency three levels down can execute whatever it wants the moment you pull it in. That's been the single most reliable foothold in npm supply-chain attacks for years — and with npm v12, it's finally getting closed by default.

GitHub's changelog pegs v12 for an estimated July 2026 release, and the headline is that several npm install behaviors that run automatically today become things you explicitly opt into. The good news: all of it is already wired up behind warnings in npm 11.16.0 or newer, so you can find out exactly what breaks before the major lands.

Install scripts go silent unless you allow them

The big one is allowScripts defaulting to off. Once v12 ships, npm install will not execute preinstall, install, or postinstall scripts from your dependencies unless they're explicitly allowed in your project.

The sharp edge here is native builds. A package that ships a binding.gyp but no explicit install script still gets blocked — because npm runs an implicit node-gyp rebuild for it, and that counts as a script. So if your tree leans on anything compiled (node-gyp, native bindings, the usual suspects), a default npm install under v12 will leave those packages unbuilt until you say otherwise. prepare scripts from git, file, and link dependencies get blocked the same way.

The workflow to get ahead of it is a small set of new subcommands:

# See everything that would be blocked
npm approve-scripts --allow-scripts-pending

# Allow the packages you actually trust
npm approve-scripts

# Explicitly block the rest
npm deny-scripts

The resulting allowlist is written into package.json and is meant to be committed. After the upgrade, only the scripts you approved keep running; anything you left unapproved simply stops. If your install routine depends on lifecycle scripts today — and almost every non-trivial project does, even if you don't realize it — you'll see warnings the moment you're on 11.16.0+.

If this pattern feels familiar, it should. pnpm already moved to blocking dependency build scripts by default and gating them behind an explicit onlyBuiltDependencies allowlist. npm is converging on the same posture: assume a freshly installed package is hostile until a human vouches for it. The difference is npm's enormous install base, which means the blast radius of flipping this default is correspondingly larger.

Advertisement

Git dependencies stop resolving by default

The second change sets --allow-git to default none. npm install will no longer resolve Git dependencies — direct or transitive — unless you explicitly pass --allow-git.

The motivation is more subtle than "don't run scripts." Per GitHub, a Git dependency's .npmrc could override the Git executable itself, which is a code-execution path that persists even with --ignore-scripts. In other words, the old advice of "just disable lifecycle scripts in CI" didn't fully close the door — turning off scripts doesn't help if the act of resolving a Git URL can hijack the binary doing the resolving. This one was announced back on 2026-02-18 and has been available since npm 11.10.0+, so it's had the longest runway.

Remote URL tarballs join the blocklist

Third: --allow-remote also defaults to none. Dependencies resolved from remote URLs — think https tarballs, again direct or transitive — won't install unless you opt in with --allow-remote. That flag has been available since npm 11.15.0+.

If you've ever pinned a dependency to a raw tarball URL (a fork hosted somewhere, an internal artifact behind a plain HTTPS link, a quick patch you never got around to publishing), this is the change that'll bite quietly. It's exactly the kind of thing that lives in one service's package.json, works fine for two years, and then breaks the day someone bumps the toolchain.

Worth noting what isn't moving: the related --allow-file and --allow-directory flags keep their current defaults in v12. Local file and directory dependencies — your monorepo file: links and friends — are not affected by this round.

The pre-flight checklist

None of these defaults change on their own schedule; they all land together with v12. The preparation path is the same regardless of which one trips you up:

  • Upgrade to npm 11.16.0 or later. This is where all three behaviors are observable behind warnings simultaneously.
  • Run your normal install and read the warnings. Don't pipe them to /dev/null — they're the whole point.
  • Audit scripts with npm approve-scripts --allow-scripts-pending, approve what you trust, and commit the updated package.json. That allowlist is now part of your project's security posture, so treat the PR like one.
  • Grep your manifests and lockfiles for Git and remote-URL dependencies. Anything resolved over git+... or a bare https tarball needs an explicit --allow-git / --allow-remote, or a migration to a published package.
  • Check npx and global installs separately. GitHub points to a distinct allow-scripts config for those paths, so your CLI tooling won't necessarily inherit your project's allowlist.

The practical reality is that the first post-upgrade install in a busy monorepo is going to surface a list of packages running scripts that's longer than you'd like — and that's the feature working as intended. Better to discover your trust boundary on 11.16.0 with warnings than to find it in CI the morning v12 rolls out. July isn't far off; the audit is cheap now and annoying later.

Sources & further reading

  1. Upcoming breaking changes for NPM v12 — github.blog
  2. Upcoming breaking changes for npm v12 — github.blog
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 5

Join the discussion

Sign in or create an account to comment and vote.

Fiona Walsh @frontend_fae · 3 days ago

finally, about time we got some security upgrades

Lena Vogel @lowlevel_lena · 3 days ago

finally, about time they flipped the default on those lifecycle scripts - been waiting for this change since all the supply chain attacks started popping up, now to go audit my own install scripts...

Oleg Petrov @db_nerd_oleg · 3 days ago

finally, some sanity to package installs

Pia Andersson @promptsmith_pia · 3 days ago

i've already started auditing my projects and it's crazy how many dependencies have install scripts that will break with this change - definitely worth checking your package.json files now

Yuki Tanaka @distsys_yuki · 3 days ago

yeah, it's pretty surprising how many packages rely on these auto-run scripts - i've been digging through my own projects and it's making me think about how we can use declarative config to minimize the need for these kinds of imperative install scripts in the first place

Related Reading