Wraps cargo-audit + cargo-deny. Catch known CVEs, enforce license policy, ban specific crates — with a single machine-readable verdict.
dev-* verification collection.Also available as the
security feature of the dev-tools umbrella crate — one dependency, every verification layer.
dev-security wraps two best-in-class Rust security tools and emits
results as a dev-report::Report:
cargo-auditscans the dependency tree against the RustSec advisory database for known CVEs.cargo-denyenforces policy: allowed/banned licenses, allowed/banned crates, allowed/banned sources, multiple-version detection.
Findings from both tools come back through one typed AuditResult,
ready to drive an AI agent or a CI gate without parsing free-form
output.
[dependencies]
dev-security = "0.9"One-time tool install:
cargo install cargo-audit cargo-denyDrive it from code:
use dev_security::{AuditRun, AuditScope};
let run = AuditRun::new("my-crate", "0.1.0").scope(AuditScope::All);
let result = run.execute()?;
let report = result.into_report();
if report.failed() {
eprintln!("audit failed: {}", report.to_json()?);
}
# Ok::<(), Box<dyn std::error::Error>>(())| Scope | What it runs |
|---|---|
AuditScope::Vulnerabilities |
cargo audit only (RustSec advisory DB). |
AuditScope::Policy |
cargo deny check only (licenses, banned crates). |
AuditScope::All |
Both. |
| Source | dev-report::Severity |
|---|---|
cargo-audit critical |
Critical |
cargo-audit high |
Error |
cargo-audit medium |
Warning |
cargo-audit low / none / missing |
Info / Warning |
cargo-audit warnings (unmaintained etc.) |
Warning |
cargo-deny error |
Error |
cargo-deny warning |
Warning |
cargo-deny help / note |
Info |
Suppress known false positives by advisory ID, and / or set a
severity floor so noisy Info findings stop showing up in CI:
use dev_security::{AuditRun, AuditScope};
use dev_report::Severity;
let run = AuditRun::new("my-crate", "0.1.0")
.scope(AuditScope::All)
.allow("RUSTSEC-2024-9999")
.allow_all(["RUSTSEC-2023-0042", "RUSTSEC-2022-0066"])
.severity_threshold(Severity::Warning); // drop Info findings
let _result = run.execute()?;
# Ok::<(), Box<dyn std::error::Error>>(())Allow-list entries match against the id field of each Finding —
advisory IDs for cargo-audit findings (RUSTSEC-2024-NNNN) and
diagnostic codes for cargo-deny findings (e.g. L001).
AuditProducer plugs the audit into a multi-producer pipeline driven
by dev-tools:
use dev_security::{AuditProducer, AuditRun, AuditScope};
use dev_report::Producer;
let producer = AuditProducer::new(
AuditRun::new("my-crate", "0.1.0").scope(AuditScope::All),
);
let report = producer.produce();
println!("{}", report.to_json().unwrap());Subprocess failures map to a single failing CheckResult named
security::audit with Severity::Critical — the pipeline keeps
running.
Finding, FindingSource, and AuditResult are all
serde-derived. JSON output uses snake_case field names and omits
optional fields when they are None:
{
"id": "RUSTSEC-2024-0001",
"title": "Use after free in foo",
"severity": "critical",
"affected_crate": "foo",
"affected_version": "1.2.3",
"url": "https://rustsec.org/advisories/RUSTSEC-2024-0001",
"source": "audit"
}| File | What it shows |
|---|---|
examples/basic.rs |
Full audit (All scope); prints the JSON report. |
examples/audit_only.rs |
Vulnerabilities scope only. |
examples/policy_only.rs |
Policy scope only. |
examples/producer.rs |
AuditProducer wired into a pipeline (gated by DEV_SECURITY_EXAMPLE_RUN). |
Both cargo-audit and
cargo-deny must be installed:
cargo install cargo-audit cargo-denyThe crate detects absence of either tool and surfaces
AuditError::AuditToolNotInstalled /
AuditError::DenyToolNotInstalled rather than panicking.
Runtime dependency footprint: dev-report, serde, serde_json.
Finding gained four new fields: affected_version, url,
description, and source. If you constructed Finding literals in
0.1.0, add the new fields:
# use dev_security::{Finding, FindingSource};
# use dev_report::Severity;
let _f = Finding {
id: "RUSTSEC-2024-0001".into(),
title: "Use after free in foo".into(),
severity: Severity::Critical,
affected_crate: "foo".into(),
// new in 0.9.0:
affected_version: Some("1.2.3".into()),
url: None,
description: None,
source: FindingSource::Audit,
};The constructor surface (AuditRun::new, AuditScope variants,
AuditResult::into_report) is unchanged.
dev-security ships independently and is also re-exported by the
dev-tools umbrella crate as
the security feature. Sister crates cover the other verification
dimensions:
dev-report— report schema everything emitsdev-fixtures— deterministic test fixturesdev-bench— performance and regression detectiondev-async— async runtime verificationdev-stress— stress and soak workloadsdev-chaos— fault injection and recovery testingdev-coverage— code coverage with regression gatesdev-deps— unused / outdated dep detectiondev-ci— GitHub Actions workflow generatordev-fuzz— fuzz testing workflowdev-flaky— flaky-test detectiondev-mutate— mutation testing
v0.9.x is the pre-1.0 stabilization line. The API is feature-complete
for vulnerability scanning, policy enforcement, allow-listing, and
severity gating. Production use is fine; 1.0 will pin the public API
and the wire format.
1.85 — pinned in Cargo.toml via rust-version and verified by
the MSRV job in CI.
Apache-2.0. See LICENSE.
Copyright © 2026 James Gober.