We Scanned 70,000 Packages Across 221 Lockfiles -- Here's What We Found
We Scanned 70,000 Packages Across 221 Lockfiles -- Here's What We Found
Last month we pointed Vekt at every lockfile across our client portfolio. 221 lockfiles. 69,419 packages. 6 ecosystems. One Rust binary and a pot of coffee.
Here's what came back.
The Setup
Vekt reads lockfiles. That's it. No agents crawling your node_modules, no background daemon phoning home. You point it at a directory, it finds every lockfile it recognizes, resolves the full dependency tree, and checks each package against OSV.dev for CVEs and MAL-* malicious package advisories.
$ vekt scan --recursive ~/projects/
Scanning... 221 lockfiles found
Ecosystems: npm (134), PyPI (41), Go (22), crates.io (12), Composer (8), RubyGems (4)
Packages resolved: 69,419
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%
Results:
Critical: 14
High: 87
Medium: 234
Low: 412
Malicious: 3
Clean: 68,669
Three malicious packages. Fourteen critical vulnerabilities. In production client code.
Nobody had run a supply chain scan on most of these projects. Ever.
npm Is Exactly as Bad as You Think
134 of our 221 lockfiles were package-lock.json or yarn.lock. That's 60% of the surface area, and it accounted for over 80% of the findings.
This tracks with the industry numbers. Sonatype's 2026 report counted 454,648 new malicious packages published to registries in 2025 alone. Over 99% of them landed on npm. The cumulative total is now 1.23 million known malicious packages across major registries.
The average npm project pulls in 79 transitive dependencies. You npm install one thing and you're trusting 79 maintainers you've never heard of. Some of those maintainers are publishing a new package every seven seconds -- the IndonesianFoods campaign pushed 150,000+ malicious packages in days.
And then there's Shai-Hulud. The first self-replicating npm worm. It compromised 1,000+ packages across two campaigns and exposed an estimated 25,000 GitHub repositories. No phishing email, no social engineering. Registry-native propagation. The worm installs itself into your package, publishes a new version under your credentials, and moves on.
npm is infrastructure for state-sponsored actors now. Lazarus Group maintained 800+ packages on the registry. This isn't script kiddies.
Your Scanner Is Lying to You
Here's the part nobody talks about: 65% of open source CVEs don't have an NVD-assigned CVSS score. When Sonatype independently scored those unscored CVEs, 46% turned out to be High or Critical.
Read that again. Nearly half of the unscored vulnerabilities -- the ones your scanner skips or marks "unknown" -- are actually serious.
NVD's median time-to-score in 2025 was 41 days. Some CVEs took a year. In the meantime, Sonatype identified 20,362 false positives and 167,286 false negatives in vulnerability databases.
So when you run npm audit and it says "0 vulnerabilities found," that might mean:
- You actually have zero vulnerabilities (unlikely)
- The vulnerabilities exist but haven't been scored yet
- The advisory data is wrong
- npm audit doesn't check for MAL-* advisories at all
$ npm audit
found 0 vulnerabilities
$ vekt scan .
Critical: 2
Malicious: 1
This is why Vekt scans against OSV.dev instead of relying solely on NVD. OSV aggregates advisories from GitHub, PyPI, RustSec, Go, and ecosystem-specific databases. It catches things NVD hasn't gotten around to yet.
Blindly trusting your scanner output is almost as dangerous as not scanning at all. The real question isn't "how many CVEs do I have?" It's "which of these vulnerabilities are actually reachable in my code?"
The AI Angle Is Worse Than You've Heard
GPT-5 hallucinated 27.8% of component versions in a study of 37,000 package recommendations. A separate academic study across 576,000 AI-generated code samples found ~20% of recommended packages didn't exist at all.
58% of those hallucinated package names were repeatable. Same prompt, same fake package name, every time.
Attackers figured this out. It's called slopsquatting: find the package names that AI models consistently hallucinate, register them on npm with malicious payloads, and wait.
In January 2026, a researcher found react-codeshift -- a package name that didn't exist but had been hallucinated by AI coding agents. A single commit of 47 AI-generated files with no human review. Before anyone claimed the name, it had propagated to 237 repositories through forks.
No attacker was involved. The AI created the vulnerability on its own.
If you're using Copilot, Cursor, or any AI coding assistant, you need to verify every dependency it suggests actually exists and is what it claims to be. Vekt's browser extension shows trust badges on npm, PyPI, and crates.io package pages -- so you can check before you install.
The Good News: Some Ecosystems Are Getting Safer
Not everything is doom. ReversingLabs found malware on PyPI declined 43% year-over-year. NuGet dropped 60%.
Why? Mandatory 2FA. Trusted publishing workflows. Attestation requirements. PyPI's investment in security controls is measurably working.
npm hasn't made those investments. The story isn't "everything is getting worse." It's that specific, boring platform-level security controls actually work -- and the biggest registry in the world hasn't implemented them.
What You Should Actually Do
If you manage client sites, run agency infrastructure, or maintain anything with a package-lock.json in production, here's the minimum:
Scan your lockfiles now. Not next sprint. Now. You can do it in one command:
# Install Vekt
curl -fsSL /blog/install.sh | sh
# Scan everything recursively
vekt scan --recursive .
# Or scan a specific lockfile
vekt scan package-lock.json
Don't chase every CVE. Focus on Critical and High severity findings first. Check if the vulnerable code path is actually reachable in your application. A critical vulnerability in a dev dependency you never ship to production is noise.
Check for malicious packages, not just vulnerabilities. npm audit doesn't flag MAL-* advisories. Most SCA tools don't either. Vekt does -- it's the difference between "this package has a bug" and "this package is actively stealing your environment variables."
Pin your dependencies. Lockfiles exist for a reason. If you're not committing your lockfile, you're letting every npm install roll the dice on what versions you get.
Audit AI-suggested dependencies. If your coding assistant suggests a package you've never heard of, check that it exists on the registry, has meaningful download numbers, and isn't three days old. The Vekt browser extension makes this a two-second check.
The Institutional Signal
OWASP Top 10 2025 elevated supply chain failures to a standalone category (A03). 50% of survey respondents ranked it their #1 concern. The 2025 Verizon DBIR found 30% of all breaches involved third-party software -- doubled from the prior year.
This isn't a niche concern anymore. SBOM mandates are going mainstream through the US Executive Order, EU Cyber Resilience Act, and PCI DSS 4.0. If you do agency or MSP work, supply chain auditing is becoming billable compliance work. Your clients' auditors are going to start asking for SBOMs.
Lockfiles are the practical SBOM. They're already in your repo. They already list every dependency with exact versions. Tools like Vekt can scan them in seconds and output structured results you can hand to a compliance team.
69,419 Packages Later
We started this scan expecting to find a few outdated jQuery versions and maybe a deprecated crypto library. We found three malicious packages in active client deployments.
The tools exist. The data exists. The scan takes less time than your CI pipeline. There's no reason not to know what's in your dependency tree.
Scan your first lockfile free on kief.dev. 50 scans a day, no signup required.
meta_title: "70,000 Packages Scanned Across 221 Lockfiles"
meta_description: "We scanned 69,419 packages across 221 lockfiles and found 3 malicious packages in production. Here's what supply chain security actually looks like."
tags: ["supply-chain-security", "vekt", "npm-security", "dependency-scanning", "sbom"]