> ## 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 TypeScript SDK.

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

## SecretBuilder

Builder for one secret configuration.

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

```typescript theme={null}
env(varName: string): this
```

Set the environment variable name that holds the placeholder inside the guest. The guest sees `$MSB_<varName>` (or a custom [`placeholder`](#secret-placeholder)), never the real value. Names must be non-empty and cannot contain `=` or NUL; shell-identifier syntax is not required. **Required.**

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>varName</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Environment variable name (non-empty, no <code>=</code> or NUL).</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">value()</span>

```typescript theme={null}
value(value: string): this
```

Set the real secret value. This is the string that replaces the placeholder when a request reaches an allowed host. It never enters the guest VM. **Required.**

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">The actual credential or token.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">placeholder()</span>

```typescript theme={null}
placeholder(placeholder: string): this
```

Override the auto-generated placeholder string. By default microsandbox generates `$MSB_<envVar>`. Use this when you need a specific format or when the placeholder must match a particular byte length. Placeholders must be non-empty, at most 1024 bytes, and cannot contain NUL, CR, or LF.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>placeholder</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Custom placeholder string: non-empty, up to 1024 bytes, no NUL/CR/LF.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">allow()</span>

```typescript theme={null}
allow(host: string): this
```

<Accordion title="Example">
  ```typescript theme={null}
  .secret((s) =>
    s.env("STRIPE_KEY")
      .value(process.env.STRIPE_KEY!)
      .allow("api.stripe.com")
      .allow("files.stripe.com"),
  )
  ```
</Accordion>

Add an exact host or wildcard pattern allowed to receive the real secret value. A `*.suffix` pattern matches the suffix itself and its single- or multi-label subdomains. The proxy checks the host against the connection's verified TLS identity and observed DNS history. Can be called multiple times to allow several hosts. At least one allowed host (exact, pattern, or any) is required.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>host</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Hostname or wildcard pattern, e.g. <code>"api.example.com"</code> or <code>"\*.example.com"</code> (ASCII case-insensitive).</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">allowAnyHostDangerous()</span>

```typescript theme={null}
allowAnyHostDangerous(iUnderstand: boolean): this
```

Allow substitution on **any** host. Every server the guest connects to can then receive the real secret, which effectively disables host-based protection. The call is a no-op unless `iUnderstand` is `true`. Only use this when the secret is not sensitive or the sandbox network is fully locked down. This is the one allow-list pattern that skips DNS and TLS-identity pinning.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>iUnderstand</code><span className="msb-type">boolean</span></div>
    <div className="msb-param-desc">Must be <code>true</code> to take effect.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">requireTlsIdentity()</span>

```typescript theme={null}
requireTlsIdentity(enabled: boolean): this
```

When `true`, the secret is only substituted on TLS-intercepted connections where the proxy has verified it is performing MITM and the SNI matches an allowed host. Bypassed TLS is opaque and never receives substitution. Disable only when you know the traffic path is safe and explicitly supports non-TLS substitution. Default: `true`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>enabled</code><span className="msb-type">boolean</span></div>
    <div className="msb-param-desc">Require verified TLS identity. Default: <code>true</code>.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">substituteInHeaders()</span>

```typescript theme={null}
substituteInHeaders(enabled: boolean): this
```

Control whether the placeholder is replaced anywhere in HTTP headers, including decoded and re-encoded Basic authentication credentials. This is the most common injection scope, covering `Authorization: Bearer $MSB_...` and similar patterns. Default: `true`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>enabled</code><span className="msb-type">boolean</span></div>
    <div className="msb-param-desc">Substitute in headers. Default: <code>true</code>.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">substituteInQuery()</span>

```typescript theme={null}
substituteInQuery(enabled: boolean): this
```

Control whether the placeholder is replaced in the URL query string (the `?key=value` portion of the request line). Default: `false`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>enabled</code><span className="msb-type">boolean</span></div>
    <div className="msb-param-desc">Substitute in query parameters. Default: <code>false</code>.</div>
  </div>
</div>

#### <span className="msb-recv">secret.</span><span className="msb-hn">substituteInBody()</span>

```typescript theme={null}
substituteInBody(enabled: boolean): this
```

Control whether the placeholder is replaced in inspectable request bodies. When 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 with fresh chunk sizes. Encoded bodies pass through unchanged. HTTP/2 DATA-frame body substitution is unsupported, and matching body placeholders are blocked. Default: `false`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>enabled</code><span className="msb-type">boolean</span></div>
    <div className="msb-param-desc">Substitute in request bodies. Default: <code>false</code>.</div>
  </div>
</div>

<span id="secret-allowpassthroughfor" />

#### <span className="msb-recv">secret.</span><span className="msb-hn">allowPlaceholderFor()</span>

```typescript theme={null}
allowPlaceholderFor(host: string): this
```

Allow an exact host or wildcard pattern to receive the placeholder unchanged when it cannot be substituted. Repeat this method for multiple hosts. `allowPassthroughFor()` remains a deprecated alias. This never grants permission to receive the real secret; use [`allow()`](#secret-allow) for substitution. Credential-allowed hosts already permit unchanged placeholders outside enabled substitution locations once the secret's host and TLS identity checks pass. Without either permission, the configured blocking action applies.

#### <span className="msb-recv">secret.</span><span className="msb-hn">violationAction()</span>

```typescript theme={null}
violationAction(action: "block" | "block-and-log" | "block-and-terminate"): this
```

Override the [sandbox-wide action](#networkbuilder-secretviolationaction) for this secret. Omitting this method inherits the network setting, whose default is `"block-and-log"`. Invalid action strings throw an error. Passthrough is a separate per-secret host policy, not a violation action.

<Accordion title="Example">
  ```typescript theme={null}
  .secret((s) =>
    s.env("API_KEY")
      .value(process.env.API_KEY!)
      .allow("api.github.com")
      .allowPlaceholderFor("api.anthropic.com")
      .substituteInBody(true)
      .violationAction("block-and-terminate"),
  )
  ```
</Accordion>

#### <span className="msb-recv">secret.</span><span className="msb-hn">build()</span>

```typescript theme={null}
build(): SecretEntry
```

Materialize the [`SecretEntry`](#secretentry). Called for you by [`SandboxBuilder.secret`](#sandboxbuilder-secret), so you rarely call it directly. If [`placeholder`](#secret-placeholder) was not set, it defaults to `$MSB_<envVar>`. Consumes the builder; do not reuse it afterward. Throws if `env` or `value` was not set, or if the allow-list is empty. Sandbox configuration validation also rejects invalid environment names or placeholders and configurations with every substitution site disabled.

<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">The materialized secret entry.</div>
  </div>
</div>

## SandboxBuilder

Two methods on [`SandboxBuilder`](/sdk/typescript/sandbox) for adding secrets without reaching into a [`NetworkBuilder`](/sdk/typescript/networking). Both automatically enable TLS interception.

#### <span className="msb-recv">sandbox.</span><span className="msb-hn" id="sandboxbuilder-secret">secret()</span>

```typescript theme={null}
secret(configure: (s: SecretBuilder) => SecretBuilder): this
```

<Accordion title="Example">
  ```typescript theme={null}
  await using sb = await Sandbox.builder("payments-worker")
    .image("python")
    .secret((s) =>
      s.env("STRIPE_KEY")
        .value(process.env.STRIPE_KEY!)
        .allow("api.stripe.com")
        .allow("*.stripe.com")
        .substituteInHeaders(true)
        .substituteInQuery(false),
    )
    .create();
  ```
</Accordion>

Add a secret with full configuration via a [`SecretBuilder`](#secretbuilder) closure. The builder's [`build()`](#secret-build) is called for you.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>configure</code><a className="msb-type" href="#secretbuilder">(s: SecretBuilder) => SecretBuilder</a></div>
    <div className="msb-param-desc">Configure the secret.</div>
  </div>
</div>

#### <span className="msb-recv">sandbox.</span><span className="msb-hn" id="sandboxbuilder-secretenv">secretEnv()</span>

```typescript theme={null}
secretEnv(envVar: string, value: string, allowedHost: string): this
```

<Accordion title="Example">
  ```typescript theme={null}
  await using sb = await Sandbox.builder("agent")
    .image("python")
    .secretEnv("OPENAI_API_KEY", process.env.OPENAI_API_KEY!, "api.openai.com")
    .create();
  ```
</Accordion>

Three-argument shorthand. Auto-generates the placeholder as `$MSB_<envVar>` and allows substitution only on `allowedHost`. The default injection scopes apply (headers and Basic Auth enabled, query and body disabled).

<Warning>
  **Plaintext at rest.** The value is persisted verbatim in the durable sandbox config until a later modify rotate migrates the entry to a source reference. Use this path when you hold only a value; use source references through the [live-modify API](/sandboxes/secrets#update-secrets) when the value is available in the host environment.
</Warning>

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>envVar</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Environment variable name (non-empty, no <code>=</code> or NUL).</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Secret value.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>allowedHost</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Allowed destination host (exact match).</div>
  </div>
</div>

## NetworkBuilder

The same secret configuration is available inside [`SandboxBuilder.network(n => ...)`](/sdk/typescript/networking) for callers who are already configuring networking. These methods set the secrets and the sandbox-wide violation policy directly on the network.

#### <span className="msb-recv">network.</span><span className="msb-hn" id="networkbuilder-secret">secret()</span>

```typescript theme={null}
secret(configure: (s: SecretBuilder) => SecretBuilder): this
```

<Accordion title="Example">
  ```typescript theme={null}
  await using sb = await Sandbox.builder("agent")
    .image("python")
    .network((n) =>
      n.secret((s) =>
        s.env("OPENAI_API_KEY")
          .value(process.env.OPENAI_API_KEY!)
          .allow("api.openai.com"),
      ),
    )
    .create();
  ```
</Accordion>

Add a secret with full configuration via a [`SecretBuilder`](#secretbuilder) closure. Identical in behavior to [`SandboxBuilder.secret`](#sandboxbuilder-secret).

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>configure</code><a className="msb-type" href="#secretbuilder">(s: SecretBuilder) => SecretBuilder</a></div>
    <div className="msb-param-desc">Configure the secret.</div>
  </div>
</div>

#### <span className="msb-recv">network.</span><span className="msb-hn" id="networkbuilder-secretenv">secretEnv()</span>

```typescript theme={null}
secretEnv(envVar: string, value: string, placeholder: string, allowedHost: string): this
```

Four-argument shorthand. Same as the `SandboxBuilder` form but lets you provide the placeholder explicitly instead of auto-generating `$MSB_<envVar>`.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>envVar</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Environment variable name (non-empty, no <code>=</code> or NUL).</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Secret value.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>placeholder</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Explicit placeholder: non-empty, up to 1024 bytes, no NUL/CR/LF.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>allowedHost</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Allowed destination host (exact match).</div>
  </div>
</div>

#### <span className="msb-recv">network.</span><span className="msb-hn" id="networkbuilder-secretenvsimple">secretEnvSimple()</span>

```typescript theme={null}
secretEnvSimple(envVar: string, value: string, allowedHost: string): this
```

Three-argument shorthand on `NetworkBuilder`. Auto-generates the placeholder as `$MSB_<envVar>`, matching [`SandboxBuilder.secretEnv`](#sandboxbuilder-secretenv). Like `NetworkBuilder.secret()` and `NetworkBuilder.secretEnv()`, it enables TLS interception while preserving other TLS settings. The guest receives only the placeholder. Earlier SDK versions incorrectly exposed the supplied secret as the placeholder in this helper. Code that intentionally needs a raw guest environment value should use ordinary environment configuration; this helper keeps the credential on the host. Updating the SDK does not rewrite existing sandbox configurations; recreate or explicitly reconfigure sandboxes created with the affected helper.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>envVar</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Environment variable name (non-empty, no <code>=</code> or NUL).</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>value</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Secret value.</div>
  </div>

  <div className="msb-param">
    <div className="msb-param-key"><code>allowedHost</code><span className="msb-type">string</span></div>
    <div className="msb-param-desc">Allowed destination host (exact match).</div>
  </div>
</div>

#### <span className="msb-recv">network.</span><span className="msb-hn" id="networkbuilder-secretviolationaction">secretViolationAction()</span>

```typescript theme={null}
secretViolationAction(action: "block" | "block-and-log" | "block-and-terminate"): this
```

Set the sandbox-wide blocking action for placeholders that cannot be substituted or passed through. [`SecretBuilder.violationAction()`](#secret-violationaction) overrides it per secret. This method belongs to `NetworkBuilder`, so configure it through `SandboxBuilder.network()`.

<Accordion title="Example">
  ```typescript theme={null}
  await using sb = await Sandbox.builder("agent")
    .image("python")
    .network((n) =>
      n.secretEnvSimple("OPENAI_API_KEY", process.env.OPENAI_API_KEY!, "api.openai.com")
        .secretViolationAction("block-and-log"),
    )
    .create();
  ```
</Accordion>

## Types

### SecretEntry

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

The materialized object produced by `SecretBuilder.build()`. Configure secrets through the builder; its output is not the sparse live-modification input.

| Field | Type | Description |
| - | - | - |
| `envVar` | `string` | Environment variable name (non-empty, no `=` or NUL) |
| `value` | `string` | Real secret value (stays on the host; raw values are persisted) |
| `placeholder` | `string` | Guest-visible placeholder; defaults to `$MSB_<envVar>`, non-empty, at most 1024 bytes, no NUL/CR/LF |
| `allowedHosts` | `string[]` | Exact allowed hosts |
| `allowedHostPatterns` | `string[]` | Wildcard allowed hosts |
| `allowAnyHost` | `boolean` | Permit substitution to any host |
| `passthroughHosts` | `string[]` | Hosts or patterns allowed to receive the unchanged placeholder |
| `requireTlsIdentity` | `boolean` | Require verified TLS identity before substitution |
| `substitution` | [`SecretSubstitution`](#secretsubstitution) | Enabled request locations |

### SecretSubstitution

<p className="msb-backref">Used by <a href="#secretentry">SecretEntry.substitution</a></p>

The materialized substitution settings. Set them through the `substituteIn*` methods on [`SecretBuilder`](#secretbuilder). 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 require explicit placeholder permission or follow the violation action.

| Field | Type | Builder default | Description |
| - | - | - | - |
| `headers` | `boolean` | `true` | Substitute in headers, including Basic authentication. |
| `query` | `boolean` | `false` | Substitute in URL query parameters. |
| `body` | `boolean` | `false` | Substitute in supported bodies; see [limits](#secret-substituteinbody). |

### ViolationAction

<p className="msb-backref">Used by <a href="#secret-violationaction">SecretBuilder.violationAction()</a> · <a href="#networkbuilder-secretviolationaction">NetworkBuilder.secretViolationAction()</a></p>

The `ViolationActions` array enumerates these values. Per-secret settings override the network default; passthrough is configured separately.

```typescript theme={null}
type ViolationAction = "block" | "block-and-log" | "block-and-terminate";
```

| Value | Description |
| - | - |
| `"block"` | Block the request without logging. |
| `"block-and-log"` | Block and emit a warning on the host. This is the default. |
| `"block-and-terminate"` | Block, log an error, and shut down the sandbox. |


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