---
title: Secrets
"og:title": Go SDK Secrets reference
description: Configure destination-bound sandbox credentials with the Go SDK.
keywords: ["Go SDK", "Go secrets", "microsandbox secrets"]
---

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

## Functions

#### <span className="msb-hn">WithSecrets()</span>

```go
func WithSecrets(secrets ...SecretEntry) SandboxOption
```

<Accordion title="Example">

```go
sb, err := m.CreateSandbox(ctx, "worker",
    m.WithImage("python:3.12"),
    m.WithSecrets(
        m.Secret.Env("STRIPE_KEY", os.Getenv("STRIPE_KEY"),
            m.SecretEnvOptions{Allow: []string{"api.stripe.com"}}),
        m.Secret.Env("OPENAI_API_KEY", os.Getenv("OPENAI_API_KEY"),
            m.SecretEnvOptions{Allow: []string{"*.openai.com"}}),
    ),
)
```

</Accordion>

Append credential secrets to the sandbox. Each call appends, so multiple calls accumulate. Secrets never enter the VM; the network proxy substitutes them at the transport layer. Pass to [`CreateSandbox`](/sdk/go/sandbox#m-createsandbox) alongside the other options.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>secrets</code><a className="msb-type" href="#secretentrystruct">...SecretEntry</a></div>
    <div className="msb-param-desc">Secret entries to attach, usually built with <a className="msb-type" href="#secret-env">Secret.Env</a>.</div>
  </div>
</div>

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">SandboxOption</span></div>
    <div className="msb-param-desc">Functional option for <a className="msb-type" href="/sdk/go/sandbox#m-createsandbox">CreateSandbox</a>.</div>
  </div>
</div>

## Secret

The [`Secret`](#secret-env) factory is a package-level value. Call its methods to build [`SecretEntry`](#secretentrystruct) values without populating struct literals by hand.

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

```go
func (secretFactory) Env(envVar, value string, opts SecretEnvOptions) SecretEntry
```

<Accordion title="Example">

```go
m.Secret.Env("STRIPE_KEY", os.Getenv("STRIPE_KEY"),
    m.SecretEnvOptions{
        Allow:               []string{"api.stripe.com", "*.stripe.com"},
        AllowPlaceholderFor: []string{"api.anthropic.com"},
        Substitution:        m.SecretSubstitution{Body: true},
        Placeholder:         "$MSB_STRIPE",
    },
)
```

</Accordion>

Build a [`SecretEntry`](#secretentrystruct) that maps an environment variable to a real value. The guest sees a placeholder; the real value is substituted by the TLS proxy only when traffic goes to an allowed host. Supply at least one exact or wildcard host in `Allow`; an empty allow-list is rejected when the sandbox configuration is validated.

<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 holding the placeholder inside the sandbox. 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">string</span></div>
    <div className="msb-param-desc">The real secret value. Passed to the native host runtime, never exposed inside the guest.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>opts</code><a className="msb-type" href="#secretenvoptionsstruct">SecretEnvOptions</a></div>
    <div className="msb-param-desc">Allowed hosts, placeholder override, TLS requirement, and violation action.</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="#secretentrystruct">SecretEntry</a></div>
    <div className="msb-param-desc">Pass to <a className="msb-type" href="#withsecrets">WithSecrets</a>.</div>
  </div>
</div>

## Validation and lifecycle

Sandbox configuration validation rejects invalid environment names (empty or containing `=` or NUL), an empty allow-list, all substitution locations disabled, and invalid placeholders. `Secret.Env()` constructs a value; errors surface when the configuration is validated.

Raw values are persisted in the durable sandbox configuration. See [source references and live modification](/sandboxes/secrets#update-secrets) to rotate or remove secrets without restarting. Adding a secret or changing its guest-visible placeholder requires a restart. Live modification is local-only.

## Types

### SecretEntry<span className="msb-tag is-type" style={{marginLeft: "8px"}}>struct</span>

<p className="msb-backref">accepted by <a href="#withsecrets">WithSecrets()</a> · returned by <a href="#secret-env">Secret.Env()</a></p>

A single credential the network proxy substitutes at the transport layer. The value never reaches the guest VM. Usually produced by [`Secret.Env`](#secret-env); exported for callers that prefer struct literals.

| Field | Type | Description |
|-------|------|-------------|
| `EnvVar` | `string` | Environment variable name holding the placeholder inside the sandbox. Must be non-empty and cannot contain `=` or NUL; shell-identifier syntax is not required |
| `Value` | `string` | Real secret value; stays on the host, including across the native FFI boundary |
| `Allow` | `[]string` | Exact hosts or wildcard patterns allowed to receive the real value |
| `Passthrough` | `[]string` | Exact hosts or wildcard patterns allowed to receive the unchanged placeholder |
| `Substitution` | [`SecretSubstitution`](#secretsubstitutionstruct) | Enabled request locations; zero value enables headers only |
| `Placeholder` | `string` | Custom placeholder shown inside the sandbox in place of the secret. Auto-generated from `EnvVar` when empty. Custom values must be non-empty, at most 1024 bytes, and cannot contain NUL, CR, or LF |
| `RequireTLSIdentity` | `*bool` | Require a verified TLS identity before substituting. Defaults to `true` when `nil` |
| `ViolationAction` | [`ViolationAction`](#violationactionstring-enum) | Override the sandbox-wide action when this secret is detected going to a disallowed host. This overrides the network default for this secret only |

### SecretEnvOptions<span className="msb-tag is-type" style={{marginLeft: "8px"}}>struct</span>

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

Tunes [`Secret.Env`](#secret-env) beyond the required `envVar` and `value`.

| Field | Type | Description |
|-------|------|-------------|
| `Allow` | `[]string` | Exact hosts or wildcard patterns allowed to receive the real value |
| `AllowPlaceholderFor` | `[]string` | Hosts allowed to receive the unchanged placeholder where substitution does not apply |
| `Passthrough` | `[]string` | Deprecated alias; combined with `AllowPlaceholderFor` when both are supplied |
| `Substitution` | [`SecretSubstitution`](#secretsubstitutionstruct) | Zero value enables headers only |
| `Placeholder` | `string` | Custom placeholder: non-empty, up to 1024 bytes, no NUL/CR/LF |
| `RequireTLSIdentity` | `*bool` | Require a verified TLS identity before substituting. Defaults to `true` when `nil` |
| `ViolationAction` | [`ViolationAction`](#violationactionstring-enum) | Per-secret violation action |

### SecretSubstitution<span className="msb-tag is-type" style={{marginLeft: "8px"}}>struct</span>

#### <span className="msb-recv">substitution.</span><span className="msb-hn">Headers</span>

```go
Headers *bool
```

Substitute in headers, including Basic authentication. Default: `true` when `nil`; use a pointer to set `false`.

#### <span className="msb-recv">substitution.</span><span className="msb-hn">HeaderFields</span>

```go
HeaderFields []string
```

Restrict substitution to these header names. An empty list allows all headers. Requires header substitution to be enabled. Prefer only the intended credential header, such as `Authorization`, to prevent other headers from exposing a secret in a reflected response.

#### <span className="msb-recv">substitution.</span><span className="msb-hn">Query</span>

```go
Query bool
```

Substitute in the URL query string. Default: `false`.

#### <span className="msb-recv">substitution.</span><span className="msb-hn">Body</span>

```go
Body bool
```

Substitute in supported HTTP/1 bodies. Default: `false`. Fixed-length bodies up to 16 MiB update `Content-Length`; larger bodies are blocked. Chunked bodies are decoded and re-encoded. Encoded bodies pass through unchanged. HTTP/2 body substitution is unsupported, and matching placeholders are blocked.

At least one substitution location must remain enabled. On verified allowed hosts, disabled locations forward the placeholder unchanged. Other destinations must match the passthrough policy or follow the violation action.

<Accordion title="Example">

```go
headers := false
secret := m.Secret.Env("GH_TOKEN", os.Getenv("GH_TOKEN"), m.SecretEnvOptions{
    Allow:               []string{"github.com", "api.github.com"},
    AllowPlaceholderFor: []string{"api.anthropic.com"},
    Substitution:        m.SecretSubstitution{Headers: &headers, Body: true},
    ViolationAction:     m.ViolationActionBlockAndTerminate,
})
sb, err := m.CreateSandbox(ctx, "worker",
    m.WithImage("python"),
    m.WithSecrets(secret),
    m.WithNetwork(&m.NetworkConfig{
        SecretViolationAction: m.ViolationActionBlockAndLog,
    }),
)
```

</Accordion>

### ViolationAction<span className="msb-tag is-type" style={{marginLeft: "8px"}}>string enum</span>

<p className="msb-backref">field of <a href="#secretentrystruct">SecretEntry</a> · <a href="/sdk/go/networking#networkconfig">NetworkConfig</a></p>

```go
type ViolationAction string
```

What happens when a secret placeholder cannot be substituted or passed through. Passthrough is a separate per-secret host policy, not a violation action. Configure the sandbox-wide default on [`NetworkConfig.SecretViolationAction`](/sdk/go/networking#networkconfig); override per-secret with [`SecretEntry.ViolationAction`](#secretentrystruct).

| Constant | Value | Description |
|----------|-------|-------------|
| `ViolationActionDefault` | `""` | Leave the runtime default in place (currently `block-and-log`) |
| `ViolationActionBlock` | `"block"` | Silently drop the request. The guest sees a connection reset |
| `ViolationActionBlockAndLog` | `"block-and-log"` | Drop the request and emit a warning log on the host side |
| `ViolationActionBlockAndTerminate` | `"block-and-terminate"` | Drop the request, log an error, and shut down the entire sandbox |
