The Dependency You Already Trust Is the One That Gets You - VibeDoctor 
← All Articles 📦 Dependency Vulnerabilities Critical

The Dependency You Already Trust Is the One That Gets You

axios served a RAT for three hours. 142 @mastra packages were republished in 88 minutes. Account takeover, not typosquatting, is the 2026 npm threat.

DEP-008 DEP-009 SEC-014

Quick Answer

The npm threat most people defend against is typosquatting - a fake package with a name close to a real one. The attacks that landed in 2026 were subtler: real packages, real maintainer accounts, compromised, with a typosquatted dependency injected underneath. On 31 March 2026 a hijacked maintainer account published two malicious releases of axios - over 100 million downloads a week - each pulling in a cross-platform RAT, for about three hours. On 17 June 2026 a hijacked contributor account republished roughly 142 packages across the @mastra scope in an 88-minute automated campaign. Careful package selection defends against neither. Pinned versions and a committed lockfile do.

The Threat Model Most People Have Is Out Of Date

Ask a developer how they avoid malicious npm packages and you will usually hear some version of: check the download count, check the GitHub stars, avoid anything that looks misspelled.

That is a defence against typosquatting - reqeusts instead of requests, lodahs instead of lodash. It is a real category, and it is adjacent to the slopsquatting problem where an AI assistant hallucinates a package name and an attacker registers it.

It provides no protection whatsoever against the 2026 pattern, where the package is the one you meant to install, from the maintainer you meant to trust, and the malicious code arrived in a new version of it.

What Actually Happened In 2026

IncidentDateMechanismWindow
axios (100M+ downloads/week, 174k dependents)31 March 2026Hijacked maintainer account publishes 1.14.1 and 0.30.4, each pulling typosquatted plain-crypto-js~3 hours (00:21-03:25 UTC)
@mastra scope, ~142 packages (~8M downloads/week)17 June 2026Hijacked contributor account swaps dayjs for attacker-controlled easy-day-js88 minutes (01:12-02:39 UTC)

The axios case is the clearest illustration. The attacker reached the lead maintainer's machine through social engineering, took the npm credentials, and published [email protected] and [email protected]. Neither release contained obvious malware. Each simply added a dependency - plain-crypto-js, a typosquat of crypto-js - which downloaded and executed a cross-platform RAT on install. That dependency had been pre-staged 18 hours earlier. Not a fake package: axios, the HTTP client sitting in a large share of Node projects, including most AI-generated ones, because it is what assistants reach for by default.

@mastra followed the same shape three months later. A forgotten contributor account was hijacked and used to republish roughly 142 packages across the scope, swapping dayjs for an attacker-controlled easy-day-js. The first version of that package was clean; a later one added a post-install hook that disabled TLS verification, fetched a second stage from a raw IP address and ran a cross-platform cryptocurrency stealer. Snyk and Orca both link the tradecraft to Sapphire Sleet, also tracked as BlueNoroff - a North Korean group specialising in developer-targeted supply chain operations. This is not a hobbyist threat surface.

Note what the two have in common: the compromised package itself looked fine. The malice sat one level down, in a dependency it pulled in. Reading the diff of axios would not have saved you.

The background numbers are worth holding alongside the incidents. Sonatype's 2026 report puts the cumulative total of known and blocked malware at over 1.233 million packages across npm, PyPI, Maven Central, NuGet and Hugging Face, with more than 454,600 new malicious packages identified in 2025. Over 99% of open source malware occurred on npm.

Why This Hits AI-Generated Projects Harder

Two structural reasons, neither of which is about the code being bad.

First, dependency count. Assistants add packages freely - a date helper here, a validation library there - and a Bolt or Lovable scaffold routinely ships with 40 to 60 direct dependencies before you have written a feature. Each one is an account that can be compromised.

Second, and more important, version ranges. AI-generated package.json files are full of carets, and a caret means "give me the newest thing that is probably compatible". That is precisely the mechanism both 2026 attacks relied on: they did not need you to install anything new, only to install again during their window.

