How to Use cargo-audit to Check for Vulnerable Dependencies

Run `cargo audit` in your project root to scan your `Cargo.lock` file against the RustSec advisory database for known security vulnerabilities.

The vulnerability you didn't write

You are pushing a release. The CI pipeline turns red. A dependency has a critical vulnerability. You didn't write the code, but you ship the binary. The vulnerability lives in your Cargo.lock. This is the daily reality of modern software. You don't write every line, but you own every line that runs.

cargo-audit is the gatekeeper that catches these issues before they hit production. It scans your locked dependencies against the RustSec advisory database and tells you exactly what is broken, how severe it is, and how to fix it. It turns a scary supply chain risk into a manageable task list.

How cargo-audit works

Rust's package manager, Cargo, manages dependencies through two files. Cargo.toml declares what you want. Cargo.lock records exactly what you got. The lockfile pins every transitive dependency to a specific version and hash. This determinism is what makes auditing possible.

cargo-audit reads Cargo.lock. It extracts every crate name and version. It fetches the RustSec advisory database, which is a community-curated list of known vulnerabilities. It compares your dependencies against the database entries. If a match is found, it reports the advisory.

Think of cargo-audit like a health inspector for your supply chain. You bring in ingredients from various vendors. The inspector checks every ingredient against a list of known recalls. The inspector doesn't taste the food. The inspector checks the labels. If a label matches a recall, the inspector flags it. You then decide whether to swap the ingredient, wait for a replacement, or accept the risk with a documented justification.

The advisory database is not magic. It is maintained by the RustSec project and the broader community. Security researchers, crate maintainers, and users submit advisories. Each advisory goes through a review process. The database is public and open source. You can inspect the data yourself. This transparency means the tool is only as good as the community's vigilance.

Running your first audit

Install the tool using Cargo's standard installation mechanism. This adds the cargo-audit subcommand to your local cargo registry.

# Install the tool globally. This compiles and installs the binary to your cargo bin directory.
cargo install cargo-audit

# Run the audit in your project root. This reads Cargo.lock and compares against the RustSec database.
cargo audit

The output lists any vulnerabilities found. Each entry includes the advisory ID, the affected crate, the severity, and the recommended fix version. If no vulnerabilities are found, the tool prints a clean message and exits with code 0.

The tool relies entirely on Cargo.lock. If you run cargo audit in a fresh checkout without a lockfile, it will fail or produce incomplete results. Always commit Cargo.lock to your repository. This ensures that every developer and every CI runner audits the exact same set of dependencies. Skipping the lockfile means auditing a moving target, which defeats the purpose of security checks.

The anatomy of a finding

When cargo-audit finds a match, it displays structured information. Understanding this output helps you triage issues quickly.

Every advisory has a unique ID in the format RUSTSEC-YYYY-NNNN. The year indicates when the advisory was published. The number is a sequential counter. This ID is the primary key for the advisory. You use it to reference the issue in ignore lists, bug trackers, and security reports.

The severity field indicates the potential impact. Severities range from Low to Critical. The classification is based on the Common Vulnerability Scoring System (CVSS) or community consensus. A Critical severity usually means remote code execution, privilege escalation, or data leakage. A Low severity might mean a minor information disclosure or a theoretical issue with no known exploit.

The recommendation field tells you how to fix the issue. It usually points to a version of the crate where the vulnerability was patched. For example, upgrade to >= 1.2.3. You can apply this fix by running cargo update -p crate_name. This bumps the dependency to the safe version, provided your Cargo.toml constraints allow it.

Some advisories include keywords. These tags describe the type of vulnerability, such as denial-of-service, buffer-overflow, or injection. Keywords help you filter and categorize issues when you are managing a large project with many dependencies.

Configuring behavior and ignores

You will encounter situations where you need to control the audit behavior. Perhaps you are waiting for an upstream fix. Perhaps the advisory is a false positive for your specific usage. The tool provides flags and configuration files to handle these cases.

Use the --deny flag to control which severities cause the tool to exit with an error code. This is essential for CI pipelines where you want to block critical issues but allow low-risk noise to pass.

