Secrets let you pass API keys, tokens, and credentials into sandboxes without the real values ever entering the VM. They are encrypted at rest, sealed into opaque tokens at boot, and only revealed by a host-side proxy on outbound HTTPS requests.
How it works
The real secret value only exists in the host-side proxy’s memory — it is never written to disk, never sent to the VM, and never visible via env or /proc inside the sandbox.
Quick start
Create a secret store, add a secret, and launch a sandbox that uses it:
import { Sandbox, SecretStore } from '@opencomputer/sdk';
// 1. Create a secret store with egress restrictions
const store = await SecretStore.create({
name: 'my-agent-secrets',
egressAllowlist: ['api.anthropic.com'],
});
// 2. Add an encrypted secret
await SecretStore.setSecret(store.id, 'ANTHROPIC_API_KEY', 'sk-ant-...');
// 3. Create a sandbox — secrets are injected as sealed tokens
const sandbox = await Sandbox.create({
secretStore: 'my-agent-secrets',
timeout: 600,
});
// Inside the VM, the env var is sealed — not the real key
const result = await sandbox.exec.run('echo $ANTHROPIC_API_KEY');
console.log(result.stdout); // "osb_sealed_7f3a9c..."
// But HTTPS requests to allowed hosts get the real value via the proxy
const apiResult = await sandbox.exec.run(`
curl -s https://api.anthropic.com/v1/messages \\
-H "x-api-key: $ANTHROPIC_API_KEY" \\
-H "anthropic-version: 2023-06-01" \\
-H "content-type: application/json" \\
-d '{"model":"claude-haiku-4-5-20251001","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}'
`);
console.log(apiResult.stdout); // 200 OK — real key was substituted by the proxy
Per-secret host restrictions
You can restrict individual secrets so they are only substituted in requests to specific hosts. This prevents a compromised dependency from exfiltrating secrets to an attacker-controlled server.
// This secret will only be substituted in requests to api.anthropic.com
await SecretStore.setSecret(store.id, 'ANTHROPIC_API_KEY', 'sk-ant-...', {
allowedHosts: ['api.anthropic.com'],
});
// This secret works on any allowed egress host
await SecretStore.setSecret(store.id, 'GENERIC_TOKEN', 'tok-...');
Egress allowlists
Secret stores can restrict which hosts the sandbox can make HTTPS requests to. Requests to hosts not on the list are blocked by the proxy.
const store = await SecretStore.create({
name: 'restricted-store',
egressAllowlist: ['api.anthropic.com', '*.openai.com'],
});
Supports exact matches (api.anthropic.com) and wildcards (*.openai.com). An empty allowlist means all hosts are allowed.
Managing secrets
// List all secret stores
const stores = await SecretStore.list();
// List secrets in a store (metadata only — values are never returned)
const entries = await SecretStore.listSecrets(store.id);
// Delete a secret
await SecretStore.deleteSecret(store.id, 'OLD_KEY');
// Delete a store and all its secrets
await SecretStore.delete(store.id);
Security properties
| Property | Detail |
|---|
| Encryption at rest | AES-256-GCM in Postgres, key via OPENSANDBOX_SECRET_ENCRYPTION_KEY |
| Never in VM memory | Env vars contain opaque osb_sealed_* tokens |
| Host-side only | Real values exist only in the MITM proxy process on the worker host |
| Egress control | Allowlists restrict which domains receive secrets |
| Per-secret scoping | Individual secrets can be locked to specific hosts |
| Values never returned | The API only returns secret names and metadata, never values |
Next steps