Safety model

The safety model

What GUS defends against, what it doesn't, and where the boundary sits. If a claim here ever disagrees with the code or the drills, the code and drills win.

The core assumption

The model is not trusted. Not because models are malicious, but because everything a model reads is untrusted input: a fetched page, a file, an MCP server response, or a pasted chat message can carry instructions written by someone else (prompt injection), and the model's own memory of the rules can be silently trimmed by context compaction. So in GUS, no safety property is allowed to depend on the model behaving. Each one is enforced by a component the model cannot reach.

What's at stake

Governor modes: enforcing & permissive

SELinux had the right idea: an enforcement system people can relax while they learn it gets adopted; one they can only suffer gets uninstalled. GUS has two modes.

Enforcing (default)

Shield verdicts bind. Classifier parks and denies bind. This is the posture every install ships in.

Permissive

Everything is still scanned by Agent-Shield and classified by the policy layer — but a would-be block (Shield), park (approval), or deny (classifier) proceeds instead. Each let-through is recorded with what enforcing mode would have done: the gate log carries mode: "permissive" and wouldBe: "block" with the real verdict and its receipt, and classifier let-throughs land in permissive.jsonl. The panel shows today's count and the recent list; /mode in chat reports the same. It is the firewall-disable troubleshooting loop — except the thing you turned off keeps the receipts, so hardening again is an informed decision, not a guess.

Flip it in the panel (Status → Governor mode), the GUS.app menu, or by chat command (/mode permissive / /mode enforcing — operator-only; delegates are refused, like /stop and /update). One state file, read at every decision point, so a flip is live on the next action with no restart.

The floors no mode can cross

  • Vault reads stay denied. A secret entering model context is an irreversible disclosure, not a reversible action. The control plane floors it before the mode is consulted.
  • The spend caps still stop at the ceiling, and the kill switch still halts everything. Those are Governor mechanics — runaway insurance — not content policy. The mode never reaches them.
  • Scanning and receipting never turn off. A mode with no receipts is just an unaccountable agent, and that product is not GUS.
  • Some action classes are never delegable, in any mode: vault reads, deletes, installs, sends and posts, git push, sudo/kill-class shell, and keychain access. See approval delegation.

Threats and what stops them

ThreatMechanism
Prompt injection in fetched content or tool results tries to exfiltrate a credentialEgress allowlist + injection bindings: the credential can only ever travel, injected by the proxy, to its one bound destination; fetched content is Shield-scanned and vault-scrubbed before it reaches the model
The agent asks for a secret directly, or scrapes state for oneThere is no vault read API; the state volume is not mounted in the sandbox; the sandbox root filesystem is read-only with all capabilities dropped
A pasted secret in chat gets forwarded, stored, or loggedSecret-guard screens channel ingress and egress; a hit is refused, redacted in every store, and the user is warned to rotate
The agent forgets "ask first" (compaction, long context) and acts destructivelyClassification and approval live in the control plane's policy store, not in the model's context; approvals are hash-bound to exact arguments and single-use
A runaway loop burns the budgetGovernor caps (per-task / day / month) enforced by reservation before each call; the refusal is mechanical, not a request to the model
The operator says stop and the agent keeps goingThe kill switch is a persisted control-plane flag; every authorization checks it; in-flight spend freezes at the last settled call
A malicious or compromised skill / MCP serverInstall-time scanner gate (secrets, SSRF surfaces, injection directives, dependency risks); a do not install verdict has no override; runtime tool calls and results still cross the Shield gate
A bad or tampered update replaces a working agentSigned manifests (Ed25519) verified before staging; A/B slots; canary replay of the operator's own automations before promotion; automatic rollback; append-only data stores are never rolled back
DNS rebinding: an allowlisted name resolves to an internal address at connect timeResolve once per hop, pin the socket to a resolved address, verify the socket's actual peer against the resolved set; a mismatch discards the response unscreened
The control plane crashes mid-job and work is silently lost or double-runDurable job store; the boot sweep settles orphaned queued/running jobs failed-loudly with receipts; Governor orphan reservations are refunded at boot so caps never wedge
The Shield is down when a scan is requiredThe operator's recorded policy decides, stated at onboarding: fail-closed (default for tool calls) blocks the surface and mints no fake receipt; fail-open proceeds flagged, never pretending a scan happened

Out of scope — stated plainly