cargo-capsec
Static capability audit for Rust — find out what your code can do to the outside world.
What it does
cargo-capsec scans Rust source code and reports every function that exercises ambient authority: filesystem access, network connections, environment variable reads, process spawning. Point it at a workspace and it tells you what's happening — no annotations or code changes required.
Installation
From crates.io:
From source:
Quick start
# Audit your workspace
# JSON output for CI
# Only show high-risk and critical findings
# Fail CI if any critical findings
# Save baseline, then diff on next run
# SARIF output for GitHub Code Scanning
Output example
my-app v0.1.0
─────────────
FS src/main.rs:8:5 fs::read_to_string main()
FS src/main.rs:22:9 fs::write save_output()
NET src/api.rs:15:9 TcpStream::connect fetch_data()
ENV src/config.rs:3:5 env::var load_config()
Summary
───────
Crates with findings: 1
Total findings: 4
Categories: FS: 2 NET: 1 ENV: 1 PROC: 0
Configuration
Create .capsec.toml in your workspace root:
[]
= ["tests/**", "benches/**"]
# Custom authority patterns
[[]]
= ["my_crate", "secrets", "fetch"]
= "net"
= "critical"
= "Fetches secrets from vault"
# Suppress known-good findings
[[]]
= "tracing"
= "Logging framework, reviewed"
Limitations
- Use aliases:
use std::fs::read as r; r(...)— the import is flagged, but the bare aliased call may not be detected in all cases. - Method call matching is contextual:
.output(),.spawn(),.status()only flag whenCommand::newis in the same function..send_to()requiresUdpSocket::bind. Other method names not matched. - Proc macro generated code is not visible to the analysis. This is inherent to syntax-level tooling —
cargo expandsupport is on the roadmap. - No data flow analysis: Dead code will be flagged.
- FFI:
externblocks are detected but individual libc calls aren't categorized.
License
MIT OR Apache-2.0