Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/opensandbox-group/OpenSandbox/llms.txt

Use this file to discover all available pages before exploring further.

Credential Vault is OpenSandbox’s outbound credential broker for sandboxed agents and developer tools. Real credentials are written to the egress sidecar by the host-side SDK, while the sandbox process only receives fake or empty credential values. When tools such as Claude Code, Git, curl, package managers, or model API clients make allowed outbound HTTPS requests, the sidecar matches the request against Credential Vault bindings and injects the required authentication headers on the way out. This keeps real secrets out of the sandbox environment, command line, filesystem, and logs — reducing credential exfiltration risk from prompt injection or untrusted AI-generated code.

Requirements

The following minimum versions are required to use Credential Vault:
ComponentMinimum Version
opensandbox-server>= 0.2.0
egress sidecar>= 1.1.1
Python SDK>= 0.1.11
JavaScript / TypeScript SDK>= 0.1.9
Kotlin SDK>= 1.0.13
Go SDK>= 1.0.3
C# SDK>= 0.1.3
In addition to SDK versions, the following conditions must be met at runtime:
  • The server configuration must set [egress].image to a valid egress sidecar image.
  • The sandbox create request must include an outbound network_policy.
  • The sandbox create request must enable Credential Proxy (credentialProxy.enabled = true).
  • Sandbox pods must not be running with a transparent service-mesh sidecar (such as Istio/Envoy injection) in the same network namespace. Credential Vault assumes the OpenSandbox egress sidecar is the only transparent outbound interception layer in the pod.

How It Works

Credential Vault is implemented by the egress sidecar. A sandbox must be created with both an outbound network_policy and Credential Proxy enabled. At a high level, the flow is:
1

Sidecar attached

The lifecycle server attaches the egress sidecar to the sandbox at creation time.
2

Credentials written

The SDK writes credentials and bindings to the sidecar Credential Vault API from the host side. The sandbox process never receives the real values.
3

Sandbox runs with fake credentials

The sandbox process starts with fake or empty credential environment variables — for example, ANTHROPIC_API_KEY=fake-key-inside-sandbox.
4

Outbound HTTPS request made

When the sandbox makes an HTTPS request, transparent MITM interception in the sidecar inspects the request metadata (scheme, host, port, method, and path).
5

Binding matched

If exactly one binding matches the outbound request, the sidecar injects the configured authentication header before the request leaves the pod.
6

Secrets redacted from responses

Secret values are redacted from vault API responses and outbound response headers. The active vault state is served over a local Unix domain socket inside the sidecar and is not accessible to the sandbox workload over the normal server proxy path.

Service Mesh Compatibility

Credential Vault depends on the egress sidecar’s transparent redirect and MITM path. If the sandbox pod is also injected with a transparent service-mesh sidecar such as Istio/Envoy, both layers will attempt to intercept outbound traffic in the same network namespace. OpenSandbox does not currently support that combination for Credential Vault.Use one of these operator patterns instead:
  • Disable mesh sidecar injection for sandbox pods that need Credential Vault.
  • Keep mesh injection enabled, but do not enable credentialProxy for those pods — Credential Vault will not be active.
  • Move outbound policy and credential handling to a platform mechanism outside the sandbox pod if mesh injection is mandatory.

Auth Types

Each Credential Vault binding includes an auth rule that describes how the referenced credential is rendered into the outbound request:
TypeInjected HeaderNotes
bearerAuthorization: Bearer <credential>Standard OAuth / API bearer tokens
basicAuthorization: Basic <credential>Credential must be pre-encoded as base64(username:password)
apiKey<header-name>: <credential>Credential value is placed in the configured header name
customHeadersMultiple headersEach header is backed by its own named credential

Python SDK Example

The following example creates a sandbox with credential_proxy enabled and a network_policy that allows only api.anthropic.com and registry.npmjs.org. It then calls sandbox.credential_vault.create() to register the real API key on the sidecar and binds it to outbound requests matching the Anthropic API path.
import os
from datetime import timedelta

from opensandbox import SandboxSync
from opensandbox.models.sandboxes import (
    Credential,
    CredentialBinding,
    CredentialProxyConfig,
    NetworkPolicy,
    NetworkRule,
    SandboxImageSpec,
)


ANTHROPIC_HOST = "api.anthropic.com"
ANTHROPIC_BASE_URL = "https://api.anthropic.com"
REAL_API_KEY = os.environ["ANTHROPIC_API_KEY"]


sandbox_env = {
    "ANTHROPIC_BASE_URL": ANTHROPIC_BASE_URL,
    "ANTHROPIC_API_KEY": "fake-key-inside-sandbox",
}

