#supply-chain-security #audit #cargo-vet #security

bin+lib openvet

Command-line tool for checking project conformance against auditing requirements, and authoring, signing and publishing software dependency audits

4 releases (breaking)

Uses new Rust 2024

new 0.4.0 May 13, 2026
0.3.0 May 12, 2026
0.2.0 May 6, 2026
0.1.0 May 1, 2026

#359 in Cryptography

MIT/Apache

4MB
25K SLoC

openvet

The command-line interface for OpenVet. Write, sign, and publish audits to your own log, and gate your project against a policy expressed over the audits other people publish.

You can use this to initialize an openvet.toml configuration file in your projects, where you define which audit logs you trust, and which requirements to gate your project against.

The openvet check command will parse your lockfiles, fetch any matching audits from the audit logs you trust, and either pass or fail with a message describing the reason for the result (for example, that a dependency you use is not audited, or that it is audited but it does not pass your requirements).

OpenVet is designed to be secure and fast to run. Any audit logs you trust are validated to ensure that their signatures are valid and that they have not been tampered with. Audit logs objects you've fetched are cached locally, to ensure that checking is fast.

The openvet update command will update the pinned audit log heads in your openvet.lock file to the latest available head, validating new commits as you go. This is the trustless design: you do not need to trust the audit log provider, as you are validating the logs locally.

The command-line tool also allows you to audit code locally and publish it to your own log. There is a command-line driven workflow for doing this, and a TUI workflow for auditing code interactively.

Installation

The easiest way to install the command-line interface is via Cargo.

cargo install openvet

Usage

Consumer flow

Declare which logs to consult, then gate the project's lockfiles against a policy expressed over the audits in those logs.

openvet init                  # creates openvet.toml
$EDITOR openvet.toml          # add [log.*], [[lockfile]], [requirement]
openvet update                # fetch + verify log heads, write openvet.lock
openvet check                 # gate the project's lockfiles against the policy
openvet check --verbose       # also print one line per passing subject
openvet log alice             # walk a log (newest commit first)

A minimal openvet.toml:

[log.alice]
url = "https://openvet.example/alice"

[[lockfile]]
kind = "cargo"
path = "Cargo.lock"

[requirement]
safe-to-deploy = "safe-to-deploy and not unsafe-code"

[[override]]
package = "libc"
requirements = { add = ["sandbox"] }

See openvet-policy for the requirement language in detail, and openvet-lockfile for the lockfile formats accepted in the kind = "..." field.

Authoring flow

When creating audits, OpenVet has a concept of a workspace. This is a directory that openvet audit new creates which contains the unpacked package contents, the audit.pb file, a manifest.json file, and a VCS checkout of the package (if the metadata is available).

You'll need a publish target and an SSH identity in your user config at ~/.config/openvet/config.toml:

[publish]
log = "https://openvet.example/alice"

[identity]
key = "~/.ssh/id_ed25519"

The audit lifecycle:

openvet audit new cargo:serde@1.0.210      # fetch + unpack into ./audit-cargo-serde-.../
cd audit-cargo-serde-1.0.210-*
openvet audit edit                         # ratatui TUI: Summary / Files / Findings / Claims
openvet audit sign                         # sign audit.pb in place
openvet audit publish                      # extend your log

Or drive each subcommand from the shell instead of the TUI:

openvet audit claim safe-to-deploy true
openvet audit summary "Looked clean."
openvet audit findings add -m "Questionable transmute in src/de.rs:42" --claim safe-to-run
cd contents/src && openvet audit annotate lib.rs --lines 10-20 -m "unsafe block"

audit publish and audit publish --update are explicit about intent: the first errors if the subject is already audited, the second errors if it isn't. To retract an audit, openvet audit remove cargo:serde@1.0.210#sha256:....

Keyset management

Every log has a keyset, which defines the list of keys that may alter the log's state. Operators manage their log's keyset through openvet keyset. Each entry carries a set of capabilities (auditor, publisher, operator), an optional label, and the proof-of-possession that established the key's ownership at enrolment time.

openvet keyset list                                 # walk the keyset
openvet keyset show "SHA256:..."                    # detail one entry
openvet keyset add ./new_key --cap auditor          # enrol a new key
openvet keyset edit "SHA256:..." --cap +operator    # incremental cap change
openvet keyset edit "SHA256:..." --revoke           # drop all caps

Custodial onboarding

When a hosted OpenVet server creates a log on a user's behalf, it issues a token URL that can be handed to openvet login. The CLI signs a proof-of-possession with the local SSH key — the private key never leaves the machine — and the server adds the pubkey to the keyset.

openvet login https://openvet.example/alice/login/<token>

The reference openvet-server does not implement these endpoints (it does not hold custodial keys); this flow is meant for hosted server variants.

Package utilities

openvet package exposes the package crate's primitives outside the audit flow — useful for scripting, inspection, and offline cache priming.

openvet package resolve cargo:serde@1.0.210
openvet package download cargo:serde@1.0.210#sha256:...
openvet package extract serde-1.0.210.crate
openvet package manifest cargo:serde@1.0.210#sha256:...

Configuration and storage

Three places hold state:

  • openvet.toml (per project) — logs, lockfiles, and policy. Auto-discovered by walking up from cwd.
  • ~/.config/openvet/config.toml (per user) — publish target, identity key, cache preferences.
  • openvet.lock (per project) — each log's verified head, written by openvet update.

Reads go through a local sqlite cache at ~/.cache/openvet/cache.db. Heads are intentionally never cached. [cache] compression_allowed = ["zstd"] (default) makes the CLI negotiate end-to-end zstd with the server. There is no GC command yet.

Resolution chain for --key, --log, and similar flags: CLI flag → OPENVET_KEY / OPENVET_LOG env var → user config → error with hint.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Dependencies

~78MB
~1.5M SLoC