Security
The limits live outside the VM.
An agent that has been tricked by a prompt has full control of its own sandbox. So the rules that matter run on the host, where that control does not reach.
This page says what runner does by default, what it does when you turn a control on, and what we have not done. We wrote it from the code, not from our roadmap.
What is true today
| One microVM for each sandbox | Shipped |
| Snapshots stored off the host | Shipped |
| Domain allowlist for a sandbox, enforced on the host | Shipped |
| Credential proxy | On for new accounts |
| Deny-by-default egress for a whole organization | Org switch, off by default |
| Spend caps | Per member only |
| Account-wide audit log | Partial |
| Independent penetration test | None published |
Defaults, stated exactly
| Control | Default | When you turn it on |
|---|---|---|
| Egress | Open to public addresses until an owner turns on the organization-wide deny-by-default switch. The switch is off for every account until then. | With the switch on, each new sandbox can reach only the names on your organization's list, through the host's egress proxy. With an empty list it reaches nothing. Only an owner can change the switch. |
| Credential proxy | On for new accounts, free on every plan. Accounts that already exist keep the setting they had. | The key never enters the VM. The sandbox holds a placeholder and the host swaps in the real key. |
| Always on, for every sandbox | The host's kernel blocks private networks, loopback, link-local addresses and cloud metadata, IPv6 ranges that embed IPv4 addresses, runner's own infrastructure, other sandboxes and the outbound mail ports (25, 465 and 587). No setting opens them. | |
The organization switch applies when a sandbox is created. Turning it on does not change sandboxes that already exist, and turning it off does not open the ones that took it. A sandbox's own allowlist can only be stricter than the organization's, never looser.
Isolation
Each sandbox is its own Firecracker microVM with its own guest kernel. Firecracker runs under the jailer as an unprivileged user, in its own chroot and cgroup, with Firecracker's default seccomp filters.
The wall is only as strong as Firecracker, KVM and the host kernel. We do not test for escapes through them. All VMs on a host share one unprivileged user.
Rules only get stricter
The host decides first and the sandbox second. A sandbox's own policy can add limits and can never remove one. An allow entry that falls inside an always-blocked range is refused when you create the sandbox.
A domain policy is set at create and cannot change on a running sandbox.
How the credential proxy works
- The sandbox gets a random placeholder in a variable such as
ANTHROPIC_API_KEY. - Its request is redirected to the egress proxy on the host.
- The proxy puts the real key in the
Authorizationorx-api-keyheader, for that key's own host, for the sandbox the placeholder was made for. - The request goes on over HTTPS with the provider's certificate checked. In the response, the key is swapped back to the placeholder.
What it does not do
- The sandbox cannot read the key, but it can still use it. We have not built per-task call budgets or an audit log of proxied calls.
- Keys in the query string and signed requests (AWS SigV4) are not supported yet.
- A provider that echoes the key in a success response hands it back to the sandbox.
- While a sandbox lives, its keys sit in plain text in the host's record of it.
- A Claude or ChatGPT subscription sign-in and Amazon Bedrock cannot be proxied. If your agents use those, turn the proxy off. We tell you why when a prompt is refused.
The egress proof
Our acceptance gate starts real sandboxes on a real host and tries, from inside them, to reach what a sandbox must not reach: the metadata service, private networks, runner's own infrastructure, other sandboxes and the mail ports. A blocked connection only counts if the same sandbox first shows it can reach the public internet.
- The last full run passed 57 of 57 checks, on 2026-10-19.
- A separate run of 39 domain-allowlist checks also passed.
- Neither ran on today's code. The network policy and the checks have changed since. We plan to run the full set again on current code and publish the result here.
So read 57 of 57 as proof about the code we tested in October, not a guarantee about the code you run.
What we have not done yet
| Account-wide audit log | Partial | Each sandbox keeps a history of state changes and commands. There is no log of who changed settings, keys or members, and none of proxied provider calls. |
| Independent penetration test | None published | We have not had one done. |
| Per-sandbox and organization spend caps | Not built | Per-member monthly caps exist. |
Security questions, or a questionnaire to fill in? Write to support@runner.so.