> ## Documentation Index
> Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

> Configure destination-bound sandbox credentials with the Python SDK.

See [Secrets](/sandboxes/secrets) for usage examples and security boundaries.

## Secret

#### <span className="msb-recv">Secret.</span><span className="msb-hn">env()</span>

```python theme={null}
@staticmethod
def env(
    env_var: str,
    *,
    value: str,
    allow: Sequence[str] = (),
    allow_placeholder_for: Sequence[str] = (),
    passthrough: Sequence[str] = (),  # deprecated alias
    placeholder: str | None = None,
    require_tls_identity: bool = True,
    violation_action: ViolationAction | None = None,
    substitution: SecretSubstitution | None = None,
) -> SecretEntry
```

<Accordion title="Example">
  ```python theme={null}
  import os
  from microsandbox import Sandbox, Secret, SecretSubstitution, ViolationAction

  secret = Secret.env(
      "SERVICE_API_KEY",
      value=os.environ["SERVICE_API_KEY"],
      allow=["api.example.com", "*.example.com"],
      allow_placeholder_for=["api.anthropic.com"],
      violation_action=ViolationAction.BLOCK_AND_TERMINATE,
      substitution=SecretSubstitution(query=True),
  )

  sb = await Sandbox.create(
      "worker",
      image="python",
      secrets=[secret],
      secret_violation_action=ViolationAction.BLOCK_AND_LOG,
  )
  ```
</Accordion>

Create a secret entry that maps an environment variable to a real value. The guest sees a placeholder; the TLS proxy substitutes the real value only when traffic goes to an allowed host. Pass the returned entry to `Sandbox.create(..., secrets=[...])`.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>env\_var</code><span className="msb-type">str</span></div>
    <div className="msb-param-desc">Environment variable name. Must be non-empty and cannot contain <code>=</code> or NUL; shell-identifier syntax is not required.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">str</span></div>
    <div className="msb-param-desc">The real secret value. Never enters the guest VM. Keyword-only and required. Raw values are persisted in the durable sandbox configuration.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>allow</code><span className="msb-type">Sequence\[str]</span></div>
    <div className="msb-param-desc">Exact hosts or wildcard patterns allowed to receive the real value. At least one exact or wildcard host is required. Default <code>()</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>allow\_placeholder\_for</code><span className="msb-type">Sequence\[str]</span></div>
    <div className="msb-param-desc">Exact hosts or wildcard patterns allowed to receive the unchanged placeholder. Does not grant access to the real value. Default <code>()</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>placeholder</code><span className="msb-type">str | None</span></div>
    <div className="msb-param-desc">Custom placeholder string: non-empty, up to 1024 bytes, no NUL/CR/LF. Auto-generated as <code>\$MSB\_\<env\_var></code> when <code>None</code>. Default <code>None</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>require\_tls\_identity</code><span className="msb-type">bool</span></div>
    <div className="msb-param-desc">Only substitute on TLS-intercepted connections. Disable only if you know the traffic is safe. Default <code>True</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>violation\_action</code><a className="msb-type" href="#violationaction">ViolationAction</a> | None</div>
    <div className="msb-param-desc">Per-secret blocking action. Default <code>None</code> inherits the network setting, whose default is <code>BLOCK\_AND\_LOG</code>.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>substitution</code><a className="msb-type" href="#secretsubstitution">SecretSubstitution</a> | None</div>
    <div className="msb-param-desc">Where in the HTTP request to substitute. <code>None</code> uses <code>SecretSubstitution()</code> defaults. Default <code>None</code>.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#secretentry">SecretEntry</a></div>
    <div className="msb-param-desc">Secret entry for <code>Sandbox.create(secrets=\[...])</code>.</div>
  </div>
</div>

## Validation and lifecycle

Sandbox configuration validation rejects empty environment names, names containing `=` or NUL, missing allowed hosts, every substitution location disabled, and placeholders that are empty, longer than 1024 bytes, or contain NUL/CR/LF. `Secret.env()` constructs an entry; it does not itself run all native validation.

