The OpenVet Registry is now live at openvet.org as a preview deployment. The registry is a public, collaborative host for cryptographically signed software dependency audits: a place for auditors to publish their work and for projects to subscribe to the auditors they trust.
OpenVet is a tool that tries to make it possible, affordable and scalable for projects to adopt audited-dependencies workflows. The status quo today is that most projects use dependencies without reviewing what they do. As a collective, we place implicit trust in packages published in registries. Large corporations can afford teams dedicated to reviewing dependencies, but most projects cannot. The OpenVet command-line tool tries to make it easy to audit packages, and to consume those audits. The registry tries to make it easy to publish those, and discover logs. If you want to know more, the docs have a longer answer.
This is a preview deployment. The registry is operational and I’m dogfooding it daily, but the data structures behind it aren’t yet frozen. Expect that I’ll occasionally change something and reset the registry in the process. Don’t host audits here that you can’t afford to lose until I drop the preview label.
What you can do with it today #
I run openvet against the OpenVet repository as a continuous
dogfooding exercise. The output below is real, from a check in
mid-May 2026 — the numbers are what they are.
Setup #
openvet init drops a starter openvet.toml. Mine, after a
few edits, looks like this:
[log.xfbs]
url = "https://openvet.org/xfbs"
[[lockfile]]
kind = "cargo"
path = "Cargo.lock"
[requirement]
benign = "is-benign"
crypto = "uses-crypto implies crypto-safe and crypto-tested"
unsafe = "uses-unsafe implies unsafe-safe and unsafe-tested"
I trust one log (my own, at openvet.org/xfbs), I want to gate
the Cargo.lock, and I declare three requirements: every
dependency must be benign, must be safe-and-tested if it uses
cryptography, and must be safe-and-tested if it uses unsafe
code. The requirement syntax is boolean over claim names — see
claims vocabulary and requirement syntax
in the docs for the full set.
Pin and verify the logs you trust #
openvet update fetches each audit log you’ve subscribed to in
openvet.toml, verifies its signature chain end-to-end, and
writes the new head into openvet.lock:
$ openvet update
xfbs: verified 50 new commit(s) (0 keyset / 0 gen-root); head 117574148ceb -> cb6e938a4ced
wrote openvet.lock
The signature verification is local — the registry’s only job
here was to serve bytes. The pinned head in openvet.lock is
what guarantees the same verdict on every machine running
openvet check later.
Gate your project against the audits #
openvet check walks your lockfiles, evaluates each requirement
against the audits in the logs you’ve pinned, and exits non-zero
on anything that doesn’t satisfy your policy:
$ openvet check
✘ cargo:matchers@0.2.0
└─ unsafe: ✘ contradicted
└─ from xfbs: ✘ false
└─ any → false
├─ not → false
│ └─ uses-unsafe → true
└─ all → false
├─ unsafe-safe → true
└─ unsafe-tested → false
Summary: 53 passed, 505 failed, 13 skipped
(output trimmed)
When a requirement fails, check prints the resolution tree:
which auditor’s statement contradicted it, which claim atoms
combined under three-valued logic, and which atom resolved to
which value. The full mechanics live in
How it works.
The 505 failed is honest — most crates in OpenVet’s own
dependency tree don’t have audits in my log yet. That’s the
work; closing the gap is the next stretch of dogfooding.
Ask concrete questions about your dependency tree #
openvet query <expression> walks your lockfiles and reports
the state of a requirement expression across them. It uses the
same parser and evaluator as [requirement] in openvet.toml
— anything you can write as a requirement, you can pass to
query. The simplest case is a single claim atom: which of my
crates use unsafe code, according to my pinned audits?
$ openvet query uses-unsafe
warn openvet@0.4.0 (path / workspace dep)
warn openvet-audit@0.4.0 (path / workspace dep)
…
✓ cargo:bitflags@2.11.1
✓ cargo:log@0.4.29
✓ cargo:matchers@0.2.0
✓ cargo:once_cell@1.21.4
✓ cargo:tempfile@3.27.0
✓ cargo:tracing@0.1.44
✓ cargo:unsafe-libyaml@0.2.11
✓ cargo:zeroize@1.8.2
…
Summary: 30 match, 35 contradicted, 493 unknown, 13 skipped
(output trimmed)
match is the count of dependencies the expression resolves to
true for. contradicted are dependencies where audits disagree
under three-valued logic. unknown is the long tail where no
pinned audit provides enough information to resolve the
expression. Compound expressions work the same way — openvet query "uses-unsafe and impl-crypto" would count only
dependencies where both atoms resolve to true. The summary line
on its own tells you the coverage of a given property across
your tree.
What’s in this deployment #
The registry implements the OpenVet protocol. It’s not a central trust anchor — the command-line tool will work with anything that speaks the protocol. You can host your own log on anything that can serve data over HTTP/HTTPS, and get the same functionality. The public deployment exists to make participation low-friction. Signup is two clicks if you have a GitHub account. It defaults to custodial keys, so you don’t have to manage your own keys (unless you want to, which is perfectly fine, and encouraged), all to make the process of adopting it as easy as possible. The registry is free, and it will always be. It’s not a SaaS, it’s just a (public) service.
What’s working today:
- Account signup and custodial keys. New accounts get a registry-held signing key by default. Custodial keys are published in your keyset like any other, so consumers can verify audits you sign with them.
- Publishing audits from the CLI. Author audits locally, sign with a self-held key, and push to your registry-hosted log. End-to-end without going through the UI.
- Package search. The registry actively synchronizes package registry contents, so you can search for packages on openvet.org, and find matching audits. Currently, only synchronization with crates.io is enabled on the hosted registry, but more will be enabled soon.
- Audit log hosting for any ecosystem. Audits can be hosted here regardless of which ecosystem the audited package comes from.
- Raw log endpoints for subscribers. The CLI subscribes directly to a log’s HTTP endpoint and verifies the signature chain locally; the registry’s job is to serve bytes.
What’s still rough #
In the spirit of “should I use this yet?”, a candid list:
- Data structures may still change. Some breaks will be migrations; some will be hard resets of the registry’s data. Until I drop the preview label, anything you publish here should be considered ephemeral.
- The web UI is pre-pre-beta. The basic flows (login, searching packages, viewing audits) work. Some things may look strange, or be subtly broken.
- Self-custodial setup doesn’t fully work yet. You can add your own key to your log’s keyset, but there is currently no way to remove the custodial key and give your own key operator privileges.
- Search beyond cargo is dark. RubyGems and PyPI syncers are implemented but not yet enabled in production. npm and Go are next. The work is queue-and-storage, not a code rewrite.
- No mirroring story yet. Self-hosting a log on static storage works, but tooling for “mirror this registry-hosted log to your own server” isn’t shipped.
Try it #
Browsing the registry is open, no account required. Visit
openvet.org and search for a crate (try serde) to
see what audits exist for it, or open my profile to see
what one auditor has published.
To participate, sign in with GitHub (two clicks). The registry mints you a log slug and a custodial signing key. From there:
- Click Trust on any profile to follow that auditor — their audits flow into your feed.
- Under Settings → Keys, add your own key. The UI gives
you a one-line
openvet logincommand to run in your terminal, which pairs the CLI with your log. You can create, sign and publish audits from the CLI, and they will show up in the registry.
To gate your own project against the audits, the CLI
section above walks the loop: install the CLI,
declare a log to trust, run openvet update and openvet check.
The Quickstart in the docs is the end-to-end
version.
What’s next #
OpenVet is still under development. I am working on the specification, the command-line interface, and the backend in parallel. As new bits get released, I will make announcements on this blog, explaining what works, what doesn’t, what is stable, and what isn’t.
One of the outstanding pieces that will be released in the upcoming days is an initial version of the OpenVet specification, which still needs some cleaning up. The registry is the piece that is the most behind: audits already render fine, but there is no web-based auditing flow implemented yet. There are a lot of rough edges and unimplemented pieces. The command-line tool is in better shape, but is still missing some important features, such as signing with encrypted keys, or supporting signatures with anything besides sshsig.
Find it / report it #
- Registry source: gitlab.com/openvet-org/registry
- CLI source: gitlab.com/openvet-org/openvet
- Docs: docs.openvet.org
- Issues: the GitLab tracker on whichever repo is closest to the problem. Issues and MRs are very much welcome — this is a one-person project and any extra eyes help.
If you’d rather reach me directly, my GitHub profile has the contact info.