Package Hijacking

npm Supply Chain critical Linux macOS Windows
Package hijacking occurs when an attacker gains control of a legitimate maintainer's npm publishing authority and publishes trojanized versions of popular packages. Because npm packages often have deep transitive dependency trees, compromising one widely used package can affect many downstream projects. In March 2026, malicious Axios versions 1.14.1 and 0.30.4 reached an ecosystem with more than 70 million weekly downloads according to Microsoft. Microsoft attributed the supporting infrastructure and compromise to Sapphire Sleet. [1][2][3][4][5][6][7][8]

Prerequisites

  • Compromised npm maintainer credentials via phishing, credential stuffing, or token leakage
  • Target package must have a significant number of downstream dependents to maximize blast radius
[1][2][3][4][5][6][7][8]

Attack Scenarios

Account Takeover and Trojanized Publish

An attacker compromises a maintainer's npm account and publishes a new patch version containing a malicious dependency. A fresh resolution or dependency update can select that patch when a semver range permits it; an existing lockfile can keep the older version. In the March 2026 Axios attack, the attacker changed a primary maintainer account's registered email and published two backdoored versions within a 39-minute window. npm 12 now blocks unapproved dependency install scripts by default, but this does not prevent malicious runtime code in a selected package.

[1][2][3][4][5][6][7][8]
Attacker logs in with compromised credentials and publishes
npm login --auth-type=legacy
# Using compromised credentials
npm publish
Trojanized package.json injecting a malicious dependency (as in the Axios attack)
{
  "name": "axios",
  "version": "1.14.1",
  "dependencies": {
    "plain-crypto-js": "4.2.1"
  }
}
The malicious dependency (plain-crypto-js) delivers a cross-platform RAT via its own postinstall
{
  "name": "plain-crypto-js",
  "version": "4.2.1",
  "scripts": {
    "postinstall": "node scripts/postinstall.js"
  }
}
// The postinstall script downloads and executes a platform-specific
// remote access trojan (RAT) for macOS, Windows, or Linux

Transitive Dependency Amplification

A package deep in the dependency tree is compromised. Because it is a transitive dependency of many popular frameworks, the malicious code reaches thousands of projects that never directly depend on the hijacked package and may not even be aware it exists in their dependency tree.

[1][2][3][4][5][6][7][8]
Viewing dependencies and dependents to assess blast radius
# Check a package's dependencies
PACKAGE=axios
npm view "$PACKAGE" --json | jq '.dependencies'
# To find who depends on a package, check:
# https://www.npmjs.com/browse/depended/axios
# Or use npm.anvaka.com to visualize the dependency graph

Detection

Monitor for Unexpected Version Bumps

Set up alerts for new versions of your critical dependencies. Compare published versions against the project's GitHub releases or changelog to detect unauthorized publishes.

[1][2][3][4][5][6][7][8]
npm view axios versions --json | jq '.[-5:]'

Lockfile Integrity Verification

Use npm ci instead of npm install to enforce the exact versions and integrity hashes recorded in package-lock.json. Any tampering with the published tarball will cause a checksum mismatch and fail the install.

[1][2][3][4][5][6][7][8]
npm ci

Use Registry Advisories as a Separate Signal

npm audit submits dependency information to the configured registry's audit endpoint and reports known advisories. It can identify a compromise after an advisory exists, but it is not a general detector for new malicious package behavior.

[1][2][3][4][5][6][7][8]
npm audit --audit-level=moderate

Mitigation

  • Enable two-factor authentication (2FA) on all npm maintainer accounts, especially for packages with large install bases
  • Use npm ci in CI/CD pipelines to enforce lockfile integrity and detect unexpected changes
  • Pin exact dependency versions and review all version bumps before merging
  • Monitor npm advisory feeds and subscribe to security notifications for critical dependencies
  • Use npm provenance attestations to verify that published packages were built from the expected source repository
  • On npm 12, keep dependency install scripts default-denied and approve only reviewed, version-pinned scripts
[1][2][3][4][5][6][7][8]

References