npm v12 Disables Three Features by Default: What Changes, Why, and How to Prepare
npm v12, scheduled for July 2026, introduces three breaking changes—default‑off allowScripts, --allow-git set to none, and --allow-remote set to none—forcing developers to explicitly approve install scripts, git and remote dependencies, with detailed migration steps and security implications explained.
Ten‑year‑old CVE finally addressed
On June 9, 2026 the GitHub blog posted a changelog marked "RETIRED", which actually signals long‑standing breaking‑change handling. npm v12 is expected in July 2026, and the three breaking changes were already warned in the 11.10.0, 11.15.0, and 11.16.0 releases, giving a pre‑release window of many months.
allowScripts default off, blocking more than postinstall
The first breaking change turns allowScripts off by default. npm install no longer runs preinstall, install, or postinstall scripts unless the project explicitly permits them.
This creates a hidden pitfall: native packages that contain a binding.gyp file trigger an implicit node-gyp rebuild even without an explicit install script. Consequently, packages such as node-sass, bcrypt, and sharp have been executing code that the developer never wrote or approved.
Git, file, and link dependencies that run a prepare script are also blocked.
The new approval workflow requires running npm approve-scripts --allow-scripts-pending to list pending scripts, then either npm approve-scripts to trust them or npm deny-scripts to reject them. The decision is written to package.json and committed with the code, turning an implicit "install at will" model into an explicit consent model.
While this blocks the entry point, it does not close every path; the underlying logic can still be reached later.
allow‑git and allow‑remote also locked down
The second breaking change changes the default of --allow-git to none. Git dependencies can still override the Git executable via a .npmrc file, bypassing --ignore-scripts. This creates a separate code‑execution path independent of install scripts, meaning disabling install scripts alone is insufficient for security.
The third breaking change sets --allow-remote to none, preventing npm install from fetching packages from remote URLs (including HTTPS tarballs) unless the flag is explicitly enabled. The related flags --allow-file and --allow-directory retain their previous defaults.
Combined, these three changes shift npm’s logic from "I try to install everything for you" to "I will ask you first".
pnpm and Bun already did this; npm is catching up
Other package managers have long offered similar controls: pnpm provides an onlyBuiltDependencies allowlist, and Bun disables lifecycle scripts by default unless explicitly enabled. npm’s changes bring it in line with these approaches, albeit several years later.
Community reaction on Hacker News is mixed. Some see the change as moving the trust window from "first install" to "first run", while others note that pure web‑only JavaScript libraries lack a "first run" phase, making the change beneficial for them. A suggestion was raised to bind allowances to a specific package hash rather than the package name, highlighting the risk of future malicious versions of an already‑trusted package.
Preparation steps before upgrading
Practical migration is short:
Upgrade to npm 11.16.0 and run a normal npm install to view warnings.
Execute npm approve-scripts --allow-scripts-pending to list pending scripts.
Review each entry and run npm approve-scripts for trusted scripts or npm deny-scripts for untrusted ones. The decisions are recorded in package.json and should be committed.
For monorepos, the prepare script is often part of the release pipeline, and workspace link dependencies also trigger approvals, making the process more involved. A recommended approach is to create a CI branch using npm 11.16.0, collect all warnings, and curate an allowlist before the full upgrade; skipping this can lead to a flood of errors on upgrade day.
In Chinese teams, additional complications arise from private Git sources and native modules (e.g., puppeteer, node-sass, bcrypt, sharp), which will each hit the new checks. The handling logic for --allow-git must be baked into CI configuration rather than added ad‑hoc.
The allowlist stored in package.json also becomes a new collaboration norm: every new dependency addition now requires a review of the allowlist entry, adding extra work to PR reviews.
Finally, the article raises an open question: if a package was trusted yesterday but its maintainer account is compromised today, can the allowlist still protect you? The proposed hash‑based allowance could answer this, but npm did not adopt it in v12. Supply‑chain security has no final destination—only the next gate.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
