DEV Community

cargo-witness: verify a published Rust crate matches the exact commit it claims

When you review a Rust dependency on GitHub, you are reading its source. When cargo build runs, it compiles the .crate artifact downloaded from crates.io - a separate upload. Those two are not guaranteed to be the same bytes, and nothing in the normal workflow checks that they are.

That gap is exactly what the onering attack (June 2026) used: a malicious build.rs build script was slipped into the published artifact while never appearing in the crate's public git history. Anyone auditing the repository saw clean code; anyone who ran cargo build executed the injected script at compile time.

cargo-witness is a small, zero-cost tool that closes that gap. It downloads the exact .crate Cargo would install, extracts it, and diffs it against the crate's real source.

What it verifies against

The hard part is deciding which source to compare against. cargo-witness uses the strongest anchor available, in order:

  • The attested commit (Trusted Publishing). If the version was published through crates.io Trusted Publishing, crates.io records the OIDC-verified commit the CI build ran from in trustpub_data.sha. The publisher cannot forge this. cargo-witness fetches the git tree at that exact commit and compares against it. This is the gold standard.
  • The self-reported commit. Otherwise it reads .cargo_vcs_info.json - embedded in every modern crate - for the exact git.sha1 and path_in_vcs the publisher recorded at package time. No tag guessing.
  • A git tag. For older crates without vcs info, it falls back to common tag formats.

Because it resolves to a precise commit, comparison is exact rather than approximate, and workspace crates (whose source lives in a subdirectory) are handled correctly - no false positives on crates like serde.

What it detects

Flag Meaning
BUILD_RS_INJECTED build.rs in the artifact, absent from source (the onering pattern)
BUILD_RS_MODIFIED build.rs present in both, content differs
SOURCE_MODIFIED a Rust source file's published content differs from source
FILE_NOT_IN_GIT a source file shipped only in the artifact
BINARY_NOT_IN_GIT a precompiled binary shipped only in the artifact
CHECKSUM_MISMATCH artifact sha256 does not match the crates.io-recorded checksum
VCS_MISMATCH the self-reported commit disagrees with the attested one

Content comparison uses the git blob SHA the tree API already returns, so most files are checked with no extra network calls; only a mismatch triggers a fetch, which is then confirmed against newline-normalized content to avoid line-ending false positives.

Using it

# One-time scan of a project's Cargo.lock
npx cargo-witness --scan

# CI mode: check only newly added dependencies, fail the build if suspicious
npx cargo-witness --ci --fail-on medium

# Investigate a specific crate: show exactly how the artifact differs from source
npx cargo-witness --diff <name> <version>

It also runs as a nightly daemon and as a GitHub Action that posts a job summary, sets step outputs, and can emit SARIF for code scanning.

Source is resolved on GitHub, GitLab, and Gitea/Codeberg. No API keys or paid services are required - a GITHUB_TOKEN (or GITLAB_TOKEN / GITEA_TOKEN) only raises rate limits.

Where it fits, and where it does not

cargo-witness is complementary to what already exists.

  • cargo-audit checks dependencies against the RustSec advisory database - known, already-reported issues.
  • cargo-vet and cargo-crev are human-attestation systems.

cargo-witness is mechanical and looks for one specific thing those structurally miss: the published artifact not matching its source, before anyone has filed an advisory. It is a detection aid, not a guarantee. An attacker who also tampers with the git tag or commit, or a crate whose repository has no matching commit (reported as NO_GIT_TAG, not a clean verdict), can evade it.

The intended trajectory is to compose with crates.io provenance as it matures - Trusted Publishing support is the first step in that direction.

If you run it against a popular crate and find a real divergence, please report it privately to the crate owner and to the RustSec advisory database before disclosing publicly.

Comments

No comments yet. Start the discussion.