npm v12 Just Shipped the Biggest Security Change in Its History: What Breaks and How to Fix It
npm v12 shipped quietly on July 8, 2026. No confetti, no keynote. Just three defaults flipped, the kind of change that’s easy to miss until your CI pipeline breaks in a way that makes no sense.
This is the most significant security redesign in npm’s sixteen year history, and if your team runs npm install anywhere in your build process, it affects you whether you’ve noticed yet or not.
The Year That Forced This
This wasn’t a routine update. It was the answer to a year that kept getting worse.
- September 2025 — the Shai-Hulud worm turned npm into a self-spreading attack vector for the first time, automating the compromise and redistribution of malicious packages at a scale the ecosystem hadn’t seen before.
- March 2026 — North Korean state-linked attackers compromised Axios, one of the most widely used HTTP libraries in the JavaScript ecosystem.
- June 2026 — the Miasma worm hit Red Hat’s own official npm namespace, compromising 32 packages, then returned two days later with a second technique and compromised 57 more, all within a two hour window.
- July 2026 — within the same week, the AsyncAPI packages and the Jscrambler package were both compromised through separate supply chain attacks, one of them a CI/CD pipeline compromise sophisticated enough to carry legitimate provenance attestations.
Sonatype’s 2026 supply chain report counted nearly 455,000 malicious open source packages published in 2025 alone, pushing the cumulative total past 1.2 million, a 75 percent jump year over year. At some point, the ecosystem had to close the door that all of this was walking through.
What Actually Changed in npm v12
npm v12 flips three defaults that have quietly existed since npm began:
✅ Install scripts, off by default. preinstall, install, and postinstall scripts from dependencies no longer run automatically. You approve them explicitly with npm approve-scripts, or block them with npm deny-scripts.
✅ Git dependencies, blocked by default. Direct or transitive Git dependencies won’t resolve unless you pass –allow-git.
✅ Remote sources, blocked by default. Remote tarball URLs require –allow-remote.
There’s a fourth, quieter fix worth knowing: what security researchers nicknamed the “Phantom Gyp” technique, where a package could trigger an implicit native build step through a small binding.gyp file, no lifecycle script required at all. v12 closes that path too.
For over a decade, any package in your dependency tree, including ones several levels deep that nobody on your team ever chose directly, could run arbitrary code the moment it landed in node_modules. That’s the assumption npm v12 finally removes.
The Silent Failure
Here’s the part that catches experienced teams off guard: under npm v12, an unapproved script doesn’t fail your install. It gets skipped, npm prints a warning, and the install still succeeds.
That sounds reassuring until you realize what it means in practice. Native modules like bcrypt, sharp, or esbuild depend on that install-time compilation step.
Skip it silently, and your build finishes green, exit code 0, while those modules were never actually compiled. The failure doesn’t show up until something tries to use them, often well after the deploy.
CI pipelines specifically should turn on strict-allow-scripts, which converts that soft skip into a hard, visible error. The default behavior is built for individual developers who don’t want their local installs breaking. It is not what you want guarding a production pipeline.
An npm v12 Migration Checklist
✅ Update to npm 11.16.0 or newer first. The warnings for everything v12 will enforce are already visible there, before anything actually breaks.
✅ Run npm approve-scripts for the native modules and build tools you genuinely trust, then npm deny-scripts for the rest.
✅ Commit the resulting allowlist in package.json. It becomes a reviewable, version-controlled decision instead of an invisible default.
✅ If your project depends on internal Git dependencies or monorepo branch references, the durable fix is migrating to a real package registry, GitHub Packages, Nexus, or Artifactory, rather than routinely passing –allow-remote as a blanket override.
✅ Turn on strict-allow-scripts in CI specifically, so a skipped native build fails loudly instead of shipping quietly broken.
Most teams can get through this in about fifteen minutes. The outage it prevents tends to cost a lot more than that.
What This Doesn’t Fix
Worth saying plainly, since overstating a fix is its own kind of risk: npm v12 closes the install-script and implicit-build entry points specifically. It would not have stopped every attack from the past year.
The September 2025 chalk and debug package hijack shipped malicious code directly in the package body, not through an install script, and an allowlist for scripts doesn’t touch that vector at all.
Blocking install-time execution by default is a real, meaningful fix for the most common entry point of the last year’s attacks. It isn’t the end of the conversation on supply chain risk, and treating it that way is how teams get complacent again in six months.
Where We Fit In
We build across React, Next.js, Node, and React Native for founders and businesses, which means npm install runs constantly across our own pipelines and our clients’. This is exactly the kind of check we run before it becomes a problem instead of after.
If you’re not sure whether your CI is quietly sitting on the old defaults, that’s a short, concrete thing to check, not a big project. Happy to help you look.