Raw values are persisted at rest. Prefer source references through [live modification](/sandboxes/secrets#update-secrets) when the secret is available in the host environment. Rotating or removing an existing secret does not require a restart; adding a secret or changing its guest-visible placeholder does. Live modification is local-only.

`passthrough=` remains a deprecated alias for `allow_placeholder_for=` and emits a `DeprecationWarning` when used with hosts. If both are supplied, the host lists are combined. The returned `SecretEntry.passthrough` field and serialized configuration keep their existing names.

## Types

### SecretEntry

<p className="msb-backref">Returned by <a href="#secret-env">Secret.env()</a></p>

A single secret entry, used in `Sandbox.create(secrets=[...])`. Construct it with [`Secret.env()`](#secret-env) rather than directly.

| Field | Type | Default | Description |
| - | - | - | - |
| env\_var | `str` | required | Environment variable name (non-empty, no `=` or NUL) |
| value | `str` | required | Secret value. Never enters the guest |
| allow | `tuple[str, ...]` | `()` | Exact or wildcard hosts allowed to receive the real value |
| passthrough | `tuple[str, ...]` | `()` | Exact or wildcard hosts allowed to receive the unchanged placeholder |
| placeholder | `str \| None` | `None` | Placeholder string: non-empty, up to 1024 bytes, no NUL/CR/LF. Auto-generated as `$MSB_<env_var>` when `None` |
| require\_tls\_identity | `bool` | `True` | Only substitute on TLS-intercepted connections |
| violation\_action | [`ViolationAction`](#violationaction) `\| None` | `None` | Per-secret override; inherits the sandbox-wide action when omitted |
| substitution | [`SecretSubstitution`](#secretsubstitution) | `SecretSubstitution()` | Per-request substitution scopes |

### SecretSubstitution

<p className="msb-backref">Used by <a href="#secret-env">Secret.env()</a> · <a href="#secretentry">SecretEntry.substitution</a></p>

Frozen dataclass selecting where in an HTTP request the real value may replace the placeholder. At least one location must remain enabled. On credential-allowed hosts that pass the secret's identity checks, disabled locations forward the placeholder unchanged. Other destinations must match `passthrough` or follow the violation action.

| Field | Type | Default | Description |
| - | - | - | - |
| headers | `bool` | `True` | Substitute in headers, including decoded and re-encoded Basic authentication. |
| query | `bool` | `False` | Substitute in the request URL query string. |
| body | `bool` | `False` | Substitute in supported HTTP/1 bodies. |

When body substitution is enabled, fixed-length HTTP/1 bodies up to 16 MiB are rewritten with an updated `Content-Length`; larger fixed-length bodies are blocked. Chunked HTTP/1 bodies are decoded and re-encoded. Encoded bodies pass through unchanged. HTTP/2 DATA-frame body substitution is unsupported, and matching body placeholders are blocked.

Default settings are omitted from serialized configuration; explicitly setting `headers=False` is preserved. Passing a value other than `SecretSubstitution` to `SecretEntry.substitution` raises `TypeError` when serialized.

### ViolationAction

<p className="msb-backref">Used by <a href="#secret-env">Secret.env()</a> · <a href="#secretentry">SecretEntry.violation\_action</a></p>

String enum defining the blocking action when a placeholder cannot be substituted or passed through. Set the sandbox-wide default with `Network.secret_violation_action` or the top-level `Sandbox.create(secret_violation_action=...)`; the top-level value takes precedence if both are supplied. A secret's `violation_action` overrides that default. Passthrough is a host policy, not an enum member.

| Member | Value | Description |
| - | - | - |
| `ViolationAction.BLOCK` | `"block"` | Silently drop the request. The guest sees a connection reset. |
| `ViolationAction.BLOCK_AND_LOG` | `"block-and-log"` | Drop the request and emit a warning log on the host side. This is the default. |
| `ViolationAction.BLOCK_AND_TERMINATE` | `"block-and-terminate"` | Drop the request, log an error, and shut down the entire sandbox. |

### SecretViolationError

<p className="msb-backref">Subclass of <code>MicrosandboxError</code></p>

Raised when a secret placeholder was sent to a disallowed host. Carries `code = "secret-violation"`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.