rust-dependencies
Manage Rust dependency governance at scale — version requirement strategy, crate and source selection, feature minimization, transitive dependency analysis, cargo-deny license/ban/advisory/source policy, cargo-audit, cargo-outdated, Renovate/Dependabot automation, dependency update cadence, cycle diagnosis, and supply-chain security. Use for dependency strategy, crate approval, license compliance, advisories, allowed sources, automated updates, or dependency-graph governance; hand Cargo manifest and registry configuration, lockfile mechanics, resolvers, and Cargo command behavior to rust-cargo-build, semver compatibility decisions to rust-semver, and lint policy to rust-style-clippy.
How do I install this agent skill?
npx skills add https://github.com/full-stack-skills/rust-skills --skill rust-dependenciesIs this agent skill safe to install?
- Gen Agent Trust Hubfail
The skill provides guidance on Rust dependency governance but contains a poisoned example lockfile ('examples/golden-deps/Cargo.lock'). This 'golden' reference includes non-standard dependencies injected into well-known crates, which is a significant supply chain security risk.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Rust Dependency Management and Governance
Authority: Cargo — Specifying Dependencies, Cargo — Dependency Resolution, Cargo — Source Replacement, Cargo — Credentials, cargo-deny, cargo-audit, RustSec.
This skill owns the governance of dependencies: how to declare them safely, what they pull in, who is allowed in, and what to do when one goes wrong. It does not own the Cargo.toml field reference (rust-cargo-build), semver (rust-semver), or workspace topology (rust-workspace).
Capability Boundaries
✅ Strengths
- Choosing the right version requirement (
"1"vs"1.2"vs"=1.2.3") - Evaluating dependency sources (crates.io / git / path / private registry)
- Setting up source replacement for vendored or mirrored registries
- Configuring
cargo-deny(4 tables: advisories, licenses, bans, sources) - Running
cargo-auditand responding to RustSec advisories - Diagnosing dependency cycles and duplicate-version problems via
cargo tree - Setting MSRV-aware resolver behavior
- Automating dependency updates with Renovate / Dependabot
- Establishing supply-chain policy for an organization
⚠️ Prerequisites
- Cargo manifest basics — see
rust-cargo-build - Semver vocabulary — see
rust-semver
❌ Out of Scope
- Cargo.toml field-by-field reference →
rust-cargo-build - Workspace layout →
rust-workspace - Clippy / lint policy →
rust-style-clippy - Testing dependency injection →
rust-testing
Data Privacy
This skill does not collect, store, or transmit user data. Private registry access and credential use are user-authorized actions; never log credentials or expose tokens in build artifacts.
Part 1: Version Requirement Syntax
Cargo uses SemVer version requirements (not exact versions) by default.
| Syntax | Meaning | Compatibility |
|---|---|---|
"1" or "^1" | >=1.0.0, <2.0.0 | Default — auto-update within major |
"1.2" or "^1.2" | >=1.2.0, <2.0.0 | At least 1.2.x |
"1.2.3" or "^1.2.3" | >=1.2.3, <2.0.0 | At least 1.2.3, may pull 1.5.0 |
"=1.2.3" | Exactly 1.2.3 | Pin — for reproducibility |
"~1.2" | >=1.2.0, <1.3.0 | Within minor only |
"~1.2.3" | >=1.2.3, <1.3.0 | Within minor only |
">=1.0, <2.0" | Range | Explicit bounds |
"*" | Any | Forbidden on crates.io — too loose |
"0.1" or "^0.1" | >=0.1.0, <0.2.0 | Pre-1.0: minor treated as major |
"0.0.1" | >=0.0.1, <0.0.2 | Pre-0.1: patch treated as major |
The default is caret (^)
[dependencies]
serde = "1" # caret by default
serde = { version = "1" } # same
This is usually right. You get bug fixes and non-breaking features automatically.
When to deviate
| Need | Use | Example |
|---|---|---|
| Pin for reproducibility | = | "=1.2.3" |
| Restrict to minor only | ~ | "~1.2" (no 1.3.x) |
| Bounded range | >=, < | ">=1.0, <1.5" |
| Pre-1.0 with breaking minors | minor pin | "0.7.3" (Cargo treats as <0.8) |
| Git head | git | { git = "..." } |
Caret rule for pre-1.0
# These are equivalent and both mean <0.2:
my-crate = "0.1"
my-crate = "^0.1"
# 0.0.x is even more restrictive:
my-crate = "0.0.3" # means >=0.0.3, <0.0.4 — almost a pin
The pre-1.0 rules exist because the SemVer spec treats 0.x as "anything goes." Cargo encodes community convention: minor bump in 0.x = breaking.
Part 2: Dependency Sources
crates.io (default)
[dependencies]
serde = "1"
Public, immutable, audited via crates.io. This is what 99% of dependencies should use.
Git
[dependencies]
# Branch / tag / rev / default
my-crate = { git = "https://github.com/user/repo", branch = "dev" }
my-crate = { git = "https://github.com/user/repo", tag = "v1.0.0" }
my-crate = { git = "https://github.com/user/repo", rev = "abc1234" }
my-crate = { git = "https://github.com/user/repo" }
Use sparingly: git deps make Cargo.lock non-portable, slow down CI, and cannot be published to crates.io unless the git dep is also published. Prefer crates.io, a fork published under a different name, or cargo vendor.
Path (local / workspace)
[dependencies]
my-core = { path = "../core", version = "0.1" }
Required for workspace internal deps. Always pair with a version for publishing (otherwise cargo publish fails).
Private registry
# .cargo/config.toml
[registries.my-registry]
index = "sparse+https://my-registry.example.com/index/"
[registry]
default = "my-registry" # optional: make this the default
# Cargo.toml
[dependencies]
my-private-crate = { version = "1.0", registry = "my-registry" }
Source replacement (transparent)
Cargo Source Replacement lets you replace crates.io with a mirror — without editing each Cargo.toml:
# .cargo/config.toml
[source.my-mirror]
registry = "sparse+https://mirrors.example.com/crates.io-index"
[source.crates-io]
replace-with = "my-mirror"
Use cases: enterprise proxy, China mirrors (RsProxy, tuna), vendored offline builds.
Vendored
cargo vendor vendor/ # downloads all deps to vendor/
# .cargo/config.toml
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor"
For air-gapped / reproducible builds. Check vendor/ into git (it's large but stable).
Part 3: Dependency Tree Analysis
cargo tree
cargo tree # full tree
cargo tree --depth 2 # limit
cargo tree --invert --package X # what depends on X?
cargo tree -e features # show feature unification
cargo tree -e no-dev # exclude dev-deps
cargo tree -e no-build # exclude build-deps
Finding duplicates
cargo tree --duplicates # show crates with multiple versions
If you see serde at both 1.0.180 and 1.0.195, that's two versions in the tree. Common causes:
- An old transitive dep requires an old version
- A git dep pulled in a specific version
- Your own version requirement is too tight
Resolving duplicates
cargo update -p serde # bump to latest matching req
cargo update -p serde --precise 1.0.200
If a transitive dep pins an old version, you can either:
- Update the transitive dep (
cargo update -p that-crate) - Live with the duplicate (usually fine)
- Replace the transitive with a fork
Detecting cycles
Cargo forbids cycles in the dependency graph. If you see:
error: cyclic package dependency: package `a` depends on `b`. package `b` depends on `a`.
You have a real design bug — restructure (often by extracting a shared crate c that both depend on).
Part 4: Dependency Update Governance
Use rust-cargo-build for current Cargo.lock version-control guidance and the exact behavior of --locked, --offline, and --frozen. The current Cargo Guide recommends committing Cargo.lock when in doubt; do not apply an application-versus-library prohibition here.
This skill owns how resolved dependency changes are proposed, reviewed, and approved:
cargo update # bump all to latest within reqs
cargo update --precise 1.0.200 -p serde # pin a specific version
cargo update --dry-run # see what would change
- Prefer package-scoped updates over unrelated graph churn.
- Review lockfile source, checksum, version, feature, and duplicate-version changes.
- Run advisories, licenses, bans, and source-policy checks on the proposed graph.
- Keep automated update pull requests bounded and observable.
- Use a separate scheduled compatibility lane when libraries need to test newly resolved dependency ranges.
- Never add an unconditional
cargo updateto required CI merely to make a stale lockfile pass.
Part 5: cargo-deny (Supply-Chain Governance)
cargo-deny is the de-facto tool for dependency policy. Four checks:
5.1 advisories — RustSec
# deny.toml
[advisories]
db-urls = ["https://github.com/rustsec/advisory-db"]
yanked = "deny"
ignore = [
# "RUSTSEC-2024-0001", # ignore specific advisory with justification
]
cargo deny check advisories
5.2 licenses — policy
# deny.toml
[licenses]
allow = [
"MIT",
"Apache-2.0",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
]
confidence-threshold = 0.93
[[licenses.exceptions]]
allow = ["Zlib"]
name = "some-zlib-crate"
version = "1.0"
cargo deny check licenses
Default is permissive; tighten to your org's policy.
5.3 bans — forbidden crates
# deny.toml
[bans]
multiple-versions = "warn"
wildcards = "deny" # don't allow "2.*" requirements
[[bans.deny]]
name = "openssl" # prefer rustls
version = "*"
[[bans.deny]]
name = "chrono"
version = "<0.5" # only old versions
[bans.workspace-dependencies]
duplicates = "deny" # require [workspace.dependencies]
cargo deny check bans
5.4 sources — where deps come from
# deny.toml
[sources]
unknown-registry = "deny" # disallow non-crates.io registries
unknown-git = "deny" # disallow non-allowlisted git sources
allow-registry = ["crates-io"]
allow-git = []
cargo deny check sources
All-in-one
cargo deny check # runs all four
CI integration:
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check
Part 6: cargo-audit
cargo-audit scans Cargo.lock against the RustSec advisory database.
cargo install cargo-audit --locked
cargo audit # scan
cargo audit --deny warnings # fail CI on warnings
cargo audit --ignore RUSTSEC-XXXX # ignore specific advisory
Difference from cargo-deny:
cargo-auditis advisory-only (security focus)cargo-denycovers advisories + licenses + bans + sources
Most projects use cargo-deny as a superset. Some use both (defense in depth).
Responding to an advisory
- Run
cargo auditto identify the vulnerable crate + version - Check RustSec for the fixed version
cargo update -p vulnerable-crate --precise X.Y.Z- If no fix exists: switch to a maintained fork, remove the dependency, or disable the affected feature
- File an issue upstream if it's a new vulnerability
Part 7: Automation
Renovate
Renovate auto-opens PRs when deps update. Supports Cargo out of the box:
// .renovaterc.json
{
"extends": ["config:recommended", ":semanticCommits"],
"schedule": ["before 6am on Monday"]
}
Dependabot
Dependabot is GitHub-native:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
Cargo's own auto-update
There's no built-in "cargo update PR" tool, but you can script it:
cargo update
git diff Cargo.lock
# Commit + push to a branch
Part 8: Feature Minimization
[dependencies]
serde = { version = "1", features = ["derive"] } # only what you use
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
Each enabled feature increases compile time, binary size, and attack surface. Disable defaults when you only need a subset:
[dependencies]
tokio = { version = "1", default-features = false, features = ["rt", "net"] }
Inspecting features
cargo tree -e features # which features are enabled, where
cargo tree -e features -p tokio # just tokio's features
If tokio shows up with [full] from a transitive dep, you're paying for more than you use.
Workspace dep governance
# root Cargo.toml
[workspace.dependencies]
serde = { version = "1", features = ["derive"] } # pin features once
# crates/abc/Cargo.toml
[dependencies]
serde.workspace = true # inherits feature set
Prevents feature drift across members.
Workflow
- Inventory —
cargo tree -e features,cargo tree --duplicates - Audit —
cargo audit(advisories) +cargo deny check(full policy) - Tighten versions — replace
"*"with"1"; pin exact only when reproducible - Minimize features —
default-features = false, list only what you use - Decide sources — prefer crates.io; reserve git/path for legitimate cases
- Configure CI —
cargo build --locked,cargo deny check, scheduledcargo audit - Automate updates — Renovate or Dependabot with semantic commits
Decision Shortcuts
| Question | Answer |
|---|---|
| Pin or caret? | Caret ("1") by default; pin ("=1.2.3") for reproducibility only |
| crates.io or git? | crates.io unless you have a specific reason |
| Use latest or wait? | Wait 1-2 weeks for new majors; auto-patch for patches |
Allow "*" requirements? | No — crates.io rejects them, and they hide upgrades |
How many versions of serde? | One. If duplicates, trace via cargo tree --duplicates |
| Commit Cargo.lock for a library? | No — downstream owns the lock |
CI: --locked or --frozen? | --locked for normal CI; --frozen for air-gapped |
Resources
- Cargo — Specifying Dependencies — full syntax reference
- cargo-deny Configuration Cookbook — 4-table policies
- Private Registry Setup — credentials, source replacement
examples/golden-deps/— a small crate with a minimal, audited dep set
Upstream Sources
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/full-stack-skills/rust-skills/rust-dependencies">View rust-dependencies on skillZs</a>