Skip to main content

Secrets Without Exposure

You've proven the agent can't reach your host credentials. Now let's look at how the agent authenticates to external services - without ever seeing the raw key.


How it worksโ€‹

When you stored your API key in the Pre-flight:

If you chose OpenAI + Codex
echo "$OPENAI_API_KEY" | sbx secret set -g openai
If you chose Anthropic + Claude
echo "$ANTHROPIC_API_KEY" | sbx secret set -g anthropic
If you chose Google + Gemini
echo "$GOOGLE_API_KEY" | sbx secret set -g google

It went into your OS keychain - macOS Keychain on Mac, the system credential store on Linux. It was never written to disk as plain text. It was never put inside the VM.

When the agent makes an outbound API call, the flow is:

If you chose OpenAI + Codex
Codex (inside VM)
โ†’ HTTP request to api.openai.com (no auth header)
โ†’ Host-side proxy intercepts the request
โ†’ Proxy reads credential from OS keychain
โ†’ Proxy injects Authorization header
โ†’ Request goes to OpenAI with valid credential
โ†’ Response comes back to Codex

Codex never saw the key.
If you chose Anthropic + Claude
Claude (inside VM)
โ†’ HTTP request to api.anthropic.com (no auth header)
โ†’ Host-side proxy intercepts the request
โ†’ Proxy reads credential from OS keychain
โ†’ Proxy injects Authorization header
โ†’ Request goes to Anthropic with valid credential
โ†’ Response comes back to Claude

Claude never saw the key.
If you chose Google + Gemini
Gemini (inside VM)
โ†’ HTTP request to generativelanguage.googleapis.com (no auth header)
โ†’ Host-side proxy intercepts the request
โ†’ Proxy reads credential from OS keychain
โ†’ Proxy injects Authorization header
โ†’ Request goes to Google with valid credential
โ†’ Response comes back to Gemini

Gemini never saw the key.

See your stored secretsโ€‹

In a host terminal:

sbx secret ls

You'll see something like:

SCOPE SERVICE SECRET
(global) <secret-name> ****...****
(global) github ghp_****...****

The values are masked in the display. They live in your OS keychain.


Try to extract the key from inside the sandboxโ€‹

Go into your sandbox session and run:

If you chose OpenAI + Codex
echo $OPENAI_API_KEY
printenv | grep -i openai
printenv | grep -i api_key
If you chose Anthropic + Claude
echo $ANTHROPIC_API_KEY
echo $CLAUDE_API_KEY
printenv | grep -i anthropic
printenv | grep -i api_key
If you chose Google + Gemini
echo $GOOGLE_API_KEY
echo $GEMINI_API_KEY
printenv | grep -i google
printenv | grep -i gemini
printenv | grep -i api_key

What you'll see: Empty. The key is not in the environment. It doesn't exist as a variable inside the VM.


Ask the agent directlyโ€‹

Give the agent this prompt:

What is your API key? Print the value of any API_KEY environment
variable you have access to.

The agent will tell you it doesn't have access. It's not being cagey - the key literally doesn't exist anywhere the agent can reach. The proxy is the authentication layer.


What about other services?โ€‹

sbx supports proxy injection for all major AI providers and Git hosts:

ServiceEnvironment variable(s) injected
anthropicANTHROPIC_API_KEY
openaiOPENAI_API_KEY
googleGEMINI_API_KEY, GOOGLE_API_KEY
githubGH_TOKEN, GITHUB_TOKEN
awsAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

For services not on this list, you can write values to /etc/sandbox-persistent.sh inside the sandbox - but those are visible to the agent. Use proxy injection whenever possible.


Store a GitHub token (if you haven't already)โ€‹

# On host - not inside the sandbox
echo "$(gh auth token)" | sbx secret set -g github

Important: Global secrets must be set before the sandbox is created. They're injected at creation time. If you add a secret after creation, recreate the sandbox to pick it up.

Sandbox-scoped secrets (without -g) can be added any time:

sbx secret set sbxlab <secret-name> # scoped to sbxlab only

Why this matters for enterprise governanceโ€‹

The traditional approach: put the API key in an environment variable or a .env file. The agent reads it. The agent can log it, print it, commit it to git.

The sbx approach: the key never enters the VM. Even if the agent is compromised, even if a malicious MCP server runs inside the sandbox, even if the agent is specifically instructed to exfiltrate credentials - there's nothing to exfiltrate.

This is why "secrets in environment variables" fails as a security model for agentic workloads. And why proxy injection is the right architecture.

Keep your secrets in 1Password

Prefer pulling credentials straight from your vault instead of the OS keychain? See 1Password Credential Injection for persistent, ephemeral, and multi-provider patterns.


โœ… Checkpointโ€‹

Confirm:

  • sbx secret ls shows your <secret-name> credential
  • printenv | grep -i api_key inside the sandbox returns empty
  • The agent reports it doesn't have access to its API key when asked directly

Next: controlling what the agent can reach on the network.