Guides / Securing an agent
Securing an agent
A sandbox stops an AI agent from touching your computer. It does not stop the agent from misusing the things you gave it on purpose: an API key, a network connection, a set of tools. This page is the map of what kosa8 puts between an agent and each of those, which threat each layer answers, and where each one stops.
Why a sandbox alone is not enough
A kosa8 sandbox is a virtual machine with its own kernel. An agent inside one cannot read your files or reach your processes. Suppose that wall is perfect. The agent can still go wrong in five ways, because none of them involve getting through the wall.
- It can leak its key. An agent needs an API key to work. If the key is an environment variable in the sandbox, the agent can read it, and so can every package it installs and every script it is talked into running. Anything that can read a key can send it somewhere.
- It can say anything to a host it is allowed to reach. A rule that says "this sandbox
may reach
api.example.com" is, underneath, a rule about addresses. It says nothing about which request is made, on which port, or what is uploaded. - A tool can give it new instructions. A tool server describes each tool in text the model reads. A server can change that text after you approved the tool, and the model will follow the new version.
- It can call a permitted tool with harmful arguments. "May call
create_issue" does not say in which repository. "May callrun_query" does not say which query. - It looks like every other agent. If three agents share a machine and one misbehaves, a log that says "an agent did it" tells you nothing.
- The key is in the sandbox, so whatever runs in the sandbox can read it.
- A host you allowed will accept any request the agent sends it, with the key or your files in it.
- One address often serves many sites. A rule about addresses admits all of them.
- A tool's description is text from a stranger that the model treats as instructions.
None of this is a flaw in the virtual machine. It is the difference between isolating a program and governing what it does with what it holds. The rest of this page is about the second.
The layers
kosa8 answers each of those with a separate control, and all of them except the first run on
your side of the boundary (the guard and broker in the kosa8d service, the tool checks in
the kosa8 mcp serve gateway), where nothing inside the sandbox can reach them. That placement is the point: a rule the agent could edit is a suggestion.
- The agent runs in a virtual machine of its own. It sees one folder and no key.
- Anything it sends to the network passes the guard, then the broker, which admits hosts by name and adds your key on the way out.
- A tool is offered only while its definition is the one that was approved, and a call's arguments must fit the approved schema.
- Your organisation's signed rules decide the call by its arguments: allow, deny, or ask.
- A call a rule answers "ask" waits for a person. The approval covers exactly that call, once.
- Each decision is written to a log the agent cannot edit.
- A refusal at any layer ends the action there.
- An allowed action is recorded as well, so the log answers "what did it do", not only "what was stopped".
The picture shows the layers in the order an action could meet them. Which ones apply depends on the action. Network traffic from a sandbox meets layers 1 and 2. A tool call made through kosa8's MCP gateway meets layers 3, 4 and 5. (MCP, the Model Context Protocol, is how an AI client is given tools.) Both are recorded in layer 6.
acme/*
repositories", "merging needs a person". Deny beats ask beats allow. See
Tool rules.kosa8 mcp asks shows it; kosa8 mcp approve ID approves exactly that
call, for one use, for ten minutes. See Tool rules.kosa8 audit verify proves nobody edited it. See
The audit log.Threats and what answers them
Read the last column before the first two. "Partly" is the honest answer more often than "yes".
| Threat | What answers it | How far |
|---|---|---|
| Prompt injection sends your data out |
The sandbox starts with no network, or a short list of named hosts. Everything else is refused on your computer and logged. See Network rules. | partly The agent can still send anything it can read to a host you allowed. Request bodies are not inspected. Allow few hosts, and none that accept uploads. |
| Stolen API key | The egress broker keeps the key on your computer. The sandbox holds a placeholder that is worthless anywhere else. See Keep API keys out of the sandbox. | yes for the brokered kits: the key cannot be read from inside.
partly for spending: while the sandbox runs, the placeholder buys
whatever the route allows. The copilot kit still passes its token in. |
| Tool poisoning, or a "rug pull" |
Tool definitions are pinned by digest. A changed or new definition is withheld until a person
reviews it with kosa8 mcp pins diff. See
Tool servers. |
partly The first definition a server gives is taken on trust, unless your organisation's policy lists the pins. Text a tool returns is checked for shape, not for hidden instructions. |
| Over-broad tool use | Argument rules: a call is allowed, denied or held for a person by what its arguments say. They apply to kosa8's own tools too. See Tool rules. | yes for what you wrote a rule for. A rule you did not write protects nothing; kosa8 does not guess which calls are dangerous. |
| Malicious package in the agent's install |
Built-in kits install one pinned version, checked against its SHA-512 before anything runs.
A kit whose setup downloads anything else is refused unless you pass
--allow-unpinned. See Kits. |
partly The pin covers the package's own tarball. Its dependencies are resolved by npm at install time, and images are still named by tag. |
| An agent pretending to be another |
An identity the service verifies: a token minted with kosa8 agent token create.
A bad, expired or revoked token is refused, not served anonymously. See
Agent identity. |
partly Tokens are bearer tokens: whoever holds one is that agent. A process running as you on your computer can still call the service as a person. |
| "What did it do?" | The audit log records brokered requests (host, port, method, path, status), every command with the SHA-256 of its exact arguments, and tool decisions. See The audit log. | partly Never bodies, never query strings, never the environment. Inside an encrypted tunnel only the host, port and byte counts are known. Entries are rate-limited, with a count of any held back. |
Get the essentials in five minutes
Three things are worth seeing with your own eyes: the key is not in the sandbox, a request that should be refused is refused, and both facts are written down.
Run a brokered kit
With your key in your shell's environment as usual, start a built-in kit. Flags go before the kit name.
$ kosa8 agent run -w ~/code/api claude kosa8: kit claude (node:22-alpine) kosa8: workspace /Users/you/code/api -> /work (nothing else on the host is visible) kosa8: network closed except through the egress broker: registry.npmjs.org, statsig.anthropic.com kosa8: brokering ANTHROPIC_API_KEY -> api.anthropic.com (the sandbox holds a placeholder, never the key) kosa8: sandbox claude-44059 ready in 653ms kosa8: pulling node:22-alpine kosa8: running kit setup, then: claude
Those lines are the contract for this run: which folder is visible, which hosts are
reachable, and where the key is. To read them without starting anything, add
--dry-run.
See that the key is not inside
Ask the agent to print its environment. Where the key used to be there is a placeholder, and
the API's address has been replaced by an address on the sandbox's own private network. This
is from a test kit with one brokered credential named echo:
ECHO_KEY=kosa8-placeholder-1803c857986afe6bc9f59600e4d6f6f8
ECHO_URL=http://192.168.127.254:57504/echo
HTTPS_PROXY=http://192.168.127.254:57504
In the claude kit the same two values arrive as
ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL. A request sent to that
address with the placeholder reaches the real API with the real key, which was added on your
computer. The same placeholder sent anywhere else is a random string.
See a refused request in the audit log
From inside that test sandbox, a request to a host that was not listed came back
HTTP/1.1 403 Forbidden, and a connection that tried to go around the broker
altogether got Connection refused. On your side, both are in the log:
$ kosa8 audit ls --json # the action and detail of three of the entries sandbox.egress.allow {"kind":"route","host":"httpbin.org","port":443,"method":"GET","path":"/headers","route":"echo","status":200,"bytes_in":225} sandbox.egress.deny {"kind":"http","host":"neverssl.com","port":80,"method":"GET","path":"/","reason":"host not in allow-list"} sandbox.egress.deny {"kind":"connect","host":"evil.example","port":443,"reason":"host not in allow-list"} $ kosa8 audit verify audit chain intact: 17 entries verified
The first line is the allowed request. It names the route and the path, and it does not
contain the key. kosa8 audit verify walks the chain and tells you whether any
entry was altered or removed.
For an organisation
Every layer above works on one person's computer with no setup. An organisation can go further and make them mandatory with a signed policy that a developer's machine enforces and cannot weaken:
require_sandboxrefuses containers outside a sandbox.default_egressis applied to any sandbox created without a network rule of its own.allowed_registriesis checked wherever an image is fetched.allowed_mcpis checked when a tool server is registered and again when it starts.require_agent_identityrefuses agent requests that carry no token.- Where a signing key is pinned, a kit file runs only if it is signed by that key
(
kosa8 agent sign).
See Governance and the Policy reference.
What kosa8 does not protect against
A control believed to do more than it does is worse than none. These are the edges, stated plainly.
What this does not do
- The placeholder is a spendable capability. The agent cannot read your key, and it can still use it: any request the route's methods and paths admit is made with the real credential, for as long as the sandbox runs. The broker cannot tell a good request from a bad one. Narrow the route, and scope the key itself at the provider.
- An encrypted tunnel is opaque. For HTTPS to an allowed host the broker sees a name and a port, then TLS it does not open. There is no method or path filtering inside it, no request log beyond byte counts, and no check that the name inside the tunnel is the name that was asked for. An allowed host that accepts uploads is a way out for data.
- Nothing reads content. Request and response bodies are not inspected in either direction. A tool's result is checked against its declared shape, not searched for instructions. Prompt injection hidden in well-formed text reaches the model.
- A process running as you on your computer is out of scope. The service's socket is
yours. A program running under your account can call it as a person, read
~/.kosa8, and approve a held call. The terminal check onkosa8 mcp approvestops an agent approving its own call through a pipe, and nothing more determined. Keep agents in sandboxes; that is what the sandbox is for. - First-use pinning trusts the first definition. If a tool server is hostile the first time it is started, its definitions are pinned as they are. Pins listed in your organisation's signed policy remove that gap; local pinning alone does not.
- Not every agent can be brokered. Brokering needs a command-line tool that accepts a
base URL. The Copilot CLI does not, so that kit passes
GITHUB_TOKENinto the sandbox, andkosa8 agent runsays so every time. - A sandbox you create by hand is open by default.
kosa8 sandbox createwith no network flag has an unrestricted network unless your organisation setsdefault_egress. Only sandboxes an agent creates, and brokered kits, are closed by default.
Where to go next
Keep API keys out of the sandbox
How the broker lets an agent use a key it never holds.
Network rules
What a sandbox can reach, and where that is enforced.
Tool rules
Decide a tool call by its arguments, and hold some for a person.
The audit log
What is written down, and how to prove nobody edited it.