On Runtime, the sandbox never holds the key. It is not in the environment, the memory or the disk. So a prompt injection or a stolen sandbox has nothing to leak. Each secret names the hosts it may go to. The proxy on the host adds the value to HTTPS requests to those hosts only. Code that sends the placeholder anywhere else sends a value that is worthless. One stored secret serves every sandbox in the account. An account can hold up to 50 secrets.
Store a secret
Terminalprintf %s "$OPENAI_API_KEY" | runtime secrets set OPENAI_API_KEY --host api.openai.comruntime secrets lsThe CLI reads the value from standard input only. So it never lands in your
shell history, and it is not shown when typed at a terminal. ls shows names,
hosts and placeholders, never values.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.secrets.set("OPENAI_API_KEY", { value: process.env.OPENAI_API_KEY ?? "", hosts: ["api.openai.com"],});Pythonimport osfrom withruntime import Runtimeruntime = Runtime()runtime.secrets.set("OPENAI_API_KEY", value=os.environ.get("OPENAI_API_KEY", ""), hosts=["api.openai.com"])An agent connected through MCP uses runtime_secrets with
set, list and delete.
Use it from code in the sandbox
Nothing changes in the code. Every sandbox has an environment variable with the
secret's name. It holds a placeholder such as rtsec_3f9c…. An SDK that reads
OPENAI_API_KEY sends it as usual:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();const call = await sbx.exec( 'curl -sS https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"', { timeoutMs: 30_000 },);console.log(call.exitCode);const seen = await sbx.exec("printenv OPENAI_API_KEY");console.log(seen.stdout); // rtsec_…, the placeholder, never the keyPythonfrom withruntime import Sandboxwith Sandbox.create() as sbx: call = sbx.exec('curl -sS https://api.openai.com/v1/models ' '-H "Authorization: Bearer $OPENAI_API_KEY"', timeout_ms=30_000) print(call.exit_code) print(sbx.exec("printenv OPENAI_API_KEY").stdout) # the placeholderSet the header for the code
With header, the proxy sets that header on every HTTPS request to the hosts.
It replaces any header the sandbox sent. So the code needs no placeholder at
all. format controls how the value is written into the header:
Terminalruntime secrets set GITHUB_TOKEN --host api.github.com --header Authorization --format 'token {value}' < token.txtTypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.secrets.set("GITHUB_TOKEN", { value: process.env.GITHUB_TOKEN ?? "", hosts: ["api.github.com", "*.githubusercontent.com"], header: "Authorization", format: "token {value}",});A secret with header Authorization and format AWS4-HMAC-SHA256 {value}
holds a bucket's ACCESS_KEY_ID:SECRET_ACCESS_KEY. The proxy re-signs S3
requests with the real key. So the secret key is never sent at all
(mount your own bucket).
Limits
| What | Limit |
|---|---|
| Secrets per account | 50 |
| Value | At most 8 KiB of visible ASCII |
| Hosts per secret | 16, as names or *.domain |
| Where it is added | The credential header, or header, to the secret's hosts |
| Never added | The URL, other headers, plain HTTP, bodies, any other host |
| Protocol to its hosts | HTTP/2 or HTTP/1.1, as client and host offer; WebSockets, gRPC |
| Replacing a value | Keeps the placeholder; running sandboxes use it within seconds |
Mistakes and how Runtime handles them
- Passing the key in
envor the command line.envvalues are never echoed back, and journals keep only a hash. But the sandbox then holds the key. A command line is recorded as sent. Use a secret instead. - Naming a host that echoes requests. A host that reflects headers back would show the value to the sandbox. Name only hosts you trust with it.
- A program with pinned certificates. The proxy opens the HTTPS connection
to the secret's hosts itself. It checks the real server's certificate.
Python, Node, curl and git already trust Runtime's certificate through
SSL_CERT_FILE,REQUESTS_CA_BUNDLEandNODE_EXTRA_CA_CERTS. A program with its own list of certificates needs/usr/local/share/ca-certificates/runtime-egress.crtadded to that list. - Deleting to revoke.
runtime secrets rmerases the value on Runtime. It does not revoke the key at its provider. Rotate it there too. - A database password. Only HTTPS requests are rewritten. So a Postgres password cannot be replaced this way. For your own cloud, an identity token avoids storing a key at all.
Lock it down further
A secret stops the key from leaking. Network rules stop the data from leaving. If you allow only the secret's host, the sandbox can call that API and nothing else. For no network at all, turn the internet off.
Related
Facts on this page were checked on 26 October 2026.