Skip to content

Back to the catalog

npm v12 delivers one of the biggest security improvements in years
aikido.devarticle

npm v12 delivers one of the biggest security improvements in years

Aikido details npm v12's plan (landing July 2026, previewed in 11.16.0) to stop running preinstall/install/postinstall lifecycle scripts by default, requiring an explicit allowlist via npm approve-scripts/npm deny-scripts, plus gating Git and remote-URL dependency resolution behind --allow-git/--allow-remote and treating binding.gyp node-gyp builds as scripts requiring approval. It ties the change to a wave of postinstall-based supply-chain attacks (Nx s1ngularity, Shai-Hulud, axios hijack, Mini Shai-Hulud) and recommends upgrading to 11.16.0+ and using tools like Safe Chain to vet packages before install.

TL;DR npm v12 will disable automatic postinstall/install scripts by default, closing the biggest recent npm supply-chain attack vector.
Document

What to do

The page gives a concrete migration sequence you can start before v12 lands July 2026, since all three changes already ship in npm 11.16.0 behind warnings.

Preview what the new default would block, approve trusted packages, and commit the result:

npm approve-scripts --allow-scripts-pending

Anything you don't approve stops running when v12 flips the default. The page stresses checking this deliberately: many legitimate packages rely on install scripts for native builds and setup, so a clean-looking install today can break once approval becomes mandatory.

Two of the flags don't require waiting for 11.16.0. Per the page, --allow-git is available now and --allow-remote has shipped since 11.15.0, so you can lock down Git and remote-URL dependency resolution immediately:

  • --allow-git — closes a path where a Git dependency's .npmrc could override the Git executable and run code even with --ignore-scripts set. This is worth noting: --ignore-scripts alone does not close it.
  • --allow-remote — blocks https-tarball and other remote-URL dependencies, where an attacker controlling the external URL could swap the payload at any time.

The binding.gyp gap this closes

Beyond the named lifecycle scripts, the page flags a quieter execution path the summary states but does not explain: a package with a completely clean package.json (no scripts field) can still execute code if it ships a binding.gyp, because npm runs an implicit node-gyp rebuild during install. v12 treats that build as a declared script, so it too requires allowlist approval. If you audit only the scripts field, you miss this.

How the attacks actually run

The exploit mechanism, per the page, explains why the allowlist helps even for packages you never import:

flowchart TD
  A[Maintainer account or publish token stolen] --> B[Poisoned version published with postinstall added]
  B --> C[Victim runs npm install]
  C --> D{Package on committed allowlist?}
  D -->|No, v12 default| E[Sits inert in node_modules]
  D -->|Yes / pre-v12| F[Script runs as user: fingerprint, fetch payload, steal tokens/SSH keys, self-delete]

You do not have to use or import the malicious package — running npm install while it is infected is enough. Under v12, an unapproved poisoned package sits as inert files in node_modules.

Caveats

  • Optional layer: the page also recommends Safe Chain (Aikido's free wrapper for npm/npx/yarn) that scans packages pre-install and enforces a waiting period on new versions — this is vendor tooling, not part of npm.
  • The named incidents include events dated after this document's context (axios hijack March 2026, Mini Shai-Hulud May 2026); the latter is described as the first npm worm to publish malware carrying valid build provenance, meaning provenance signing alone would not have flagged it.

Organisations named here

  • Shai-Hulud

Technologies named here

  • npm approve-scripts
  • npm
  • Nx
  • npm deny-scripts
  • axios
  • --allow-git flag
  • --allow-remote flag
  • Zapier, ENS, PostHog, Postman, AsyncAPI packages
  • --ignore-scripts flag
  • TanStack, UiPath, Mistral AI packages
  • Safe Chain
  • Laravel-Lang
  • Red Hat package
  • TruffleHog
  • Composer native malware filtering
  • Composer
  • Node.js

Techniques named here

  • Malicious postinstall/preinstall/install lifecycle scripts
  • Maintainer account/publish token compromise
  • Implicit node-gyp rebuild via binding.gyp
  • Git dependency .npmrc override of git executable
  • Remote-URL dependency payload swap
  • Self-replicating worm propagation
  • Build provenance forgery/abuse
  • Autoloader-based credential stealer execution

Threat actors named here

  • Nx s1ngularity
  • Shai-Hulud
  • axios hijack
  • Mini Shai-Hulud
  • Laravel-Lang credential stealer campaign
  • Red Hat package postinstall attack