Check Cargo.lock for packages that are too new (supply chain risk) or too old (staleness/CVE risk).
cargo install cargo-oxidate --locked# As a cargo subcommand
cargo oxidate --min-age-days 14 --max-age-days 730
# Direct invocation
cargo-oxidate Cargo.lock --min-age-days 14 --max-age-days 730| Flag | Description |
|---|---|
--min-age-days N |
Flag packages newer than N days (supply chain security) |
--max-age-days N |
Flag packages older than N days (staleness) |
--exempt pkg1,pkg2 |
Comma-separated packages to skip |
--exclude-missing |
Don't flag packages with unknown publish dates |
--timeout N |
HTTP timeout in seconds (default: 10) |
--suggest-fix |
For "too new" violations, suggest cargo update commands to downgrade |
--include-prerelease |
Consider prerelease versions as suggestion candidates (requires --suggest-fix); ordinary SemVer requirements (e.g. ^1.2) still generally don't match prereleases, so most will still be rejected |
--cache-path PATH |
Enable response caching at PATH (or set CARGO_OXIDATE_CACHE_PATH) |
--cache-max-age-hours N |
Max age for cached version listings (default: 24) |
--quiet |
Suppress start and per-package progress messages |
--verbose |
Show each package as it is checked |
--format text|json |
Render the final result as text (default) or JSON |
At least one of --min-age-days or --max-age-days must be specified.
The final report goes to standard output. Progress, warnings, and errors go to
standard error. --quiet hides start and progress messages, while --verbose
shows each package check. The flags cannot be combined.
--format json writes one newline-terminated schema version 1 document. Its
status is passed, violations, or error, matching exit codes 0, 1, and 2.
The command also writes a document when it cannot load the lockfile. Consumers
should ignore unknown fields because schema version 1 may add fields.
Registry failures remain errors. Cache failures produce warnings and do not change the result.
--suggest-fix prints a cargo update --precise command for the newest eligible downgrade of
each package that is too new. It checks dependency requirements it can verify from Cargo.lock
and workspace manifests.
A candidate must be old enough, not yanked, older than the locked version, and in its compatible
version zone. The zone keeps the same major version, except that 0.x keeps the same minor and
0.0.x keeps the same patch. Prereleases are excluded unless you pass --include-prerelease or
the locked version is itself a prerelease.
Registry requirements come from the crates.io index. An optional registry declaration that cannot be confirmed active is shown as unverified. Target-specific registry declarations are enforced. For local and workspace manifests, the tool does not determine feature or target activation, so it treats every declared requirement, including optional and target-specific ones, as mandatory.
Suggestions are best effort. The tool does not run Cargo's resolver or build your project, so Cargo can still reject a suggested command. Apply suggestions in order, then run the command again and run your tests. For each package without a suggestion, the command explains which dependency blocks the downgrade or why it could not choose a version.
| Code | Meaning |
|---|---|
0 |
No dependency age violations |
1 |
Dependency age violations found |
2 |
Invalid input or incomplete required check |
Repeat runs can reuse crates.io API responses by passing --cache-path:
cargo oxidate --cache-path .cache/oxidate.json --min-age-days 14Per-version publish dates are cached indefinitely (they're immutable on crates.io). Per-crate version listings expire after --cache-max-age-hours (default 24h) so newly published versions are picked up.
This tool is also available as a GitHub Action. See examples/usage.yml or use it in your workflow:
- uses: timweri/cargo-oxidate@v0.2.1
with:
min-age-days: 14
max-age-days: 730
cache-responses: true # default; set to 'false' to disableWhen cache-responses is enabled (the default), the action caches crates.io responses using the selected Cargo.lock hash. Its compiled binary is cached separately by the referenced cargo-oxidate action version, so dependency changes in the consuming repository do not trigger a rebuild of this tool.
MIT