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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions