> ## 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

> Secure credential injection for sandboxes

Secrets keep credentials on the host while giving sandboxed code a placeholder to use.

When you bind a secret to an environment variable, microsandbox puts a placeholder in the guest instead of the real value. By default that placeholder is `$MSB_<env_var>`, using the environment variable name exactly as provided, and you can provide a custom placeholder when needed. If the sandbox sends the placeholder to an allowed host, microsandbox swaps it for the real credential at the network boundary. Anywhere else, the placeholder remains meaningless.

That means the guest can call APIs without ever holding the credential itself.

Allowed hosts are checked against the sandbox's observed DNS and TLS identity. Keep allow lists narrow so placeholders can only turn into credentials at the destinations that actually need them.

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Sandbox;

  let sb = Sandbox::builder("worker")
      .image("python")
      .secret(|s| s
          .env("GITHUB_TOKEN")
          .value(std::env::var("GITHUB_TOKEN")?)
          .allow_host("api.github.com")
          .allow_host_pattern("*.githubusercontent.com")
      )
      .secret_env("SERVICE_API_KEY", service_api_key, "api.example.com")
      .create()
      .await?;
  ```

  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  await using sb = await Sandbox.builder("worker")
      .image("python")
      .secret((s) =>
          s.env("GITHUB_TOKEN")
              .value(process.env.GITHUB_TOKEN!)
              .allowHost("api.github.com")
              .allowHostPattern("*.githubusercontent.com"),
      )
      .secretEnv("SERVICE_API_KEY", process.env.SERVICE_API_KEY!, "api.example.com")
      .create();
  ```

  ```python Python theme={null}
  import os
  from microsandbox import Sandbox, Secret

  sb = await Sandbox.create(
      "worker",
      image="python",
      secrets=[
          Secret.env(
              "GITHUB_TOKEN",
              value=os.environ["GITHUB_TOKEN"],
              allow_hosts=["api.github.com"],
              allow_host_patterns=["*.githubusercontent.com"],
          ),
          Secret.env(
              "SERVICE_API_KEY",
              value=os.environ["SERVICE_API_KEY"],
              allow_hosts=["api.example.com"],
          ),
      ],
  )
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "worker",
      m.WithImage("python"),
      m.WithSecrets(
          m.Secret.Env("GITHUB_TOKEN", os.Getenv("GITHUB_TOKEN"),
              m.SecretEnvOptions{
                  AllowHosts:        []string{"api.github.com"},
                  AllowHostPatterns: []string{"*.githubusercontent.com"},
              },
          ),
          m.Secret.Env("SERVICE_API_KEY", os.Getenv("SERVICE_API_KEY"),
              m.SecretEnvOptions{AllowHosts: []string{"api.example.com"}},
          ),
      ),
  )
  ```

  ```bash CLI theme={null}
  msb create python --name worker \
    --secret "GITHUB_TOKEN@api.github.com" \
    --secret "SERVICE_API_KEY@api.example.com"
  ```
</CodeGroup>

In the CLI form, `ENV@HOST` reads the real value from the same-named host environment variable. Use `ENV=VALUE@HOST` when you need to provide an explicit value, such as `GUEST_TOKEN=$HOST_TOKEN@api.example.com`; shell-expanded values are passed to `msb` as command arguments.

For API details, see the SDK references: [Rust](/sdk/rust/secrets) | [TypeScript](/sdk/typescript/secrets) | [Python](/sdk/python/secrets) | [Go](/sdk/go/secrets).