# Fail the build only on high or critical vulnerabilities.
# Low and medium issues are reported but do not break the pipeline.
cargo audit --deny high

Use the --format flag to change the output format. The default is human-readable text. For CI integration, JSON output is easier to parse and display in build logs.

# Output results as JSON. This allows CI systems to parse findings and create structured reports.
cargo audit --format json

For persistent ignores, create a .cargo-audit.toml file in your project root. This file allows you to whitelist specific advisory IDs. The tool reads this file automatically when you run cargo audit.

[advisories]
# Ignore a specific advisory.
# Always add a comment explaining why and when to remove this ignore.
ignore = [
    "RUSTSEC-2021-0001"
]

Convention dictates that every entry in the ignore list must have a comment. The comment should explain why the advisory is ignored and include a deadline or condition for removal. An ignore list without context becomes technical debt. Developers will not know why an ignore exists, and the vulnerability may linger indefinitely. Treat the ignore list as a tracked risk register, not a trash bin.

Integrating into CI

Automating the audit is the only way to ensure consistent security checks. Manual audits are easily forgotten. CI pipelines run on every pull request and merge, catching regressions immediately.

Add cargo audit to your CI configuration. Run it after dependencies are restored but before compilation. This fails fast if a vulnerability is introduced.

# Example GitHub Actions step
- name: Audit dependencies
  run: cargo audit --deny high

The exit code determines success or failure. Exit code 0 means no denied vulnerabilities were found. Any non-zero exit code indicates a problem. The --deny flag controls which severities trigger a non-zero exit. Without --deny, any vulnerability causes a failure. This is the safest default for production branches.

Use the --quiet flag in CI to suppress informational messages and reduce log noise. The tool still reports vulnerabilities, but it skips the banner and update checks.

# Run audit quietly. Only output findings and errors.
cargo audit --quiet --deny high

Integrating cargo audit into CI creates a security gate. Developers cannot merge code that introduces critical vulnerabilities. This shifts security left, catching issues during development rather than after deployment. It also educates the team. When a PR fails the audit, the developer learns about the vulnerability and the fix. Over time, this builds a culture of security awareness.

Pitfalls and limitations

cargo-audit is a powerful tool, but it has boundaries. Understanding these limitations prevents false confidence.

The tool only checks for known vulnerabilities. It cannot detect zero-day exploits or malicious code that has not been reported. If a crate is compromised and no advisory exists, cargo-audit will not flag it. This is a fundamental limitation of reactive security tools. You must complement cargo-audit with other practices, such as minimizing your dependency tree and reviewing new dependencies carefully.

False positives occur when an advisory applies to a crate, but your code does not use the vulnerable functionality. For example, a vulnerability might exist in a feature flag that you do not enable. cargo-audit does not perform static analysis of your code. It checks version ranges. If your version falls within the vulnerable range, it flags it. You must manually verify whether the vulnerability affects your usage. If it does not, you can ignore the advisory with a documented justification.

False negatives occur when the advisory database is incomplete or outdated. The database relies on community submissions. There can be a delay between a vulnerability being discovered and an advisory being published. Regularly update the tool to fetch the latest database. The tool checks for database updates automatically, but you can force an update with the --db-path flag or by reinstalling the tool.

The tool does not fix vulnerabilities. It reports them. You must apply the fixes manually or via cargo update. Some fixes may introduce breaking changes or require code adjustments. Always test after updating dependencies. Security fixes should not break your application.

Treat the advisory database as a living document. Update your tool regularly. Review ignore lists periodically. Remove ignores when fixes are available. Security is a continuous process, not a one-time check.

Decision matrix

Use cargo audit when you need a quick scan of your locked dependencies against known vulnerabilities. Use cargo audit --deny high when your CI pipeline must block critical issues but allow low-risk noise to pass for faster iteration. Use .cargo-audit.toml ignore lists when you have a verified false positive or are waiting for an upstream fix that is imminent. Reach for manual review when the advisory describes a vulnerability that requires context about your specific usage pattern to assess risk. Pick cargo update after cargo audit flags an issue to attempt an automatic resolution by bumping the dependency version. Use cargo audit --format json when you need to integrate findings into external reporting tools or dashboards.

Where to go next