Security model and limits
This page sets out what the Agent SDK protects, where the boundaries are, and what it does not protect against. The limits are stated as plainly as the guarantees, because a security model you cannot trust at the edges is not one you can rely on.
The starting assumption
Component code is treated as hostile from its first instruction. That includes the agent harness, every tool, and anything a model persuades either of them to do. The design does not depend on the code behaving well. It depends on the code being unable to reach anything it was not granted.
Trust boundaries
A trust boundary is a line that code on one side cannot cross without the other side checking. The Agent SDK has four.
| Boundary | Between | What holds |
|---|---|---|
| Component and host | Each component and the host that runs it | A component reaches only what its grants allow. It has no ambient access to files, network, environment or credentials. |
| Workload and workload | Two workloads on the same host | Each workload has its own memory and its own virtual network. One session cannot read another's memory or reach its components. |
| Workload and host plugin | A workload and the shared host code that serves it, such as the model and session services | The host tells the plugin which workload is calling. A component cannot claim to be another. |
| Host and network | The host and everything outside it | Every peer is untrusted. Outbound requests go only to the hosts a component was granted. Loopback, link-local and cloud metadata addresses are blocked by default. |
Deny by default, granted per tool
Every component starts with nothing. Each grant is a deliberate addition: a folder, read only or writable; a list of hosts; a store; a secret by reference. An empty host list reaches nothing.
Grants belong to one component, not to the whole workload. In one session, a GitHub tool can reach api.github.com, a search tool can read one folder, and the harness next to them reaches neither. Capabilities explains why this is the boundary that matters.
The harness still holds every grant its tools hold, in one sense: it can ask a tool to use its grant. It cannot reach the GitHub API itself, but it can ask the GitHub tool to. So keep each tool's grant as narrow as its job.
The wall and the grants
Containers, gVisor and microVMs are isolation walls. A wall decides what gets out of the box. A grant decides what code can do inside it.
In four of this year's most widely reported agent escapes, none broke through a wall. Each agent used something it was allowed to do inside it: a package proxy it could reach, internet access left on, a test network left open, DNS lookups nobody blocked (sources). A stronger wall would not have stopped them. Narrower grants would have.
The two work together. Components run inside an ordinary pod, so the Kubernetes controls you already use (RBAC, admission, network policy, seccomp, a gVisor runtime class) still apply around them. The grants add a deny-by-default layer inside: each component starts with nothing and gets only what its job needs.
Credentials stay with the host
The host makes every model call with credentials the harness never sees. Secrets granted to a tool are named by reference and resolved by the host, so the value does not appear in a spec, a log or the conversation. See The host makes every model call for the details.
This means a tricked harness has no key to send anywhere. It can only ask the host to do things the session was granted.
Approvals add a check; the grant sets the limit
An approval is a decision made before something happens, such as adding a tool to a session or letting a tool change files. Approvals happen at gates the host owns, so a harness cannot fake one.
It helps to keep the two roles apart:
- The grant sets the limit. It is the most a tool can ever do. Nothing approved can exceed it.
- An approval adds a check inside that limit. It decides whether a particular step goes ahead.
In Desktop, you approve tools and folders, and only you choose folders. In Cosmonic Control, the workload spec is the approval and admission policy decides which specs are allowed, the same way it governs any other Kubernetes resource.
A record of every call
Because every model call and tool call passes through the host, each one can be recorded: what was called, with what arguments, and what came back, including failures. The session journal holds the conversation and each call in order. In Desktop, the session panel shows what a session can reach and every call each tool made.
Limits
These are the edges of the model. Knowing them is part of using it well.
- One isolation layer between tenants on a host. Workloads on the same host are separated by the WebAssembly runtime alone. For tenants who are actively hostile to each other, run them on separate hosts and control who may write their specs.
- Host plugins are shared. The code that serves models, tools, and sessions runs in the host and serves many workloads. A bug there could affect all of them.
- A sandbox does not stop prompt injection. A model can still be tricked by text it reads. The sandbox decides what a tricked agent can reach: only its grants, through the host, on the record.