security

What spore assumes, what holds a turn — the agent's work on one message — and where the boundary stops. This page follows SECURITY.md in the spore repository, which has the full text.

the axiom

The agent is untrusted. Anything it reads — a web page, a document, a message, a tool's output — can steer it, so spore treats what it runs as possibly hostile and confines it. The operator is trusted: the Unix user spore runs as, who writes ~/.config/spore/, the definitions and the host's settings. The trust boundary is that user. Another unconfined process of the same user can read every workspace and every key; spore does not defend against it.

SECURITY.md, “What spore assumes”

Spores of different customers can share that user, each confined from the host and from the others' workspaces; operators who must not trust each other need a Unix user, or a VM, each.

what confines a turn

Every turn's agent, and everything it runs, is held by the Linux kernel itself, not by the list of tools it was given. On macOS that Linux kernel is the VM's, on Windows WSL's; the boundary is not weaker for it.

files (Landlock)
Landlock limits the files a process can reach. An agent writes only its write islands — the folders of its own workspace it may write to — and the directories its definition writes. It cannot read ~/.config/spore/ or another spore's workspace. /tmp is not granted.
processes (namespaces)
Each turn, job command and router command runs in user, PID and mount namespaces of its own — a separate view of the system — and sees only the processes it started. A host that cannot provide them runs no turn, unless the operator switches the contain setting off.
syscalls
A filter refuses certain requests to the operating system (system calls): making or joining namespaces, mounting, keyctl (the Linux kernel's key store), bpf (loading programs into the Linux kernel), and the like, whatever the surrounding container allows.
ports
TCP bind is refused (Linux 6.7+), so nothing an agent runs listens on a TCP port.
not as root
spore runs no turn, job or router as uid 0, the root user.
signals and abstract sockets (Linux 6.12+)
An agent can signal, and reach over abstract sockets (local sockets with no file on disk), only its own turn's processes.

credentials

No provider key, bot token or source secret reaches an agent's environment. Model calls go through brokers — go-betweens in spore's runner — which hold the credentials and demand a key minted for that one turn.

Keys go in ~/.config/spore/environment; the agent never sees the value. The HTTP API listens on a unix socket (a local connection point that is a file) or a loopback address (reachable only from this machine) and demands a token on every request.

the record

  • Spend is settled — counted and recorded — per turn. A turn stops taking new model calls once its settled spend reaches its definition's hard cost, the spending cap it sets.
  • Events, the log of what each turn did, are appended out of the agent's reach.
  • ~/.config/spore/, where the configuration and the keys live, is unreadable to the agent.

where the boundary stops

These are accepted risks. They are stated here as SECURITY.md states them.

  • The network is open by design. spore bounds what an agent can read and holds no secret it could leak, but not where it connects.
  • An agent can connect to any unix socket its process can see and any TCP port on the host.
  • Spores of one user can reach each other through UDP ports and unix sockets.
  • Metadata endpoints (addresses where a cloud host serves information about itself) reachable from the host are reachable from an agent.

not in scope

  • a malicious operator
  • unconfined processes of the same user
  • Linux kernel and container-runtime vulnerabilities
  • what a model provider does with what it is sent
  • a turn of a spore whose definition, spore.cmk, says unconfined: true

The full text is in SECURITY.md.