Skip to content

[Medium] Cap-token budget axis is nominal; ReduceBudget does not limit real spend #362

Description

@gnanirahulnutakki

Summary

The cap-token cost caveat is not a spend control. It is verified against a fixed nominal constant (default 1), and the cost gate never reads VerifiedClaims.budget_remaining. As a result, AttenuationRule::ReduceBudget on a delegated token does not limit that delegate's real provider spend.

Evidence

  • crates/fused-runtime/src/runtime.rs:1040-1045RequiredCaveats { … cost: self.cost_units }; cost_units defaults to 1. Same at the other verify sites (:2188, :2841). crates/multi-agent/src/child.rs:121 hardcodes cost: 1.
  • The Biscuit check check if cost($c), $c <= budget therefore passes for any token with budget_remaining >= 1.
  • stage_cost_setup (runtime.rs:1338-1358) resolves the real ceiling from provisioning.budget / existing balance; claims.budget_remaining is consumed only as a Cedar attribute (cedar_attributes_from_claims, :2986-2989).

Design note

The in-code comment (child.rs:117-121) states this is intentional — the real per-turn ceiling is the CostEnvelope / cost-gate, not the cap-token caveat. The issue is the mismatch with operator expectation: ReduceBudget reads like a spend cap and is documented as an attenuation axis, but binds only the nominal cost=1.

Impact

An operator attenuating a delegated token with ReduceBudget(n) to cap a sub-agent's spend gets no real spend limit; the sub-agent can spend up to the subject's whole provisioned budget.

Suggested fix

Either feed the request's real projected envelope cost into RequiredCaveats.cost so the caveat bites, or resolve the cost-gate ceiling from min(provisioned, claims.budget_remaining). Document precisely what ReduceBudget binds. Add an E2E test that a ReduceBudget-attenuated token is denied once cumulative real spend exceeds the caveat.

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditFound by the 2026-07 Opus audit sweepbugSomething isn't workingcomp:securityCap-token / Cedar / trust substrateseverity:mediumMedium severity

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions