Environment Variables & Secrets
Injecting configuration and credentials into sandboxes — and which mechanism to use.
Sandboxes usually need configuration: log levels, feature flags, endpoints — and credentials: API keys, tokens. Daytona provides two distinct mechanisms for getting values into a sandbox, and the difference between them is a security boundary, not a convenience. Plain env variables are visible to everything inside the sandbox; secrets are usable by code inside the sandbox but never readable by it.
Two mechanisms
env | secrets | |
|---|---|---|
| What you pass | name → value map | names of stored project secrets |
| What the guest sees | real values | opaque placeholders (values substituted outside the sandbox on egress) |
| Best for | non-sensitive config | API keys, tokens, credentials |
| Persistence | per-create | stored once, reused across sandboxes |
env — plain environment variables
The env parameter is a straightforward name → value map injected into the sandbox verbatim at create time. Every process in the sandbox can read the real values, exactly like environment variables anywhere else. Names must match [A-Za-z_][A-Za-z0-9_]* (invalid names fail the create with 400), and values are limited to 64 KiB each.
Use env for anything you would be comfortable printing in a log: configuration, endpoints, flags, non-sensitive identifiers.
Note: If the sandbox runs untrusted or AI-generated code, do not put credentials in
env— that code can trivially read and exfiltrate them. Usesecretsinstead.
secrets — protected credentials
Secrets solve the problem env cannot: giving sandboxed code the ability to use a credential without the ability to read it. A secret is a named value stored encrypted in your project. You attach secrets to a sandbox by listing their names in the secrets array at create time; each name must already exist in the project or the create fails with 400.
Inside the sandbox, each attached secret appears as an environment variable — but its value is an opaque placeholder, not the real credential. When code in the sandbox makes an outbound request carrying the placeholder (say, an Authorization header for an external API), the platform substitutes the real value on the way out — and only for hosts matching the secret's allowed_domains. The real value never enters the sandbox, so even fully untrusted code cannot exfiltrate it: dumping the environment, reading memory, or sending the placeholder to an attacker's server yields nothing usable.
Create secrets first — in the dashboard or via PUT /secrets/:name — then attach them by name:
Restricting outbound network (egress)
Secrets stop credentials from leaking out of a sandbox; egress whitelisting stops the sandbox from talking to anywhere it shouldn't in the first place. The egress_policy parameter (available in the SDKs since 0.2.0) turns a sandbox into default-deny for outbound traffic: when enabled, the sandbox can reach only the destinations you list, plus DNS (which is always permitted so allowed domains can resolve). This is a strong containment control for running untrusted or AI-generated code — even if that code is malicious, it cannot reach an attacker's server or an unapproved API.
Each allow entry is one of:
- an IPv4 address —
"1.2.3.4" - an IPv4 CIDR —
"140.82.0.0/16" - a domain —
"api.openai.com"— or a leading-wildcard domain —"*.github.com"(matches subdomains, not the bare apex)
Allowed domains are enforced at the network layer: once a domain resolves, every port and protocol to the resolved IPs is permitted. An enabled policy with an empty allow list blocks everything except DNS. The policy is immutable after create (v1), and when it is absent or enabled: false the sandbox has open egress, exactly as before.
Egress whitelisting pairs naturally with secrets: scope a secret's allowed_domains to the API it authenticates, and add that same domain to the egress allow list, so the sandbox can reach exactly one credentialed endpoint and nothing else.
Choosing between them
Use env for configuration and secrets for anything whose leakage would matter. A simple test: if the sandbox will ever run code you did not write and fully trust, every credential belongs in secrets. The two compose freely — most real creates carry an env map for configuration alongside a secrets list for credentials.
For sandboxes running untrusted code, combine both with an egress policy: secrets prevents credential theft, and egress whitelisting prevents the code from reaching anywhere you didn't approve.
See also
- Secrets management — creating, updating, and deleting secrets;
allowed_domainsscoping; rotation. - Parameter reference — validation rules for
envandsecretson the create request.