cargo-audit-rust
Configures and runs cargo-audit against the RustSec Advisory Database for Rust projects; covers `cargo audit` (vulnerability scan), `cargo audit fix` (automated dependency updates), `--deny unmaintained|unsound|yanked|warnings` exit-code control, `audit.toml` per-advisory suppression with mandatory `expires` + `reason`, SARIF output for GitHub Code Scanning upload, and `rustsec/audit-check` GitHub Actions integration. Use when the codebase has a Cargo.lock and needs Rust-specific SCA beyond what the multi-ecosystem npm-pip-maven-audit wrapper provides.
Install with skills.sh (any agent)
npx skills add testland/qa --skill cargo-audit-rustcargo-audit-rust
Overview
cargo-audit scans a project's Cargo.lock against the RustSec Advisory Database (opens in new window) for vulnerable, unmaintained, unsound, and yanked crates.
Differentiation from npm-pip-maven-audit: that skill lists cargo audit as one line in a multi-ecosystem wrapper; this skill covers the Rust-specific depth (--deny semantics, audit.toml schema, cargo audit fix, SARIF, binary auditing, the rustsec/audit-check Action).
When to use
Step 1 - Install
Per cargo-audit README (opens in new window):
cargo install cargo-audit --lockedMinimum Rust version: 1.74 per rustsec-readme (opens in new window).
Platform package managers (consult rustsec-readme (opens in new window) for current availability):
# Alpine Linux
apk add cargo-audit
# Arch Linux
pacman -S cargo-audit
# macOS Homebrew
brew install cargo-auditTo enable the cargo audit fix subcommand, install with the fix feature (rustsec-readme (opens in new window)):
cargo install cargo-audit --features=fix --lockedStep 2 - Basic scan
Run at the workspace root where Cargo.lock lives (rustsec-readme (opens in new window)):
cargo auditScan a specific lockfile path (rustsec-readme (opens in new window)):
cargo audit -f path/to/Cargo.lockcargo-audit fetches the RustSec Advisory Database on first run (a git clone into ~/.cargo/advisory-db). Pass --no-fetch to skip the fetch in air-gapped environments (rustsec-readme (opens in new window)).
Step 3 - Exit codes and --deny flags
Exit codes per cargo-audit source (opens in new window):
| Code | Meaning |
|---|---|
| 0 | No vulnerabilities / denial criteria not triggered |
| 1 | Vulnerabilities found matching denial criteria |
| 2 | Execution error (missing lockfile, DB fetch failure) |
The --deny flag turns advisory categories into hard failures (cargo-audit source - audit.rs (opens in new window)):
# Fail on any vulnerability
cargo audit --deny warnings
# Fail on unmaintained crates specifically
cargo audit --deny unmaintained
# Fail on unsound (memory-unsafe) crates
cargo audit --deny unsound
# Fail on yanked crates in the lockfile
cargo audit --deny yanked
# Combine: fail on vulnerabilities AND unmaintained
cargo audit --deny warnings --deny unmaintained--deny warnings is the special catch-all: it enables all denial categories simultaneously per audit.rs source (opens in new window).
Step 4 - Output formats
Per cargo-audit source (opens in new window), --format supports three values:
| Value | Use |
|---|---|
terminal | Default human-readable output |
json | Machine-readable; pipe to multi-tool SCA triage |
sarif | SARIF 2.1; upload to GitHub Code Scanning |
# JSON output for programmatic consumption
cargo audit --format json > cargo-audit.json
# SARIF output for GitHub Security tab
cargo audit --format sarif > cargo-audit.sarifStep 5 - audit.toml suppression
Persistent suppression belongs in .cargo/audit.toml at the repo root, not CLI --ignore flags (not auditable in git). Every ignored advisory carries a mandatory reason and re-review date:
[advisories]
ignore = ["RUSTSEC-2024-0999"]
# RUSTSEC-2024-0999: serde_cbor unmaintained
# Reason: we use serde_cbor only in test fixtures, not in production paths.
# Approved-by: alice@example.com
# Re-review-date: 2026-09-30
# Tracking: JIRA-4567Commit .cargo/audit.toml so suppressions are auditable in git history and code review. The full [advisories]/[output]/[database] config schema is in references/cargo-audit-config-and-ci.md.
Step 6 - cargo audit fix
cargo audit fix automatically updates Cargo.toml version constraints to pull in patched crate versions, then runs cargo update (rustsec-readme (opens in new window)):
# Preview changes without modifying files
cargo audit fix --dry-run
# Apply updates
cargo audit fixLimitations: cargo audit fix is experimental per rustsec-readme (opens in new window); it updates version constraints but cannot resolve conflicts in the dependency graph - manual intervention is needed when the patched version is incompatible with other constraints. Always run cargo test after applying fixes.
Step 7 - CI and binary auditing
GitHub Actions integration (the official rustsec/audit-check action plus SARIF upload) and compiled-binary auditing (cargo auditable build + cargo audit bin) are in references/cargo-audit-config-and-ci.md.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
--ignore RUSTSEC-xxxx in CI script | Not auditable in git; lost on script rewrite | Use [advisories] ignore in .cargo/audit.toml committed to repo |
No reason comment next to ignore | Silent debt accumulation | Mandatory reason + re-review date (Step 5 template) |
cargo audit without --deny | Vulnerabilities surface as warnings, not failures | Add --deny warnings or set deny = ["warnings"] in audit.toml |
Skip --format sarif upload | Findings invisible in GitHub Security tab | Emit SARIF + upload (Step 7) |
cargo audit fix without cargo test | A patched dep version may break compilation or tests | Always test after fix (Step 6) |
Omitting Cargo.lock from git (library crates) | cargo audit has nothing to scan | Commit Cargo.lock or generate it with cargo generate-lockfile in CI |
Limitations
References
cargo-audit config, binary auditing, and CI
View source (opens in new window)cargo-audit config, binary auditing, and CI
Deep reference for the cargo-audit-rust SKILL.md. SKILL.md keeps install, the basic scan, --deny semantics, output formats, cargo audit fix, and the minimal suppression template; this file holds the full .cargo/audit.toml schema, binary auditing, and the GitHub Actions wiring.
Full .cargo/audit.toml schema
Per the audit.toml example (opens in new window):
# .cargo/audit.toml
[advisories]
# Advisory IDs to suppress - each MUST have a reason and expiry tracked in a
# companion comment or issue tracker entry
ignore = ["RUSTSEC-2024-0001"]
# Informational categories to surface as warnings (not hard failures)
informational_warnings = ["unmaintained", "unsound"]
# Minimum CVSS severity to report: "none" | "low" | "medium" | "high" | "critical"
severity_threshold = "medium"
[output]
# "terminal" | "json" | "sarif"
format = "terminal"
# Hard-fail categories (mirrors --deny flags)
deny = ["warnings"]
# Show inverse dependency trees alongside each finding
show_tree = true
[database]
# Skip remote fetch (for offline / air-gapped builds)
fetch = false
# Allow an advisory DB that has not been updated recently
stale = falseBinary auditing
For auditing compiled binaries (e.g. checking a deployed artifact without source access), install the companion crate and audit the binary (rustsec-readme (opens in new window)):
# Compile with embedded dependency metadata
cargo install cargo-auditable
cargo auditable build --release
# Audit the compiled binary
cargo audit bin target/release/my-appBinary auditing works best when the binary was compiled with cargo-auditable, which embeds Cargo.lock metadata into the ELF/Mach-O/PE section. Binaries without embedded metadata cannot be audited.
GitHub Actions CI integration
Use the official rustsec/audit-check (opens in new window) action, which wraps cargo audit, creates check runs, and (for scheduled workflows) opens GitHub Issues for each advisory (audit-check README (opens in new window)):
name: Security audit
on:
push:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
schedule:
- cron: '0 0 * * *'
jobs:
security_audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Optional: comma-separated advisory IDs to suppress
# ignore: "RUSTSEC-2024-0001,RUSTSEC-2024-0002"
# Optional: subdirectory with Cargo.toml
# working-directory: crates/my-crateCI gate behavior (audit-check-action (opens in new window)):
For SARIF upload alongside the action:
- name: Run cargo audit (SARIF)
run: cargo audit --format sarif > cargo-audit.sarif || true
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: cargo-audit.sarifRelated skills
bundle-audit-ruby
Use when a Ruby project has a Gemfile.lock and needs CVE/GHSA scanning or a CI SCA gate. Installs and runs bundler-audit against a Ruby Gemfile.lock, updating the ruby-advisory-db corpus, scanning for vulnerable gem versions and insecure sources, suppressing false positives via .bundler-audit.yml, and gating CI on non-zero exit. Ruby-only SCA scanner: for other ecosystems use npm-pip-maven-audit (multi-ecosystem dispatcher), snyk-test, or osv-scanner; cargo-audit-rust is the Rust analog; once findings exist, reachability-analyzer downranks unreachable gems - not this.
cve-exploitability-triage
Ranks known CVE findings by real-world exploitability instead of severity alone: enriches each CVE with its EPSS probability (the chance exploitation activity is observed in the next 30 days) and CISA KEV membership (confirmed exploited in the wild), applies OpenVEX status assertions to set aside vulnerabilities the product is not affected by, applies a reachability heuristic for vulnerable code that is never called, and assigns every finding to one of four buckets (Fix-Now, Fix-This-Sprint, Fix-Backlog, Accept-Risk) using documented EPSS thresholds. Treats a CISA KEV listing as non-waivable under any justification. Use when a dependency, container image, or SBOM vulnerability scan has produced more CVEs than the team can fix in the available window and someone has to decide which ones get fixed first and which can wait.
dependabot-config
Reference for `.github/dependabot.yml` - GitHub-native dependency-update orchestrator. Required keys (`version: 2`, `updates[]` array) plus per-update fields (`package-ecosystem`, `directory` / `directories`, `schedule.interval`); common optional fields (`ignore`, `groups`, `allow`, `labels`, `milestone`, `open-pull-requests-limit`, `target-branch`, `vendor`, `versioning-strategy`, `assignees`, `commit-message`); auto-rebase + grouped-PR + security-only updates. Use when authoring or reviewing Dependabot configs in GitHub-hosted repos.
npm-pip-maven-audit
Configures and runs native package-manager audit commands across ecosystems - `npm audit --audit-level=high` (npm), `yarn npm audit` (Yarn 2+), `pnpm audit` (pnpm), `pip-audit` (Python via PyPA), `mvn dependency:check` (Maven via OWASP Dependency-Check plugin), `cargo audit` (Rust), `bundle audit` (Ruby Bundler); fastest no-install-required SCA option. Use when the team wants fast, no-extra-tooling SCA in CI as a first line of defense, or pairs with snyk/osv-scanner for layered coverage.
osv-scanner
Configures and runs Google OSV-Scanner - open-source SCA against the OSV.dev vulnerability database; supports `osv-scanner scan -r ./` recursive scan + per-lockfile scan via `-L package-lock.json`; SBOM input (CycloneDX / SPDX) for non-standard package managers; `--format json|sarif|markdown|vertical|html` output; suppressions via `osv-scanner.toml` config. Use when the team needs OSS-native SCA without commercial-license overhead, or wants a second-opinion DB pair with Snyk's commercial DB.
reachability-analyzer
Runs dead-dependency analysis across JS, Python, and Rust projects using ecosystem-native static tools (`depcheck`/`knip` for JS, `vulture` for Python, `cargo-machete` for Rust), then cross-references the unused-dependency list against SCA findings to downrank vulns in code that is never loaded. Use when SCA output (from `osv-scanner`, `snyk-test`, or `npm-pip-maven-audit`) is too noisy to triage and the team needs to separate unreachable CVEs from exploitable ones before sprint planning; sibling cve-exploitability-triage ranks by EPSS/KEV exploitation signal, not code reachability.
renovate-config
Reference for `renovate.json` - Mend Renovate dependency-update orchestrator (multi-platform: GitHub / GitLab / Bitbucket / Azure DevOps / Gitea); top-level keys (`extends` for preset references, `schedule`, `prConcurrentLimit`, `vulnerabilityAlerts`); `packageRules[]` array with `matchPackageNames` / `matchUpdateTypes` / `automerge` matching; `ignoreDeps`, `addLabels`, `automergeSchedule`. Use when authoring or reviewing Renovate configs in any repo platform Renovate supports.
snyk-test
Configures and runs Snyk, a commercial multi-mode scanner: snyk test for SCA (dependency scanning), snyk code test for SAST (code security scanning), snyk container test for container images, snyk iac test for IaC (infrastructure-as-code), snyk monitor for continuous new-vuln alerts; policy file .snyk for ignore + patch. Use when the team has a Snyk license and needs SCA (dependency scanning) or continuous vuln monitoring; for open-source scanning without a Snyk license, prefer osv-scanner.