What Free Dependency Scanners Actually Check (And What They Miss)
I'll write this post now -- heavy research brief, clear angle, Brian's voice.
What Free Dependency Scanners Actually Check (And What They Miss)
You run npm audit. It screams at you. 47 vulnerabilities. 12 critical.
You spend an hour investigating. Three of them are in dev dependencies that never ship. Eight are in transitive dependencies your code never calls. The rest require major version bumps that would break your build. You run npm audit fix --force and it downgrades React to a version from 2023.
Sound familiar? You're not alone. And the problem is worse than you think.
What these tools actually do
Every free dependency scanner does the same thing at its core: version matching against a vulnerability database.
Your lockfile says you have lodash@4.17.20. The scanner checks a database. That database says lodash@4.17.20 has CVE-2021-23337. Scanner prints a warning. That's it.
The difference between tools is which database they check and how they match packages to entries.
npm audit checks the GitHub Advisory Database (npm's subset). It only knows about npm packages.
Dependabot also uses the GitHub Advisory Database, but covers multiple ecosystems and opens PRs automatically.
Trivy and Grype pull from multiple sources -- NVD, GitHub Advisories, and ecosystem-specific databases. They also scan container images, which npm audit and Dependabot can't touch.
OWASP Dependency-Check uses NVD's CPE matching, which is where things get ugly. CPE matching is fuzzy. It matches package names to CVE entries using string similarity, not ecosystem-aware lookups. This means it flags your Mattermost REST client library for vulnerabilities that only affect the Mattermost mobile app. It routinely reports 5-10x more false positives than tools using ecosystem-specific matching.
Here's what a Trivy scan actually looks like:
$ trivy fs --scanners vuln .
2026-04-23T10:15:22.031Z INFO Number of language-specific files: 1
2026-04-23T10:15:22.031Z INFO Detecting npm vulnerabilities...
package-lock.json (npm)
=======================
Total: 4 (HIGH: 3, CRITICAL: 1)
+-----------+------------------+----------+-------------------+---------------+
| Library | Vulnerability | Severity | Installed Version | Fixed Version |
+-----------+------------------+----------+-------------------+---------------+
| braces | CVE-2024-4068 | HIGH | 3.0.2 | 3.0.3 |
| ip | CVE-2024-29415 | HIGH | 2.0.0 | 2.0.1 |
| tar | CVE-2024-28863 | HIGH | 6.1.15 | 6.2.1 |
| ws | CVE-2024-37890 | CRITICAL | 7.5.9 | 7.5.10 |
+-----------+------------------+----------+-------------------+---------------+
Clean output. Four results. Now run OWASP Dependency-Check on the same project and count how many of those 40+ findings you can actually act on.
If you're choosing a free scanner today, use Trivy or Grype. Not npm audit alone, and probably not OWASP DC unless you have someone dedicated to triaging false positives.
The false positive problem is a security problem
This isn't just annoying. It's actively dangerous.
Dan Abramov documented that 99% of npm audit warnings are false positives in typical build-tool scenarios. The tool reports every transitive path to a vulnerable package as a separate finding. Three real issues become 47 warnings. Rebecca Turner, who helped build the feature, acknowledged that npm's revenue incentives shaped the design -- inflated vulnerability counts promoted the paid registry.
Endor Labs found that up to 95% of vulnerability flags from conventional SCA tools exist in code paths your application never calls. One manufacturer scanning a single legacy product hit 26,000 flagged vulnerabilities. Most were unreachable.
This matters because alert fatigue is real. When every build screams about dozens of "critical" vulnerabilities that aren't actually exploitable, developers learn to ignore the output. When a genuinely dangerous issue shows up, it drowns in the noise.
The technical term for this gap is reachability analysis -- determining whether your code actually executes the vulnerable function. None of the free tools do it. Forrester now evaluates it as a core criterion for SCA products. GitLab got penalized in their 2024 evaluation for not having it.
This is the single biggest gap between free and paid scanners. Your free tool tells you a vulnerability exists somewhere in your dependency tree. It can't tell you whether it matters.
The thing free scanners don't check at all
Here's the real problem. Everything above is about known vulnerabilities -- packages with CVEs. But the fastest-growing threat isn't vulnerable packages. It's malicious ones.
454,648 malicious npm packages were published in 2025 alone. Over 99% of all open-source malware now targets npm. These aren't bugs. They're intentional backdoors, credential stealers, and cryptominers published by attackers.
Free dependency scanners check CVE databases. They don't detect malicious packages. There is no CVE for a brand-new typosquatting package that steals your .env file on install.
Look at what happened in just the first quarter of 2026:
Axios got compromised in March. The official package -- 100M+ weekly downloads -- was hijacked via stolen maintainer credentials. Two poisoned versions delivered a RAT and credential stealer. This wasn't a CVE. The package was legitimate on Monday, malicious on Tuesday. No scanner would have caught it pre-publication.
Trivy itself got compromised the same month. The security scanner that runs inside your CI pipeline to find vulnerabilities became the delivery mechanism for credential-stealing malware. TeamPCP hit Trivy, KICS, LiteLLM, and Telnyx through stolen publishing credentials.
Read that again. The tool you trusted to find problems became the problem.
In April, the CanisterSprawl worm hit npm, PyPI, and Docker Hub simultaneously. It harvested developer credentials and, if it found a PyPI token, jumped ecosystems entirely. Traditional scanners saw nothing. There was no CVE to match against.
Supply chain attacks increased 742% annually over three years. Open-source malware detections jumped 73% in 2025 versus 2024. And free scanners can't see any of it.
The binary gap
There's another blind spot most people don't think about.
Most scanners check source dependencies at build time. They read your package-lock.json or requirements.txt and match versions. But between your source code and the thing running in production, there's a transformation step -- compilation, linking, bundling, containerization.
A JAR file, a Docker image, a Python wheel -- these are transformed artifacts. The running application might contain dependencies the source-level scanner never saw. A compromised build plugin could inject code that doesn't appear in any lockfile.
Trivy and Grype partially address this by scanning container images directly. That's a real advantage over npm audit and Dependabot, which only see source manifests. But even container scanning has limits -- it's still doing version matching, just against a different artifact.
What this actually means for your team
Here's the honest breakdown of what free tools cover:
What free scanners catch:
[x] Known CVEs in direct dependencies
[x] Known CVEs in transitive dependencies
[x] Outdated packages (Dependabot)
[x] Container image vulnerabilities (Trivy, Grype)
[x] Basic license compliance (Trivy, OWASP DC)
[x] SBOM generation (Trivy/Syft, Grype/Syft)
What free scanners miss:
[ ] Malicious packages (typosquatting, hijacked maintainers)
[ ] Reachability analysis (is the vuln actually callable?)
[ ] Compromised build pipelines
[ ] Runtime dependency injection
[ ] Binary/artifact tampering beyond container layers
[ ] Continuous monitoring (scan at 2pm, compromise at 3pm)
55% of organizations cite budget as the top barrier to better supply chain security. Only 13% fully automate their security checks. Most teams are stuck at scan-only with no operational control.
If you're a small team, here's the practical stack:
Layer 1: Use Trivy or Grype. Not npm audit alone. They're faster, more accurate, and cover containers. Run them in CI on every PR.
# In your CI pipeline
trivy fs --exit-code 1 --severity HIGH,CRITICAL .
Layer 2: Add malware detection. This is the gap that actually scares me. Vekt scans your lockfiles against OSV.dev, which includes both CVE advisories and MAL-* malicious package advisories. It covers 12 ecosystems and 22 lockfile formats. The free tier gives you 50 scans per day.
# Scan your project for both CVEs and malicious packages
$ vekt scan .
Scanning 3 lockfiles across 2 ecosystems...
package-lock.json
CRITICAL MAL-2026-1847 node-fetch-utils@1.0.3 Credential stealer
HIGH CVE-2024-4068 braces@3.0.2 ReDoS in pattern matching
requirements.txt
No issues found.
Found 1 malicious package, 1 known vulnerability
That MAL-* advisory is something Trivy, Grype, npm audit, and Dependabot would all miss.
Layer 3: Understand the remaining risk. Even with both layers, you're catching maybe 40-50% of actual supply chain risk. You still don't have reachability analysis, runtime monitoring, or build pipeline integrity verification. Know your gaps. Don't let a clean scan give you false confidence.
The uncomfortable truth
Free dependency scanners are better than nothing. But "better than nothing" has become the enemy of actual security.
npm audit trained an entire generation of JavaScript developers to ignore security warnings. The constant flood of unfixable, irrelevant alerts created learned helplessness. When a real issue appears, it's buried in hundreds of false positives nobody reads anymore.
The industry is slowly moving from point-in-time scans to continuous verification. A clean scan at build time means nothing if a dependency gets compromised after deployment. AI code assistants are making it worse by suggesting non-existent package names that attackers then register.
The fix isn't to abandon free tools. It's to understand what they actually do -- version matching against CVE databases -- and stop pretending that's the whole picture. Layer in malware detection. Accept the gaps you can't fill yet. And for the love of everything, stop running npm audit fix --force.
meta_title: "What Free Dependency Scanners Actually Check"
meta_description: "Free scanners match versions against CVE databases. They miss malicious packages, reachability, and runtime threats. Here's what that gap looks like."
tags: ["supply-chain-security", "dependency-scanning", "vekt", "npm-security", "open-source-security"]