Skip to main content

Bundle format

A .vkbundle is Vulkro's signed offline-update format. It carries CVE data, rule packs, and compliance frameworks across an air gap.

Layout

A .vkbundle is a gzipped tar archive with a strict internal structure:

vulkro-cve-2026-05-10.vkbundle (gzipped tar)
+-- manifest.json <- machine-readable metadata
+-- manifest.json.sig <- ed25519 signature over manifest.json
+-- data/
+-- cves/
| +-- npm.json
| +-- pypi.json
| +-- cargo.json
| +-- go.json
| +-- maven.json (optional)
+-- rules/
| +-- *.yaml (rule packs, optional)
+-- compliance/
+-- *.toml (compliance frameworks, optional)

manifest.json

{
"schema_version": 1,
"snapshot_id": "2026-05-10",
"created_at": "2026-05-10T05:17:00Z",
"ecosystems": ["npm", "PyPI", "Cargo", "Go"],
"record_counts": {
"npm": 31420,
"PyPI": 18901,
"Cargo": 4203,
"Go": 7144
},
"files": [
{"path": "data/cves/npm.json", "sha256": "...", "bytes": 18923844},
{"path": "data/cves/pypi.json", "sha256": "...", "bytes": 9821100},
...
],
"signing_key_id": "wm-prod-2026"
}

Every entry in files carries a SHA-256 that the unpacker re-checks on apply. A bundle whose manifest signature verifies but whose file hashes don't match aborts cleanly without writing.

Apply

vulkro update --bundle ./vulkro-cve-2026-05-10.vkbundle

Steps the unpacker takes:

  1. Open the gz tar.
  2. Read manifest.json + manifest.json.sig.
  3. Verify the signature against the built-in trust list and any --trust-key-supplied roots.
  4. Compute SHA-256 for each declared file and compare to the manifest.
  5. Stage the writes to a tempdir.
  6. Atomically swap the tempdir contents into ~/.vulkro/data/.

Failure at any step aborts before the swap, so a partial bundle never leaves the data directory in a half-applied state.

Verify without applying

vulkro update --verify ./vulkro-cve-2026-05-10.vkbundle

Prints the manifest, exits non-zero on signature or hash failures, and writes nothing to disk. Useful for staged review before deploying a bundle internally.

Authoring a bundle (maintainer-only)

VULKRO_SIGNING_KEY=$(cat ~/.vulkro-secrets/cve-signing-key.hex) \
vulkro update --create \
--out vulkro-cve-2026-05-10.vkbundle \
--add cves:cves/npm.json:./build/npm.json \
--add cves:cves/pypi.json:./build/pypi.json

In practice this is wrapped by bundle_push.sh at the repo root, which also handles signing-key custody, GH Releases upload, and CDN manifest update.