Lesson 5: Build Your Own npm Vulnerability Scanner
Introduction
In Lesson 4, we surveyed the tools available for npm security. Now we're going to build one ourselves. By the end of this lesson, you'll have a working vulnerability scanner that uses the deps.dev API to check your dependencies against multiple vulnerability databases, track package freshness, and generate actionable reports.
Building your own scanner teaches you how security tools work under the hood, and gives you a customizable foundation you can extend with your own organization's specific requirements.
What We're Building
Our scanner will:
- Parse
package.jsonto extract all dependencies - Query the deps.dev API for each package to get vulnerability data
- Check release dates to identify stale dependencies
- Generate a comprehensive report (console + JSON)
- Return an exit code suitable for CI/CD integration (non-zero if vulnerabilities found)
Why deps.dev?
The deps.dev API (by Google) aggregates data from multiple sources including npm, GitHub Advisory Database, and OSV. Unlike npm's built-in audit which only checks npm's own database, deps.dev provides cross-database coverage. It's free, requires no authentication, and supports multiple ecosystems.
Step 1: Project Setup
Create a new directory for our scanner (or add it to an existing project):
Create a scripts directory:
Step 2: The Scanner Script
Create scripts/dependency-scanner.js:
Step 3: Wire It Up
Add the scanner to your package.json scripts:
Run It
Example Output
Step 4: Understanding the JSON Report
The scanner saves a dependency-scan.json file that can be consumed by other tools, dashboards, or CI/CD systems:
Step 5: CI/CD Integration
GitHub Actions
The scanner exits with code 1 when vulnerabilities are found, which causes the CI job to fail — preventing merges with known vulnerable dependencies.
Step 6: Extending the Scanner
Our base scanner is functional, but here are enhancements you can add. For inspiration, consider the approach taken by NPQ, a CLI tool built by Liran Tal (Snyk) that checks package health before installation:
"NPQ actually checks the package health score. It checks if it has vulnerabilities, when was it last published, maybe like seven hours ago... There's a bunch of stuff that it does, like heuristics to check that the package is kind of healthy, also security-wise. And if it does find issues, it asks you, do you want to continue?"
— Liran Tal (Señors @ Scale podcast)
This same heuristic mindset — checking recency, health signals, and known risks — is what makes a custom scanner valuable beyond what npm audit provides.
Enhancement 1: Check for Known Compromised Versions
Add a hardcoded list of known-compromised package versions (like the September 2025 attack):
Enhancement 2: Slack/Email Notifications
Enhancement 3: Lockfile Analysis
Parse package-lock.json to scan the actual resolved versions (including transitive dependencies) rather than just the ranges in package.json:
Combining with npm audit
The most effective setup uses both tools together:
This gives you:
- npm audit: Known CVEs in npm's database, with fix suggestions
- deps.dev scanner: Cross-database vulnerabilities, package freshness, stale dependency detection
Key Takeaways
- Building a custom scanner helps you understand how security tools work and gives you a foundation you can customize.
- The deps.dev API provides free, comprehensive vulnerability data from multiple databases.
- Tracking package freshness helps identify abandoned dependencies that may never receive security patches.
- CI/CD integration ensures every build is checked — manual scanning doesn't scale.
- The JSON report format allows integration with dashboards, alerting systems, and other tools.
- Combine your custom scanner with npm audit for the broadest coverage.
What's Next
In Lesson 6, we'll add a critical security layer: containers. You'll learn how to use Docker and Dev Containers to isolate your development environment so a malicious package can't reach your SSH keys, cloud credentials, or other projects. We'll cover multi-stage production builds, network-restricted installs, container image scanning, and a complete project template.