npm v12, estimated for July 2026, introduces three security-breaking default changes that affect every Node.js developer. Install scripts become opt-in, remote tarballs are blocked, and Git dependencies require explicit approval. Here's exactly what's changing and how to migrate.
On June 9, 2026, the GitHub Changelog confirmed the final set of default changes shipping in npm v12. These have been available behind warnings since npm 11.10.0, but v12 flips them on by default:
preinstall, install, and postinstall scripts
in dependencies will no longer run automatically. You must explicitly approve them
using npm approve-scripts and npm deny-scripts. Available
behind warnings in npm 11.16.0+.
--allow-remote Defaults to None
npm will no longer resolve dependencies from remote URLs — including HTTPS tarballs —
unless explicitly allowed via --allow-remote. This covers both direct
and transitive dependencies. Available behind warnings in npm 11.15.0+.
--allow-git Defaults to None
Git dependencies (direct or transitive) are blocked by default. This closes a specific
code-execution path where a Git dependency's .npmrc could override the Git
executable — even with --ignore-scripts. Available behind warnings in
npm 11.10.0+.
All three changes can be tested right now in npm 11.10.0+. The warnings will tell you exactly which packages are affected in your project. Don't wait until July to discover your build breaks.
Install scripts have become the primary attack vector for npm supply chain attacks. The Mini Shai-Hulud worm (May 2026) compromised over 170 packages by injecting malicious code through preinstall hooks. Other package managers — pnpm, Yarn, Bun, Deno — either block install scripts by default or require explicit approval. npm was the only holdout.
The allow-remote and allow-git changes close additional vectors. The Git dependency
issue was especially dangerous: a compromised Git dependency's .npmrc
could override the Git executable npm uses to checkout repos, effectively giving an
attacker control over the install process even when scripts were disabled.
For a deeper analysis of the attack landscape that led to these changes, see my npm Install Scripts Opt-In RFC analysis and the Mini Shai-Hulud supply chain attack breakdown.
First, upgrade to npm 11.16.0+ to enable all warnings:
# Upgrade to latest npm 11
npm install -g npm@11
# Verify version
npm --version
# Should be 11.16.0 or higher
# Install with warnings enabled
npm install --install-strategy=manual
Run the query command to list every dependency that uses install scripts:
# List all packages with scripts
npm query .scripts
# Get a concise list of package names only
npm query .scripts | jq '.[].name'
# Check with warnings (npm 11.16+)
npm install --install-strategy=manual
# Warnings will show: "package X has 1 script(s) that will not run in v12"
Typical packages that trigger this warning include:
npm 11.16+ introduces two new commands for managing the script allowlist:
# Approve a specific package's scripts
npx npm-approve-scripts --allow esbuild
# Approve multiple packages
npx npm-approve-scripts --allow esbuild,sharp,@swc/core
# Deny a package
npx npm-approve-scripts --deny untrusted-package
# List current approvals
npx npm-approve-scripts list
# Approve all currently installed packages (not recommended — audit first)
npx npm-approve-scripts --allow-all
The approved scripts list gets stored in package.json under a
new field, making it reproducible across environments:
{
"name": "my-project",
"scripts": {
"build": "next build",
"start": "next start"
},
"approvedScripts": {
"approve": [
"[email protected].*",
"[email protected].*",
"@swc/core@1.*"
],
"deny": []
}
}
Version ranges follow semver patterns. Be specific about ranges — approving
[email protected].* rather than esbuild@* is safer.
Before v12 ships, test your pipeline with the future defaults:
# Simulate v12 behavior on npm 11
npm install --install-strategy=manual --allow-remote=none --allow-git=none
# If everything works, you're ready for v12
# If you see errors, review and approve the affected packages
For a full walkthrough of npm package safety evaluation before adding new dependencies, see the npm Package Evaluation Guide.
CI environments need special attention because they often run clean installs and depend on postinstall hooks for build steps. Here's how to prepare:
# GitHub Actions example — ready for npm v12
jobs:
build:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: |
npm ci
# If you need to allow remote tarballs temporarily:
# npm ci --allow-remote=all
- name: Build
run: npm run build
Key CI considerations:
approvedScripts field to your repo — CI reads it automatically--install-strategy=manual --allow-remote=none --allow-git=none before v12 shipsIf you maintain an npm package with install scripts, here's how to prepare:
Move install-time logic to lifecycle scripts that don't run on npm install:
{
"scripts": {
"postinstall": "node ./setup.mjs", // Won't run in v12
"prepare": "node ./build.mjs", // Runs on 'npm publish'
"prepublishOnly": "npm run build", // Runs before publish
"rebuild": "node-gyp rebuild" // Explicit, not automatic
}
}
Instead of compiling native code during install, ship prebuilt binaries for major platforms. Projects like esbuild (GOOS/GOARCH binaries) and sharp (prebuild-install) are good examples.
Monorepos using npm workspaces face additional complexity because each workspace may have different script requirements:
# Root package.json (workspaces root)
{
"workspaces": ["packages/*"],
"approvedScripts": {
"approve": [
"[email protected].*",
"typescript@5.*"
]
}
}
# Each workspace's approvedScripts merges with the root.
# To check all scripts across workspaces:
npm query .scripts --workspaces
Besides install scripts, the allow-remote and allow-git defaults are equally important to understand:
# Allow all remote tarballs (restores current behavior)
npm install --allow-remote=all
# Allow specific remote sources (future feature)
echo 'remote-allowlist=["https://github.com/my-org/*"]' >> .npmrc
# Allow all Git dependencies (restores current behavior)
npm install --allow-git=all
# .npmrc equivalents
echo 'allow-remote=all' >> .npmrc
echo 'allow-git=all' >> .npmrc
These flags accept all (allow everything) or none
(block everything). Future versions may support granular allowlists. For
now, test your project with both set to none and see what breaks.
The clock is ticking on npm v12. Every project that uses npm will be affected. The good news: you can prepare today by upgrading to npm 11.16.0+, running the audit commands above, and configuring your allowlist before the official release.
Start with npm query .scripts — it takes five seconds and tells
you how much work is ahead. For most projects, the migration takes 15-30 minutes.
The alternative is a broken CI pipeline in July.
Building a new Node.js project? I help teams set up secure, future-proof JavaScript architectures. Get in touch for a consultation.
I help teams audit their npm setup, configure allowlists, and prepare for npm v12. Free initial consultation.