Type npm install and, until earlier this month, you were also signing a blank check. Every package in your dependency tree, including the ones four or five levels down that you never chose and have almost certainly never read, could run shell commands on your machine the instant the install finished. No prompt. No warning. Just execution, with whatever permissions the person running the install happened to have.
Most developers never thought about this. It was simply how npm install worked, from the tool's earliest days.
Attackers thought about it constantly.
On July 8, 2026, GitHub shipped npm v12 and shut that door. Tech Times and other outlets covering the release called it the most significant security redesign in the package manager's 16-year history. For the first time, running npm install does not automatically hand code-execution rights to every dependency in the tree. It asks first.
The change is already breaking builds. Teams that skipped the migration warnings are finding out why.
The Default That Just Flipped
npm v12 does not add a new security feature so much as it removes an old assumption. According to GitHub's own changelog for the release, three behaviors that used to run automatically now require explicit opt-in.
The first: install, preinstall, and postinstall scripts, the lifecycle hooks a package can define to run arbitrary code during installation, no longer execute unless the package is explicitly approved. That includes native addons. A package that ships a binding.gyp file, signaling that it needs compilation, used to trigger an automatic node-gyp rebuild even when the package declared no install script at all. npm v12 blocks that implicit build exactly as it blocks a declared one.
The second: Git dependencies, whether a project depends on them directly or picks them up several layers down, no longer resolve unless the install runs with --allow-git. GitHub's changelog notes this closes a specific workaround, in which a malicious Git dependency's own .npmrc file could override the path to the system's Git executable and achieve code execution even on projects that had already turned on the older --ignore-scripts protection.
The third: dependencies fetched from remote URLs, such as HTTPS tarballs, no longer resolve without --allow-remote. Two related flags, --allow-file and --allow-directory, are not changing.
| Behavior | Before npm v12 | After npm v12 |
|---|---|---|
Lifecycle scripts (preinstall, install, postinstall) | Ran automatically for every dependency | Blocked unless approved with npm approve-scripts |
Implicit native builds (packages with binding.gyp) | Ran automatically, even with no declared script | Blocked, same as any other lifecycle script |
| Git dependencies (direct or transitive) | Resolved automatically | Blocked unless installed with --allow-git |
| Remote URL and tarball dependencies | Resolved automatically | Blocked unless installed with --allow-remote |
None of this arrived without warning. The --allow-git default was previously announced on February 18, 2026, and available starting in npm 11.10.0. The --allow-remote flag arrived in npm 11.15.0. Starting with npm 11.16.0, any install that would break under v12 has surfaced an advisory warning instead of silently continuing, giving teams a runway before enforcement began.
Two Attacks in Four Months
GitHub's changelog does not tie the release to any single incident by name. The timing is hard to miss regardless.
In March 2026, attackers linked to the North Korean threat group Sapphire Sleet hijacked a maintainer account for Axios, the HTTP client library that gets roughly 100 million downloads a week, and shipped malicious versions built around a postinstall hook. The fallout stretched well beyond the library itself, far enough to reach OpenAI's own macOS code-signing infrastructure.
In June, the same group compromised 144 packages inside the Mastra AI framework's npm scope in a single automated run that took roughly 88 minutes, again through a postinstall hook, according to Microsoft security researchers who later attributed the attack to North Korea.
Both incidents depended on the exact default npm v12 now turns off. Had v12's rules already been in place, neither compromised package could have run its payload in a project that had not explicitly approved it, no matter how convincing the hijacked release looked.
Axios and Mastra AI also were not isolated. They landed inside a longer run of worm-driven npm compromises through 2025 and 2026, including one that hijacked 32 of Red Hat's own npm packages by exploiting a trusted-publishing pipeline rather than a postinstall hook at all. By the time v12 shipped, npm was the last major JavaScript package manager still granting install-time execution automatically. pnpm turned it off by default in version 10. Yarn Berry and Bun already blocked lifecycle scripts too.
What to Do Before Your Build Breaks
GitHub's own migration guidance is not complicated, but it requires action before the upgrade, not after a failed deploy.
- Upgrade to npm 11.16.0 or later and run a normal
npm install. Anything v12 would block already shows up as a warning rather than a failure. - Run
npm approve-scripts --allow-scripts-pendingto generate the full list of dependencies whose scripts, Git sources, or remote tarballs would stop working under v12. - Review that list. Approve the packages that genuinely need install-time execution with
npm approve-scripts, and block everything else explicitly withnpm deny-scripts. - Commit the resulting allowlist in
package.json. It is meant to be a versioned, reviewable artifact, not a setting re-decided on every developer's laptop. - If a project has a real reason to install from Git or a remote tarball, add
--allow-gitor--allow-remotedeliberately, rather than reaching for them the first time a build fails.
Monorepos need a specific note: the allowlist is scoped per workspace, so approving a package at the repository root does not carry over to a nested package with the same dependency. Each workspace needs its own review.
Not a Silver Bullet
Not everyone believes npm v12 solves the problem it targets, and the sharpest version of that argument comes from inside the Node.js project itself.
Ulises Gascon, the Node.js AI Security Engineer in Residence and the primary contact for the OpenJS Foundation's CNA, wrote in a NodeSource post that npm v12 "is a change I have wanted for years, and on its own it is not going to save you." His point: npm v12 removes a trigger, not a capability. Running npm install never actually loads a package's own code; it downloads the package and runs its lifecycle scripts. The package's ordinary JavaScript, the part that does the real work, only runs later, the first time an application imports it, and nothing about v12 touches that moment.
Moshe Siman Tov Bustan, a security researcher at OX Security, raised a related point in comments reported by Cybernews. "Account takeover remains an open wound," he said. "Once an actor controls a legitimate maintainer's credentials, no amount of install-script blocking helps, because the malicious code ships as a trusted, signed release."
A third concern is more behavioral than technical. Paul McCarty, a vulnerability researcher who publishes as Open Source Malware, warned that the allowlist model's biggest risk is what happens when it becomes friction instead of protection. "When the choice is 'this builds' and 'this is less prone to malware,' the former will always win," he wrote, predicting that many teams will approve dependencies in bulk just to silence the warnings, recreating the old blanket-trust default in a form that is harder to audit, not easier.
The Bottom Line
For 16 years, running npm install meant trusting every package in a dependency tree to behave, with no way to say no in advance. npm v12 replaces that blank trust with a written record: a specific list of which packages get to run code at install time, checked into source control and reviewed like any other change to a codebase.
That is a genuine fix to a problem that fed a year of increasingly automated supply chain attacks. It is not the end of the problem. A compromised maintainer account can still ship malicious code that runs the moment an application imports it, no install script required, and npm v12's allowlist has nothing to say about that. Isaac Evans, founder and CEO of the security firm Semgrep, told Infosecurity Magazine he expects attackers to respond by pushing up a layer, toward private registries like Artifactory and Nexus that npm's defaults never covered to begin with.
The tool got harder to weaponize through installation. Whether that turns out to be enough depends on how many teams actually read the list of packages they just approved, rather than clicking through it to make the warnings stop.
Sources
- Upcoming breaking changes for npm v12 — GitHub Changelog, June 9, 2026
- GitHub to Update npm to Thwart Software Supply Chain Attacks — Infosecurity Magazine, June 12, 2026
- npm v12 Security Overhaul Blocks Install Scripts by Default: July Deadline for CI Migration — Tech Times, June 13, 2026
- Blocking Install Scripts Is Not a Silver Bullet — NodeSource, June 19, 2026
- NPM receiving major security overhaul in July, but some security pros say it's not enough — Cybernews, July 1, 2026
- npm install-time security and GAT bypass2fa deprecation — GitHub Changelog, July 8, 2026
- npm v12 Ships This Month, Blocking Install Scripts That Enabled Year of Supply Chain Attacks — Tech Times, July 8, 2026
- npm 12 Disables Install Scripts by Default to Reduce Supply Chain Risk — The Hacker News, July 9, 2026