ProBackend
software infrastructure
2 hours ago7 min read

npm v12 to Require Explicit Approval for Install Scripts and Non-Registry Dependencies

GitHub announces npm v12 security overhaul: install scripts, Git dependencies, and remote URLs will require explicit approval to combat supply-chain attacks

GitHub Ends the Era of Silent Executions

GitHub is shutting it down. For years, running npm install felt like a routine click of a seatbelt, but it was actually a game of digital Russian roulette. You clone a repo, you run the command, and you expect local packages to resolve neatly. You don't think about the scripts running in the dark. That silent trust has cost the industry dearly, and GitHub has finally decided enough is enough. In a massive security overhaul scheduled for next month, the upcoming npm v12 release will block automatic code execution and non-registry dependency sources by default.

If a package wants to run a script, it'll have to ask first. No exceptions, no excuses. This isn't just a minor patch; it's a fundamental rewrite of the trust boundaries within the JavaScript ecosystem. For years, npm was built on frictionless adoption—the idea that installing code should be as fast and invisible as possible. But speed became the enemy of safety. Attackers realized they didn't need to break into build servers. They just needed to slip a malicious preinstall script into a low-level utility library that a developer might download while half-asleep on a Friday afternoon.

When npm v12 drops next month, that avenue slams shut. It's a calculated move that will disrupt thousands of active developer workflows, break legacy continuous integration pipelines, and cause a fair amount of developer outrage. Yet, it's also the most necessary security decision the npm team has made in a decade.

We have all done it. We have cloned some obscure helper tool from GitHub and run the install command without looking at its dependency tree. We trusted that the registry was keeping us safe. But a registry package manager isn't a sandbox. When you install a library, you're giving it permission to run shell scripts with the same permissions as your own user. That's a massive security gap, and npm v12 is closing it.

GitHub Ends the Era of Silent Executions

Three Critical Lockdowns in the New npm v12

The overhaul targets three key pathways that malicious actors have exploited to hijack systems. Let's break down how npm v12 handles these mechanisms.

First, install scripts are blocked by default. Under the new rules, npm install won't run preinstall, install, or postinstall scripts from dependencies unless they have been explicitly approved by the user. If you use a package that requires node-gyp to compile C++ native binaries, those triggers will be blocked. Even prepare scripts from Git dependencies, local files, and linked directories are restricted. If a package wants to run code during package resolution, it'll have to wait until you give it explicit green light.

Second, Git dependencies are blocked by default. In npm v12, you can't fetch dependencies directly from a Git repository, whether direct or transitive, without explicit permission. You might suggest that disabling scripts is enough to keep Git safe. But GitHub's security engineers found a nasty attack vector here. When npm resolves a Git dependency, a malicious actor can insert a custom .npmrc file inside that repo. This config file modifies the path of the Git executable npm uses, tricking your system into running a malicious script disguised as Git. Even if install scripts are turned off, this route allows remote code execution.

Third, remote URL dependencies are blocked by default. Dependencies installed via HTTPS tarballs or arbitrary remote links won't resolve unless you explicitly authorize them. If an external link isn't in your approved configuration, npm will refuse to pull it down. This stops attackers from hiding malicious secondary layers outside the official npm registry where scanning tools can't inspect them.

By cutting off these three automatic pipes, npm v12 moves developers into a sandbox by default. If a dependency wants to do anything besides supply static JavaScript files from the main registry, it has to get your sign-off first.

Three Critical Lockdowns in the New npm v12

Scars of the Past: Real-World Attacks That Prompted the Shift

These changes didn't happen in a vacuum. The JavaScript registry has been a primary target for supply chain actors, and the recent damage has been severe. For instance, the IronWorm campaign hit dozens of packages via compromised dependencies. Similarly, the Miasma security incident demonstrated how easily internal development tools can carry credential-stealing payloads.

Look at the eslint-config-prettier incident. Attackers hijacked the namespace to publish compromised configurations. The packages contained malicious install scripts that executed automatically upon command execution. Once active, the code searched developer hard drives for environment variables, API tokens, and private keys, uploading them to remote command-and-control servers. Developers didn't notice because the build succeeded without warnings.

We also saw the Picasso package attack targeting Toptal's open-source packages. Attackers published typosquatted versions and replaced dependency targets, tricking developers and automated environments into running unsigned scripts that gathered system info and sent it to external targets.

But the most notable driver for this upgrade is the Shai-Hulud campaign. This coordinated attack wave compromised over 600 packages in the npm registry. The threat actor shipped signed, malicious packages targeting high-profile libraries like TanStack and Mistral. Shai-Hulud relied heavily on resolving dependencies from Git sources to bypass standard security filters. They utilized custom Git environments to pull in the second stage of their payload during installation.

If npm v12's new policies had been active, every one of these campaigns would have failed at the start. The malicious scripts would have remained dormant, the unauthorized Git repositories would have been blocked, and the remote tarballs would have been ignored.

A Clear Migration Path to Upgrade Without Breaking Builds

If you blindly upgrade your projects to npm v12 next month, you will break your local environments and crash your continuous integration pipelines. Many large-scale projects rely heavily on install scripts for legitimate purposes, such as compiling system-specific bindings or configuring local assets. Fortunately, GitHub isn't dumping this change on us without a bridge.

First, upgrade your local setups and build servers to npm 11.16.0 or newer. This version is designed specifically to prepare you for the transition. It doesn't block any scripts or remote sources yet, but it displays clear warnings for every single behavior that will break in version 12.

When you install your packages with npm 11.16.0, watch the terminal output. You will see a list of deprecation warnings detailing which dependencies are attempting to execute install scripts, pull from Git repositories, or fetch remote URLs. Take note of these warnings. They represent the exact list of configurations you need to audit and approve.

If a warning flags a postinstall script that only prints an ASCII message, you can safely ignore it. If a warning flags a vital package like node-sass or bcrypt that must run its compilation routines, you must configure your project to explicitly allow them. When you make the jump to version 12, only the verified dependencies on your list will keep functioning automatically.

Developer Friction and the New Security Consensus

Let's be realistic: this change is going to cause a lot of friction. Many legacy projects have been operating for years on autopilot, and developers hate dealing with configuration updates just to get their projects running. Standard build templates, automated container images, and deployment scripts will all require manual configuration changes to approve dependencies. Some development teams might choose to lock their tools to npm v11 to avoid dealing with this.

But staying on legacy npm versions is a bad long-term plan. The security benefits of the new zero-trust installation model are too large to overlook. Supply chain threats are getting more sophisticated every day, and we can't afford to run untrusted code on dev machines. The minor friction of declaring which packages you trust is a small price to pay to stop your API credentials from being stolen.

GitHub has set up a dedicated community discussion channel for developers to share feedback and suggestions. The engineering teams are looking for ways to streamline the opt-in configurations before the release next month, so now is the time to voice your opinion. If you have ideas on how to make the verification process smoother, join the discussion and share your thoughts.

The bottom line is that the JavaScript ecosystem is finally maturing. We are moving away from the wild-west model where any downloaded dependency had full access to the underlying system. It is a painful transition, but in a world where supply chain attacks are common, it is the only way forward.

More blogs