Skip to content

Roadmap: Complete mediation — from lint plugin to Rust RFC #44

@bordumb

Description

@bordumb

Context

capsec implements 6 of 8 Saltzer & Schroeder design principles. The two it partially meets — complete mediation (#3) and least common mechanism (#7) — share the same root cause: Rust's standard library grants ambient authority by default. Any function can call std::fs::read() without asking permission. capsec can't remove that ability — only a compiler or language change can.

This issue outlines three progressively ambitious approaches to closing that gap.

Option 1: Lint plugin (buildable now)

Issue: #43

A dylint or rustc_private lint that flags std::fs/std::net/std::env/std::process calls in functions that don't have Has<P> bounds. Teams that enable #[deny(capsec::ambient_authority)] get compile-time enforcement.

This is not complete mediation in Saltzer & Schroeder's sense — the check is opt-in. But it's the practical maximum within Rust's current architecture.

Status: RFC filed as #43 with three sub-options (raw rustc_private, dylint, clippy.toml fallback).

Impact: Gets capsec to ~7/8 principles. Ships without any upstream Rust changes.

Option 2: Rust RFC — authority tokens in std

The ambient-authority crate (Dan Gohman, Bytecode Alliance) already proposed the pattern: ambient-authority functions take an AmbientAuthority token parameter.

// Current std (ambient authority — any code can call this)
let data = std::fs::read("secret.txt")?;

// Proposed (capability-gated — requires explicit authority)
let data = std::fs::read("secret.txt", ambient_authority())?;

If std adopted this convention, complete mediation would be built into the language. The key arguments:

Why this is realistic:

  • The Bytecode Alliance already wants this for WASI/Wasmtime — cap-std proves the API design works at scale
  • Rust RFC #1631 (pure functions / effect system) was closed with consensus: "pursue capability approaches" rather than a pure fn keyword
  • The keyword-generics initiative is discussing effect-like systems — authority tokens fit naturally
  • An edition boundary (Rust 2027?) could introduce the new APIs without breaking existing code — the old APIs would be deprecated, not removed
  • Cargo Scan (ESOP 2026) empirical data shows 3,434/10,000 top crates are already effect-free — most code wouldn't need any authority tokens at all

What capsec brings to the RFC:

  • Cap<P> / Has<P> is a working prototype of what authority-gated std APIs would look like
  • 13 Lean 4 soundness theorems formally verify the permission lattice — machine-checked proof that the design is sound
  • 90+ test adversarial security suite documenting every evasion vector — shows exactly what the current approach can and can't catch
  • Resource/pure crate classification (already implemented) demonstrates that the ecosystem can be partitioned
  • Production-tested across a real workspace with CI integration, pre-commit hooks, and SARIF output

What the RFC would propose:

  1. Add an AmbientAuthority zero-sized token type to std (or core)
  2. Add _with_authority variants of std::fs, std::net, std::env, std::process functions that require the token
  3. In a future edition, deprecate the ambient variants in favor of the authority-gated variants
  4. Provide ambient_authority() as the bootstrap function (equivalent to capsec's CapRoot::root())
  5. Let the ecosystem build finer-grained capability systems (like capsec's Cap<P>) on top of the coarse AmbientAuthority foundation

Impact: Gets Rust to 8/8 Saltzer & Schroeder principles. Every Rust program would have a single auditable point where ambient authority enters the system.

Option 3: Compiler flag for capability-restricted compilation

A cargo/rustc feature that restricts which std modules are linkable based on declared capabilities:

# Cargo.toml
[package.metadata.capsec]
classification = "pure"  # compiler rejects std::fs/net/env/process imports

This would work like #![no_std] but finer-grained — #![no_std_fs], #![no_std_net], etc. A crate marked pure simply cannot link against std::fs at all, enforced by the compiler.

Why this is harder:

  • Requires changes to Rust's module resolution and linking
  • std is currently monolithic — you get all of it or none of it (no_std)
  • Splitting std into capability-gated modules is a massive undertaking
  • Would need coordination with the libs team, compiler team, and cargo team

Why it might happen anyway:

  • The no_std ecosystem already demonstrates demand for partial std access
  • WASI's capability model requires exactly this kind of module-level gating
  • The modular std discussion has been ongoing since 2018 (see std-aware cargo RFC)

Impact: Complete mediation enforced by the compiler. The dream state — but requires Rust project buy-in and years of work.

Recommended sequence

  1. Now: Ship the lint plugin (Option 1 / RFC: Rustc lint plugin for ambient authority detection #43) — proves the concept, provides immediate value
  2. Next: Write a pre-RFC blog post citing capsec's Lean proofs, adversarial suite, and Cargo Scan data — build community support
  3. Then: Submit a formal Rust RFC (Option 2) proposing AmbientAuthority tokens in std — cite the lint plugin's adoption data as evidence of demand
  4. Long-term: If the RFC is accepted, Option 3 becomes a natural follow-on as part of modular std work

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions