Expand description
Vulnerability auditing for a parsed package-lock.json — npm audit, pure Rust.
The packages a lockfile pins (crate::sbom::components) are checked against one or more
advisory sources behind a small AdvisorySource trait, and the hits are distilled into an
AuditReport: which installed components are vulnerable, to which advisories, at what severity.
Two sources ship in v1, both keyless and queried by default:
npm::NpmRegistrySource— npm’s native bulk-advisory endpoint (also honours a custom mirror).osv::OsvSource— the OSV (osv.dev) database, with structured affected-version ranges.
The seam is deliberately open: a new source is one impl AdvisorySource plus one line where the
active sources are assembled (e.g. a future, feature-gated, API-key’d Snyk source).
Everything except the sources’ network calls is pure and unit-tested: dedup_advisories
collapses the same vulnerability reported by several sources, and build_report keeps only the
advisories whose vulnerable range actually contains the installed version — the guard against
the npm endpoint’s range over-broadening — then groups and counts them.
use npm_utils::{audit, package_json::lock::Lockfile, sbom};
let lock = Lockfile::parse(&std::fs::read_to_string("package-lock.json")?)?;
let components = sbom::components(&lock);
let sources: Vec<Box<dyn audit::AdvisorySource>> =
vec![Box::new(audit::npm::NpmRegistrySource::new("https://registry.npmjs.org"))];
let report = audit::run_audit(&components, &sources);
print!("{}", audit::render_summary(&report));Modules§
Structs§
- Advisory
- One vulnerability advisory, normalized across sources into a single shape.
- Audit
Report - The result of an audit: the vulnerable components (sorted by name then version), the per-severity totals across them, the names of any advisory sources that could not be reached, and the dependencies the component loading could not audit — so a caller can tell an incomplete run from a genuinely clean one.
- Component
Advisories - One vulnerable installed component and the advisories that hit its exact version.
- Vulnerabilities
- Per-severity advisory counts — the shape of npm’s
metadata.vulnerabilities.
Enums§
- Severity
- A normalized advisory severity. Ordered
Low < Moderate < High < Criticalso a--audit-levelthreshold is a simple comparison. npm’s vocabulary (moderate, notmedium).
Traits§
- Advisory
Source - An advisory database that can be queried for the vulnerabilities affecting a set of components.
Functions§
- build_
report - Match deduped advisories against the installed components and group the hits into an
AuditReport. - dedup_
advisories - Collapse advisories that describe the same vulnerability for the same package across sources,
joined by any shared
GHSA-/CVE-token. The first occurrence wins (sources are concatenated in selection order, npm before osv), and a later duplicate’s aliases / url / cwe / cvss / severity enrich the survivor where it lacks them — so an OSV record’s CVE alias decorates the npm GHSA. - render_
json - An
npm audit --json-shaped report: avulnerabilitiesobject keyed by package name (each with its affected installedversions, the maxseverity, and the advisories undervia) plus ametadata.vulnerabilitiesper-severity count block. - render_
summary - A plain-text audit summary: a one-line count header, then each vulnerable
name@versionwith its advisories.found 0 vulnerabilitieswhen clean (mirrorsnpm audit). Unaudited dependencies are itemized in anote:line above the header and flag the auditINCOMPLETE. - run_
audit - Query every source, then dedup across sources and keep only advisories that actually apply to an
installed version (
build_report). A source that fails is reported to stderr, recorded in the report’sfailed_sources, and skipped — a single failing source never sinks the run, but the report is marked incomplete so the caller need not present it as clean. This isrun_audit_observed(the crate-internal eventful variant) with a no-op observer. - severity_
from_ cvss - Map a CVSS base score to a severity bucket (the CVSS v3 qualitative ranges):
<= 0isNone,< 4Low,< 7Moderate,< 9High, else Critical. Used when a source gives a numeric score but no severity word.