Sandboxes, Permissions, Approvals, and Rollback

Objectives

  • Separate capability, identity, policy, approval, and sandbox into independent control layers.
  • Tier actions by their side effects instead of tool names.
  • Define stopping, approval, rollback, or compensation strategy for irreversible work.

Why “the model will be careful” is not a security control

An environment-based Agent handles user instructions together with untrusted webpages, documents, issues, and terminal output. The model may misunderstand, follow prompt injection, or continue an old plan after state changes. A prompt saying “do not delete files” cannot stop an adapter that has delete permission; a sandbox cannot replace business authorization when an isolated environment can still message a real API or place an order.

Controls must be combined outside the model: identity answers “who”; capability describes “what can be requested”; policy decides “is it allowed in this context”; approval handles a specific decision a human must own; sandbox limits blast radius; and receipt/audit records what actually happened.

Identity, delegation, credentials, and approval are four different pieces of evidence

EvidenceIssuer or verifierWhat it must bindTypical error
Subject identityIdentity provider, trusted session, or service identityUser/service subject, tenant, authentication strength, session/service IDTreat model-claimed username or page avatar as identity
Delegation/capabilityPolicy service or runtimePurpose, tool/resource scope, budget, expiry, runGive an Agent a human administrator’s long-lived global token
Adapter credentialCredential service and adapterThis environment only, minimal scope, short lifetime, revocabilityInfer any site/system is operable because “the user is logged in”
ApprovalTrusted approver or workflowOne normalized high-impact intent, target, amount/data range, current environment, nonceTreat “allow continuation” or model output as a general approval

Runtime records should preserve integrity-protected, verifiable correlations among subject, delegation, adapter actor, policy decision, approval, and receipt for later reconciliation. Audit does not mean indefinitely copying full prompts, pages, files, tokens, and PII into logs. Define classification, minimum retention, protected raw-content location, hash/digest, redaction rule, and reader permission for every field. When necessary safety evidence for a high-impact action cannot be written, fail closed or hand off to a human according to risk rather than proceeding silently.

How to implement it

Risk tierExampleDefault controls
Read-only, low sensitivityRead an allowed directory or query test stateScope allowlist, rate/budget, audit
Reversible local writeEdit a file in an isolated worktreeSnapshot/diff, idempotency, path restriction, automatic rollback
Compensable external writeCreate a draft or cancellable appointmentExact identity, preview, idempotency, compensation step, required approval
Irreversible or high impactPay, send, delete, publish, change permissionDeny by default; strong identity, short-lived exact approval, two-person or human execution

An approval object should contain task/run/policy; action ID, kind, and normalized parameter digest; idempotency key; target identity/path/origin; amount or data range; environment instance ID; state fingerprint/generation; expiry; approver; and one-time nonce. Any critical field change invalidates approval. Matching a version number alone does not prove the environment remains in the state that was approved.

An approval record must not be an optional field in the model action schema. This course runtime makes Action.from_dict fail closed for unknown fields. Model-external register_approval receives evidence and verifies it with a trusted approver’s HMAC key. Its signed payload binds task_id, run_id, policy_version, action_id, idempotency_key, intent_digest, environment_version, environment_instance_id, state_fingerprint, environment_generation, expires_at_proposal, expires_at_unix_ms, and nonce.

Proposal-count expiry limits the last proposal at which a record is valid (equality is valid); trusted wall-clock expiry prevents approval remaining valid forever when the Agent stops proposing (the exact expiry instant is invalid). The runtime consumes the nonce when an action passes the authorization gate. If a write enters pending, it checkpoints complete signed evidence and the consumed set. Recovery revalidates the signature, trust root, and state binding but does not mistake expired historical evidence for a corrupted checkpoint: pending execution remains frozen. Only refresh_pending_approval with fresh trusted evidence bound to the same action/key/intent/instance/fingerprint/generation can replace active evidence, while the old evidence remains in the trace. Unknown issuer, signature tampering, replay across task/run/policy/action/idempotency key, same version but different state, automatic execution after expiry, and attempts to use idempotent replay to bypass approval all fail closed.

Boundary of teaching HMAC

Symmetric HMAC is used only to demonstrate that issuance authority is outside the model process. A production system normally needs a separate approval service, KMS/HSM, or verifiable asymmetric signatures, with issuance, registration, consumption, revocation, and key rotation audited. If the model can read the approval key, all field binding becomes meaningless.

Rollback depends on the environment: a browser draft can be deleted or withdrawn, a desktop file can be restored from a snapshot, and code can apply an exact inverse patch. External messages, payments, and data disclosure often cannot be truly rolled back; they need compensation or incident response, so preview and approval need to be stronger before execution.

Common failures

  • The Agent uses a human administrator account and all tools share one long-lived token.
  • Approval says only “continue,” or the model generates an approval field with its action; it remains valid after target, amount, or content changed.
  • The sandbox allows arbitrary network access, so file-system isolation does not prevent data exfiltration.
  • Text in a webpage, issue, or test output is promoted into an authorization source.
  • A non-idempotent write is retried; a rollback script overwrites a user’s newer changes.
  • Success logs exist, but refusal, approval, cancellation, takeover, and recovery audit does not.

How to validate

Build an authorization matrix: test allow and deny for every identity/action/scope pair, and assert denial happens before side effects. Independently tamper with signature, task/run/policy/action, idempotency key, intent, environment instance, state fingerprint/generation, and both expiry kinds; verify that a consumed nonce cannot replay before or after checkpoint recovery. Also test “same version but different content,” “same state but another environment instance,” “wait without new proposals until wall-clock expiry,” “expired pending remains non-executable after recovery until fresh exact approval,” and “existing receipt without new approval.”

Inject indirect prompts, network exfiltration, path traversal, symlink/redirect, repeated requests, and human cancellation, then inspect result and environment diff. Exercise compensation rather than merely verifying that a revoke button exists.

Practice task

For “read a ticket, draft a response, send email,” design three capabilities: read ticket, save draft, and send. Specify identity, data scope, network destination, idempotency key, and approval for each. Prove hostile ticket content cannot change the recipient; changing body or recipient after approval triggers reapproval; and a send timeout checks receipt before resending.

References