// ❌ BAD - typical AI-generated package.json
{
  "dependencies": {
    "axios": "^1.7.2",          // any 1.x - including the malicious 3-hour release
    "express": "^4.19.2",
    "zod": "^3.23.8",
    "date-fns": "latest",       // whatever is newest, whenever you install
    "lodash": "*"               // literally anything
  }
}
// No package-lock.json committed - CI resolves fresh on every build

With this file, a npm install in CI during the axios window pulls the trojan. You changed nothing. You deployed on a Tuesday like always.

How To Fix It

The defences are unglamorous and effective. None of them require you to evaluate packages more carefully.

// ✅ GOOD - exact versions, lockfile committed, CI installs from the lock
{
  "dependencies": {
    "axios": "1.7.2",           // exact - a new release cannot arrive silently
    "express": "4.19.2",
    "zod": "3.23.8",
    "date-fns": "3.6.0",
    "lodash": "4.17.21"
  }
}

// package-lock.json IS committed, and CI uses:
//   npm ci          (installs exactly the lockfile, fails if it disagrees)
// not:
//   npm install     (free to resolve something newer)
  1. Commit the lockfile. It records exact resolved versions and integrity hashes. An attacker republishing a version cannot match the recorded hash. This is the single highest-value change.
  2. Use npm ci in CI, never npm install. ci installs precisely what the lockfile says and fails if the manifest disagrees. install is permitted to resolve something newer - which is the entire attack path.
  3. Drop * and latest entirely. They mean "install whatever is published at the moment CI happens to run".
  4. Delay adoption of brand-new versions. Both 2026 windows were measured in hours to minutes. A cooling-off period on non-security upgrades removes most of the exposure.
  5. Know your CVE surface. Tools like VibeDoctor's Vibe Check (vibedoctor.io) automatically scan your codebase for loose version ranges, missing lockfiles and known-vulnerable dependencies, and flag specific file paths and line numbers. Free to sign up.

What A Lockfile Does And Does Not Buy You

Worth being precise, because lockfiles get oversold.

A committed lockfile with integrity hashes means an install reproduces exactly what you previously resolved. If a version you already depend on is republished with malicious content, the hash no longer matches and the install fails loudly. That is the protection, and it is substantial.

It does not protect you when you deliberately upgrade into a compromised version, and it does not help if you regenerate the lockfile during the attack window. It narrows the exposure from "every install" to "installs where you chose to move", which is a small, deliberate, reviewable set of moments.

That is the whole game here: converting a continuous, invisible risk into an occasional, visible decision.

FAQ

Should I stop using axios?

No. The package was the victim, not the villain, and the compromise was resolved. Any widely-used package is a target precisely because it is widely used - switching to an alternative just changes which maintainer account you are trusting.

Does pinning exact versions leave me on vulnerable releases?

Only if you never upgrade. Pinning changes upgrades from automatic to deliberate - you still apply security patches, you just do it as a reviewed change rather than as a side effect of an unrelated deploy.

Is Yarn, pnpm or bun safer than npm?

The registry is the same, so the exposure is the same. What matters is whether your lockfile is committed and whether CI installs from it in frozen mode - npm ci, yarn --frozen-lockfile, pnpm install --frozen-lockfile. The tool matters far less than the flag.

How would I even know if I was hit?

Both windows are published to the minute - axios 00:21-03:25 UTC on 31 March, @mastra 01:12-02:39 UTC on 17 June. Reconstruct whether a build ran inside one; CI logs give you install timestamps. If a lockfile was regenerated around that time, treat any credential reachable from the build environment as exposed and rotate it.

My app has 60 dependencies. Is that a problem by itself?

It is a surface-area problem rather than a vulnerability. Every direct dependency is a maintainer account that can be compromised, and transitive dependencies multiply that. Pruning what you do not use is worth doing, but pinning and lockfiles matter more.

Sources

Diagnose your codebase - free

VibeDoctor checks for DEP-008, DEP-009, SEC-014 and 148 other issues across 21 diagnostic areas - security, performance, code quality, and more.

SCAN MY APP →
← Back to all articles View all 149+ checks →