Problem
capsec currently detects ambient authority via AST-level pattern matching (cargo capsec audit). This misses cases where type information is needed — specifically, it cannot check whether a function calling std::fs::read() has a Has<FsRead> bound that makes the call authorized.
The goal: a lint that flags std::fs/std::net/std::env/std::process calls in functions that don't have Has<P> bounds, producing clippy-quality diagnostics with fix suggestions.
Desired UX
error: ambient authority: `std::fs::read` called without capability token
--> src/data.rs:12:5
|
12 | std::fs::read(path)
| ^^^^^^^^^^^^^^^^^^^ this performs filesystem I/O
|
= help: add a capability parameter: `cap: &impl Has<FsRead>`
= note: `#[deny(capsec::ambient_authority)]` on by default
Three options
Option A: Raw rustc_private lint plugin (nightly only)
Write a custom lint pass using rustc_private internals — the same approach clippy uses internally.
Pros:
- Full HIR access — can inspect function signatures for
Has<P> bounds
- Can provide rich fix suggestions (
#[rustfix]-compatible)
- Can resolve types, check trait bounds, follow impl blocks
- Maximum diagnostic quality
Cons:
- Requires nightly Rust —
rustc_private is unstable
- Breaks across Rust versions — internal APIs change without warning
- Ongoing maintenance burden: must track rustc releases
- Users must run via a custom driver binary (like
cargo-clippy itself)
Effort: High initial, high ongoing maintenance
Option B: dylint framework (nightly, but managed)
Use dylint (Trail of Bits) — a framework for writing and distributing third-party rustc lints.
Pros:
- Same HIR access as Option A (full type information)
- dylint handles toolchain management and lint distribution
- Lints are distributed as dynamic libraries — users install via
cargo install cargo-dylint
- Active maintainer (Trail of Bits), used by production projects
- Can produce the same rich diagnostics as Option A
Cons:
- Still requires nightly for
rustc_private under the hood
- Adds a dependency on the dylint ecosystem
- Less control over the driver than a fully custom approach
- dylint's own stability depends on Trail of Bits continuing to maintain it
Effort: Medium initial (dylint handles boilerplate), medium ongoing
Option C: clippy.toml + cargo capsec audit (stable Rust)
Use clippy's built-in disallowed-methods configuration to flag raw std::fs/std::net calls, combined with cargo capsec audit for deeper analysis.
Pros:
- Works on stable Rust — no nightly required
- Zero new code — clippy already supports
disallowed-methods and disallowed-types
- Users add a
clippy.toml to their project (capsec could generate it)
- Integrates with existing CI pipelines that already run
cargo clippy
Cons:
- No type information — cannot check for
Has<P> bounds
- Can only say "this method is disallowed" — no smart suggestions
- Cannot distinguish authorized calls (function has
Has<FsRead>) from unauthorized calls
- Essentially a blocklist, not an authority analysis
- The
ambient-authority crate already documents this exact approach
Effort: Low initial, low ongoing
Recommendation
Option B (dylint) as the primary path, with Option C shipped immediately as a stable-Rust stopgap.
- Ship a
capsec clippy-config command that generates a clippy.toml with all ambient authority methods disallowed (Option C — available today, stable Rust)
- Build a dylint lint crate (
capsec-lint) that uses HIR to check for Has<P> bounds on functions calling ambient authority APIs (Option B — nightly, but production-quality diagnostics)
- The dylint lint becomes the recommended path for teams that can use nightly; the
clippy.toml approach serves teams that require stable
References
Problem
capsec currently detects ambient authority via AST-level pattern matching (
cargo capsec audit). This misses cases where type information is needed — specifically, it cannot check whether a function callingstd::fs::read()has aHas<FsRead>bound that makes the call authorized.The goal: a lint that flags
std::fs/std::net/std::env/std::processcalls in functions that don't haveHas<P>bounds, producing clippy-quality diagnostics with fix suggestions.Desired UX
Three options
Option A: Raw
rustc_privatelint plugin (nightly only)Write a custom lint pass using
rustc_privateinternals — the same approach clippy uses internally.Pros:
Has<P>bounds#[rustfix]-compatible)Cons:
rustc_privateis unstablecargo-clippyitself)Effort: High initial, high ongoing maintenance
Option B:
dylintframework (nightly, but managed)Use dylint (Trail of Bits) — a framework for writing and distributing third-party rustc lints.
Pros:
cargo install cargo-dylintCons:
rustc_privateunder the hoodEffort: Medium initial (dylint handles boilerplate), medium ongoing
Option C:
clippy.toml+cargo capsec audit(stable Rust)Use clippy's built-in
disallowed-methodsconfiguration to flag rawstd::fs/std::netcalls, combined withcargo capsec auditfor deeper analysis.Pros:
disallowed-methodsanddisallowed-typesclippy.tomlto their project (capsec could generate it)cargo clippyCons:
Has<P>boundsHas<FsRead>) from unauthorized callsambient-authoritycrate already documents this exact approachEffort: Low initial, low ongoing
Recommendation
Option B (dylint) as the primary path, with Option C shipped immediately as a stable-Rust stopgap.
capsec clippy-configcommand that generates aclippy.tomlwith all ambient authority methods disallowed (Option C — available today, stable Rust)capsec-lint) that uses HIR to check forHas<P>bounds on functions calling ambient authority APIs (Option B — nightly, but production-quality diagnostics)clippy.tomlapproach serves teams that require stableReferences
clippy.tomlapproachcargo capsec audit— AST-level detection (current approach)