TINY(1)General Commands ManualTINY(1)

Threat model

tiny runs an LLM agent with its own permission prompts disabled, inside your cluster. That sentence should worry you; this page is what we do about it, and what we don't.

Assumptions

We assume the agent can be prompt-injected — by a repo it cloned, an issue it was fed, or a dependency README — and will then try to do whatever the injected text says. The design question is what such an agent can do, not whether it might try.

What a session pod holds

  • The agent credential (Claude or OpenAI token) — needed to run at all.
  • Its own workspace volume.
  • A localhost MCP sidecar whose Kubernetes permissions are: create Question objects, read Sessions and pods in the namespace, update its own Session's status. The ServiceAccount cannot read secrets or ConfigMaps (so it cannot widen its own egress allow-list), and cannot exec, delete, or create anything else.
  • A restricted container: runtime seccomp profile, every capability dropped, no privilege escalation, non-root. --unconfined lifts the first two for rootless buildah, per session, and nothing else.

What a session pod does not hold

  • Git credentials. Cloning uses a deploy key that is mounted read-only when you configured one; pushing does not happen from the pod at all. Work leaves as git bundles that a separate, short-lived CI job pushes after rebasing.
  • GitHub API tokens. PRs and comments are made by the courier job with a token that expires when the job ends.
  • Cluster credentials. Spawning a session, enabling an add-on — every such action parks as a Question and runs with the credentials of the human who answers, or not at all.

Known holes, honestly

  • The agent credential is in the pod. An injected agent could burn your Claude/OpenAI quota, or send the token to any host the egress policy lets it reach. Scope it: use a dedicated account, and switch on the hostname allow-list so "any host" becomes a short list.
  • HTTPS out is open until you narrow it. The default policy closes the metadata endpoint, private address space and every port but 80 and 443, but a NetworkPolicy matches addresses, and the agent must reach its model API. The allow-list closes this, and DNS with it, by making the proxy the session's only resolver. Allow-listing github.com still means an agent can write to a gist.
  • The agent's own tool calls are not intercepted. It runs with bypassPermissions; asking is cooperative. The boundary is the pod, the missing keys, the restricted container and the policy — not the gate.
  • kubectl exec into the pod is your cluster's RBAC, not ours. Anyone who can exec into pods in the namespace can read the workspace.
  • The gate is only as careful as its humans. Approving a spawn you didn't read is still an approval, audited under your name.
  • The house rules are conventions. The model usually follows "ask before anything hard to undo"; the guarantees come from the missing credentials, not from the model's manners.

The exec surface

The courier lists and downloads bundles over the Kubernetes exec API. That call is argv-only, and bundle names must match ^[A-Za-z0-9][A-Za-z0-9._-]*\.bundle$ — agent-written text never reaches a shell.

Found something we missed? Open an issue; that's what the repo is for.