sandbox = SandboxSync.create(
    image=SandboxImageSpec(
        os.getenv("SANDBOX_IMAGE", "opensandbox/code-interpreter:latest")
    ),
    timeout=timedelta(minutes=15),
    env=sandbox_env,
    network_policy=NetworkPolicy(
        defaultAction="deny",
        egress=[
            NetworkRule(action="allow", target=ANTHROPIC_HOST),
            NetworkRule(action="allow", target="registry.npmjs.org"),
        ],
    ),
    credential_proxy=CredentialProxyConfig(enabled=True),
)
After the sandbox is created, write the credential and its binding:
sandbox.credential_vault.create(
    credentials=[
        Credential(
            name="anthropic-api-key",
            source={"value": REAL_API_KEY},
        )
    ],
    bindings=[
        CredentialBinding(
            name="anthropic-api",
            match={
                "schemes": ["https"],
                "ports": [443],
                "hosts": [ANTHROPIC_HOST],
                "methods": ["GET", "POST"],
                "paths": ["/v1/*"],
            },
            auth={
                "type": "apiKey",
                "name": "x-api-key",
                "credential": "anthropic-api-key",
            },
        )
    ],
)
The binding JSON structure consists of two top-level arrays:
{
  "credentials": [
    {
      "name": "anthropic-api-key",
      "source": { "value": "<real-secret>" }
    }
  ],
  "bindings": [
    {
      "name": "anthropic-api",
      "match": {
        "schemes": ["https"],
        "ports": [443],
        "hosts": ["api.anthropic.com"],
        "methods": ["GET", "POST"],
        "paths": ["/v1/*"]
      },
      "auth": {
        "type": "apiKey",
        "name": "x-api-key",
        "credential": "anthropic-api-key"
      }
    }
  ]
}
Use narrow path matches like /v1/* rather than /* whenever possible. Scoping bindings by path prevents the credential from being injected into unrelated requests on the same host and avoids ambiguous multi-binding matches, which are rejected by the sidecar.

Additional Auth Type Examples

from opensandbox.models.sandboxes import Credential, CredentialBinding

Credential(name="github-token", source={"value": "<token>"})

CredentialBinding(
    name="github-api",
    match={
        "schemes": ["https"],
        "ports": [443],
        "hosts": ["api.github.com"],
        "methods": ["GET", "POST"],
        "paths": ["/*"],
    },
    auth={"type": "bearer", "credential": "github-token"},
)

Egress Sidecar Configuration

The egress sidecar exposes the following environment variable for Credential Vault behavior:
Environment variableDefaultDescription
OPENSANDBOX_EGRESS_CREDENTIAL_VAULT_REQUIRE_TLSoffWhen enabled (true/1/on), credential vault write operations (create, patch, delete) require the request to arrive over TLS, from a loopback address, or with X-Forwarded-Proto: https. When disabled (default), any authenticated request is accepted regardless of transport. Enable this in deployments where the egress sidecar is directly reachable from untrusted networks without a TLS-terminating reverse proxy.

Binding Guidance

  • Use defaultAction="deny" and only allow the service hosts required by the tool.
  • Scope bindings by path whenever possible — for example /v1/* for Anthropic API calls.
  • Avoid overlapping bindings at the same precedence; ambiguous matches are rejected by the sidecar.
  • Do not put real secrets in sandbox env, command arguments, files, or metadata.
  • Keep fake environment variables when a CLI refuses to start without a key — the vault-injected header is what authenticates the actual outbound request.

SDK Quick Reference

All SDKs use the same wire contract. The main differences are naming and language style:
SDKEnable proxy on sandbox createVault entry pointCreate / patch methods
Pythoncredential_proxy=CredentialProxyConfig(enabled=True)sandbox.credential_vaultcreate(...), patch(...)
JavaScript / TypeScriptcredentialProxy: { enabled: true }sandbox.credentialVaultcreate(request), patch(request)
Kotlin / JVM.credentialProxyEnabled(true)sandbox.credentialVault()create(request), patch(request)
GoCredentialProxy: &opensandbox.CredentialProxyConfig{Enabled: true}sandbox.CredentialVault(ctx)CreateCredentialVault(ctx, req), PatchCredentialVault(ctx, req)
C# / .NETCredentialProxy = new CredentialProxyConfig { Enabled = true }sandbox.CredentialVaultCreateCredentialVaultAsync(...), PatchCredentialVaultAsync(...)
Vault APIs return sanitized metadata only. Plaintext credential values are write-only and are never returned by get, list, or patch responses.

Build docs developers (and LLMs) love