Skip to main content

Offline mode

Vulkro scans offline by design. Exactly one outbound call is automatic; every other call happens only when you ask for it. The full list:

  1. Account sign-in and entitlement refresh - the only automatic call. vulkro login connects the CLI to your account (your first login starts a 14-day trial), and while signed in the CLI refreshes its signed lease about once a day. The refresh carries up to eight usage fields (product, install_id, version, OS, timestamp, scan counter, plus a device token while signed in and a language slug-set after a scan), never code, paths, or findings. Air-gapped machines use an installed license file instead and make neither call. See Telemetry for the exact fields.
  2. Live dependency CVE lookup - opt-in only. With VULKRO_CVE_LIVE=1, vulkro scan queries api.osv.dev when it finds a parsed dependency manifest, sending package name, version, and ecosystem, to catch CVEs published since your local bundle. Off by default: a plain scan resolves dependencies against the local bundle only, so nothing about your dependency tree leaves the machine. VULKRO_OFFLINE=1 overrides the opt-in.
  3. Installer - fetches the binary tarball from the Vulkro release feed.
  4. First-run CVE bundle - vulkro update runs once during install to populate ~/.vulkro/data/cves/.
  5. vulkro update when invoked explicitly. It downloads the signed CVE bundle, and it is also the only place the release-feed version check runs: it asks for the latest version and offers to install a newer binary. The scanner does not check for updates while it works, so a plain vulkro scan never touches the release feed. Suppress just the version check with --no-version-check or VULKRO_NO_UPDATE_CHECK=1.
  6. vulkro probe --base-url <URL> when invoked explicitly.
  7. vulkro rules add / vulkro rules update when invoked explicitly.
  8. vulkro notify --url <URL> / vulkro scan --post-to <...> when invoked explicitly.
  9. vulkro scan --validate-secrets when invoked explicitly.

The analysis itself is entirely local in every case: discovery, scan, container scan, history, diff, trends, contributors, compliance, and the desktop console all read from disk and write to disk. Your source code, file paths, and findings are never sent anywhere, on any command in the list above. Every call in the list is disabled by VULKRO_OFFLINE=1 (below). For the full per-call inventory (destination, payload, gate), see Network egress.

VULKRO_OFFLINE=1

Setting this environment variable refuses every outbound network call. Affected commands:

CommandBehaviour with VULKRO_OFFLINE=1
Entitlement refresh (the one automatic call, while signed in)Disabled - install a license file (vulkro activate <file>.lic) to satisfy the account requirement with zero network.
Release-feed version check (only inside vulkro update)Disabled - no request is sent.
vulkro loginRefused - use a license file on offline machines.
vulkro update (no flags)Refused with a hint to use --bundle.
vulkro update --bundle <path>Allowed. Fully offline.
vulkro update --verify <path>Allowed. Fully offline.
vulkro rules addRefused (503-style error).
vulkro rules updateRefused (503-style error).
vulkro probeRefused (exit 2) - the probe contract is "I will make HTTP calls".
vulkro notifyRefused (exit 2).
vulkro scan --post-to <...>Skipped with a warning; the scan still runs.
vulkro scan --validate-secretsRefused (exit 2) for the validation lane; main scan still works.
vulkro scan (no validate-secrets)Fully offline.
vulkro container <ref>Allowed. Shells out to local docker only.

Verifying the contract

You can confirm Vulkro holds to the offline contract:

# Run vulkro with all network egress blocked at the kernel level.
unshare -rn /bin/bash -c 'VULKRO_OFFLINE=1 vulkro scan .'

Should complete without error.

CDN base URL override

For organisations that mirror the Vulkro CVE bundle internally:

export VULKRO_CDN_BASE_URL="https://artifacts.internal/vulkro-cve"
vulkro update

The mirror must serve the same /manifest.json + /manifest.json.sig + bundle layout as the public CDN. Signed bundles are still verified against the built-in trust list - mirroring doesn't change the signing trust model.

Air-gapped install

Full walkthrough at Install -> Air-gapped install.