rust_secure_dependency_audit
Audit the dependencies of a Rust project for maintenance risk, license
compliance, and supply-chain health — usable both as a library and as a
secure-audit CLI for CI pipelines.
It is intentionally complementary to cargo-audit (CVE scanning) and
cargo-deny (advisories / bans): this crate focuses on how healthy
your dependencies are, not just whether they currently have a published
advisory.
What it tells you
For every dependency in your Cargo.lock, the audit produces:
| Signal | Sourced from |
|---|---|
| Health score | crates.io publish history + GitHub/GitLab repo activity |
| Status | Healthy / Warning / Stale / Risky |
| License risk | SPDX expression → permissive / copyleft / proprietary |
| Footprint risk | transitive dep count, feature count, build-deps |
| Security signals | OpenSSF Scorecard, SECURITY.md, yanked status |
You get a CLI summary, a JSON/Markdown report, and CI-friendly exit codes.
Installation
As a CLI
This installs the secure-audit binary.
As a library
[]
= "0.2"
= { = "1", = ["macros", "rt-multi-thread"] }
Quick start
CLI
# Audit the current directory and print a summary
# Show per-dependency detail
# Write a JSON report for downstream tooling
# CI gate: fail the build if anything scores below 60
# Skip dependencies you don't want to score (repeatable)
Tip: export
GITHUB_TOKEN(and optionallyGITLAB_TOKEN) before running to raise API rate limits. Without a token, GitHub allows only 60 requests/hour, which is not enough for medium-sized projects.
Library
use ;
use Path;
async
See examples/basic_usage.rs and
examples/custom_config.rs for more.
CLI reference
secure-audit accepts these global options (usable with any subcommand):
| Option | Default | Description |
|---|---|---|
-p, --project-path |
. |
Path to the Rust project to audit |
-c, --config |
— | Path to a TOML config file (see Configuration) |
--ignore <NAME> |
— | Skip a dependency (repeatable) |
-v, --verbose |
false |
Verbose logging |
-q, --quiet |
false |
Suppress the progress spinner (good for CI) |
Subcommands
scan
Run an audit and print a colourised summary.
| Option | Description |
|---|---|
--fail-threshold N |
Exit code 1 if any dependency scores below N (0–100) |
--detailed |
Print every dependency, not just the summary |
report
Generate a report file.
| Option | Default | Description |
|---|---|---|
-f, --format <fmt> |
markdown |
json or markdown (md) |
-o, --output <file> |
stdout | Write the report to a file |
check
CI gate. Exits with code 1 if any check fails.
| Option | Default | Description |
|---|---|---|
--min-health-score N |
60 |
Minimum acceptable health score |
--fail-on-copyleft |
false |
Fail if any dependency uses a copyleft licence |
--fail-on-unknown-license |
false |
Fail on missing / unrecognised licences |
How scoring works
Each dependency gets a 0–100 health score, a weighted average of five component scores. The defaults sum to 1.0:
| Component | Default weight | What it measures |
|---|---|---|
| Recency | 0.35 | Days since the last publish / commit |
| Maintenance | 0.25 | Repo activity, archive status, open-issues load |
| Community | 0.15 | Authors, stars, contributor count |
| Stability | 0.10 | Number of published versions, download count |
| Security | 0.15 | OpenSSF Scorecard (preferred); else SECURITY.md heuristic |
The score then maps to a status:
| Score | Status |
|---|---|
| 80 – 100 | 🟢 Healthy |
| 60 – 79 | 🟡 Warning |
| 40 – 59 | 🟠 Stale |
| 0 – 39 | 🔴 Risky |
Yanked crates are capped at 10 regardless of any other signal.
License risk buckets
Licences are normalised through SPDX and bucketed:
- Permissive — MIT, Apache, BSD, ISC, Zlib, Unlicense, …
- Copyleft — GPL, LGPL, AGPL, MPL, EUPL, OSL, EPL, CDDL, CC-BY-SA
- Proprietary — anything matching "proprietary", "commercial", "all rights reserved"
- Unknown — missing or unrecognised expressions
Footprint risk (0.0 – 1.0)
Useful for embedded, mobile, or WASM targets where binary size matters. Calculated from:
- transitive dependency count (40%)
- feature count (30%)
- build-script dependency count (30%)
Configuration
Pass a TOML config file with --config. All keys are optional — anything
you omit falls back to defaults.
[]
= 0.35
= 0.25
= 0.15
= 0.10
= 0.15
[]
= 180 # >180 days idle → "stale"
= 365 # >365 days idle → "risky"
= 2
[]
= ["MIT", "Apache-2.0", "BSD-3-Clause"]
= ["AGPL-3.0"]
= true
= true
[]
= 50
= 0.7
[]
= 30
= 3
= 100
= true
Then:
If scoring_weights doesn't sum to exactly 1.0, call
ScoringWeights::validate() from the library to surface the error, or
ScoringWeights::normalize() to rescale.
Environment variables
| Variable | Effect |
|---|---|
GITHUB_TOKEN |
Authenticated GitHub API calls (5000 req/h) |
GITLAB_TOKEN |
Authenticated GitLab API calls |
RUST_LOG |
Standard tracing filter (combine with --verbose) |
Caveats
- Network required. Scoring relies on crates.io, GitHub, GitLab, and OpenSSF APIs. Air-gapped environments aren't supported.
- Heuristics, not audits. A high score means signals look healthy,
not that the code is secure. Pair this tool with
cargo-auditand manual review for anything critical. - Rate limits. Set
GITHUB_TOKENfor non-trivial projects.
Contributing
PRs welcome. Areas where help is especially useful:
- Additional heuristics (e.g. release cadence, breaking-change frequency)
- More Git platforms (Gitea, Codeberg, sourcehut)
- Local caching of API responses
- Integration with
cargo-audit/cargo-denyadvisory data
Please open an issue first for non-trivial changes: https://github.com/emorilebo/rust_secure_dependency_audit/issues
License
Dual-licensed under either of
- MIT — LICENSE-MIT or https://opensource.org/licenses/MIT
- Apache 2.0 — LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0
at your option. Contributions are accepted under the same dual licence unless you explicitly state otherwise.