The npm registry publishes thousands of new packages every day. The NVD publishes dozens of new CVEs every day. The intersection of "packages you depend on" and "packages with new CVEs" keeps growing — whether or not anyone on your team is watching.
The dependency security timeline problem
Here's the typical lifecycle of a dependency vulnerability:
- Vulnerability is discovered by a researcher
- Researcher reports to the package maintainer (coordinated disclosure)
- Maintainer releases a patched version
- CVE is published to NVD and OSV databases
- Your scanner finds it — if you run a scan
- Your team notices the finding — if someone checks
- Dependency is updated — if anyone has time
Steps 5–7 are where vulnerability management breaks down in most organisations. The CVE exists. The patch exists. Nothing happens until a breach or a quarterly audit.
What OSV covers
The Open Source Vulnerability (OSV) database is the best open source CVE feed for developers. It covers:
- npm (JavaScript/Node.js)
- PyPI (Python)
- Cargo (Rust)
- Go modules
- Maven (Java)
- RubyGems
- NuGet (.NET)
- GitHub Actions
OSV records include the affected version ranges, the fixed version, the CVSS score, and links to the original advisory and patch. BattleTest queries OSV on every PR for every changed or added dependency.
Two scanning modes
PR-time scanning (reactive)
When a developer opens a PR that updates a dependency, the scanner checks the new version and all transitive dependencies against OSV. If [email protected] has a known RCE in the version being added, it's flagged before the PR merges.
This is the most important check — it prevents the vulnerability from entering your codebase.
Scheduled scanning (proactive)
New CVEs are published against existing versions of packages. A dependency you added six months ago at a clean version may have had a vulnerability disclosed since then. Scheduled scanning checks your current lockfile against OSV periodically and alerts when the threat landscape changes.
Multi-ecosystem support matters
Most apps aren't single-language. A Python backend with a JavaScript frontend, a Rust CLI tool, and a Java microservice may all be in the same repository. A scanner that only handles package.json misses the other three ecosystems.
BattleTest parses all of:
package.json/package-lock.json/yarn.lockrequirements.txt/Pipfile/pyproject.tomlCargo.toml/Cargo.lockgo.modpom.xml/build.gradle
Severity-based triage
Not all CVEs are equal. A CVSS 9.8 RCE in a package you use in a network-accessible handler is critical. A CVSS 4.3 DoS in a package only used in your test suite is informational. Automated scanners that alert identically on both produce alert fatigue.
The right approach: automatically block on CRITICAL CVEs in dependencies used in production code paths, alert-and-track on HIGH, and batch-report MEDIUM and LOW in a weekly digest.
Auto-fix PRs
For many CVEs, the fix is a simple version bump: [email protected] → [email protected]. When Dependabot or Renovate is configured, these PRs can open automatically. The security review then confirms the bumped version is actually clean before the PR merges.