Dependency Vulnerability Scanning (OSV)
build_sbom inventories dependencies and to_sarif exports findings,
but nothing in between ever produced a vulnerability finding — there was no
advisory matching at all. This closes that loop: given the SBOM’s
(ecosystem, name, version) components and an OSV
advisory database, scan_components reports which packages are affected, and
findings_to_sarif bridges the results straight into the existing SARIF
exporter for GitHub / Azure DevOps code scanning.
The advisory database is injected as plain data (a list of OSV records), so
matching is fully offline and deterministic; the live osv.dev query is a
separate, optional fetcher seam. Pure standard library (re); imports no
PySide6.
Headless API
from je_auto_control import (
build_sbom, scan_components, findings_to_sarif, write_sarif)
advisories = [{
"id": "GHSA-foo", "summary": "RCE in foo",
"database_specific": {"severity": "HIGH"},
"affected": [{
"package": {"ecosystem": "PyPI", "name": "foo"},
"ranges": [{"type": "ECOSYSTEM",
"events": [{"introduced": "0"}, {"fixed": "1.2.0"}]}],
}],
}]
sbom = build_sbom("je_auto_control")
findings = scan_components(sbom["components"], advisories)
# findings: [{id, package, version, summary, severity, fixed, aliases}]
write_sarif(findings_to_sarif(findings), "vulns.sarif",
tool_name="AutoControl-VulnScan")
is_affected(version, osv_range) evaluates one OSV range by sweeping its
introduced / fixed / last_affected events; match_package checks
a single package against the database (explicit versions or ranges);
scan_components runs the whole SBOM. Package names are compared with PEP-503
normalization, and the OSV severity word (CRITICAL / HIGH /
MODERATE / LOW) maps to a SARIF error / warning / note
level (defaulting to warning).
Version ordering is a pragmatic numeric comparison: release components compare
as integers and a pre-release suffix (1.2.0-rc1) sorts before the final
release. Git ranges and full CVSS-vector scoring are out of scope.
Live advisories (optional)
Pass a fetcher callable to pull advisories at scan time (e.g. from the
osv.dev API). Tests inject a fake fetcher, so the matching logic is verified
without any network:
findings = scan_components(sbom["components"], None,
fetcher=my_osv_fetcher)
Executor command
AC_scan_vulns takes components (a component list, a full SBOM dict, or a
JSON string) and advisories (a list or JSON string), with an optional
sarif_path to write a SARIF report; it returns {findings, count} (plus
sarif_path when written). The same operation is exposed as the MCP tool
ac_scan_vulns and as a Script Builder command under Security.