The offline vulnerability bundle
Vulkro checks your dependencies against known vulnerabilities on your own machine. The advisory data it uses arrives as one signed file, the CVE bundle, so the same check works on a laptop, in CI, behind a proxy and on a machine with no network at all.
What is in it
A .vkbundle is a gzipped archive with three parts:
manifest.json: the snapshot id, when it was built, the ecosystems it covers, the record counts and a SHA-256 for every data file.manifest.json.sig: an Ed25519 signature over the manifest.data/: one advisory file per ecosystem, plus optional rule packs and compliance frameworks.
The data is collected from OSV, NVD, CISA KEV and EPSS. Current bundles cover npm, PyPI, Maven, Go, crates.io, RubyGems, Packagist and NuGet.
How it is verified
Before anything is written, Vulkro:
- checks the signature on
manifest.jsonagainst the public keys built into the binary, plus any key you add with--trust-key; - checks the SHA-256 of every file against the manifest;
- stages the files and swaps them into place in one step.
A signature that matches no trusted key is refused. There is no trust on first use and no "warn but allow", and because the trust list lives in the binary, whoever controls a mirror or a USB stick cannot name their own key. Any failure stops before the swap, so the data directory is never left half updated.
vulkro update --verify ./cves.vkbundle # check only, writes nothing
vulkro update --bundle ./cves.vkbundle # check, then applyHow it stays current
On a connected machine, vulkro update downloads the current bundle named
in the public manifest at
dist.vulkro.com/cve/manifest.json,
which lists its snapshot date, record count, SHA-256 and signing key. An
air-gapped team downloads the same file on the connected side, verifies it,
carries it across its approved channel and applies it inside. For a custom
build, write to license@vulkro.com.
Every scan states how old its data is: table output prints the bundle date
and age, and JSON, SARIF and SBOM output carry a cve_bundle field. To make
age a hard rule in CI:
vulkro scan . --max-bundle-age 168 --max-bundle-age-fail # exit 2 past 7 days, or with no bundleIf a project uses an ecosystem the applied bundle does not cover, the scan says those dependencies were not checked, rather than reporting them clean.
Further reading
- Vulnerability data for air-gapped scans: transfer, verification and a staleness policy
- Bundle format and signing and trust roots
- Re-matching an SBOM as advisories land
- Air-gapped SAST with Vulkro