Credential protection
How code-host tokens, provider API keys, and saved logins are kept out of agent sessions.
The daemon keeps real credentials out of agent sessions wherever it can. A session gets a placeholder instead, and the daemon's credential proxy swaps in the real credential only on requests to the destination it was issued for. Anything the agent reads from its environment or files is useless anywhere else.
Code-host credentials
GitHub, GitLab, and Gitea access works this way in every execution environment: host, srt, microsandbox, Kubernetes pool pods, and sessions a daemon group runs on another member's machine. There is nothing to enable.
git,gh, andglabwork as usual. The proxy attaches a short-lived token scoped to the repository the request names and the agent's access level on it.- The session's environment, Git configuration, and files hold no usable token.
- A token the agent was given itself, such as its own
GH_TOKENorGITLAB_TOKENsecret, passes through unchanged. - The former
gh-tokenandglab-tokenhelper commands and theghandglabwrappers are gone. Scripts should callgit,gh, orglabdirectly.
What the proxy refuses
| Request | Result |
|---|---|
| A GitHub GraphQL mutation | Refused: GraphQL is read-only. The error names the agent's code-host tool for the write (pull requests, issues, comments, reviews), and the agent retries with it. |
| A GitLab or Gitea API write | Refused, naming the tool for the write. API reads work. |
git push to a repository the agent can only read | Refused with a message that the agent lacks write access. Grant Read & write to allow it. |
| A REST write that names no repository | Refused. GitHub REST writes to a repository, such as gh api, go through at the agent's access level. |
Creating or changing GitHub Projects items and Discussions, which only GraphQL writes can do, is unavailable to agents; reading them still works.
A session that cannot reach the proxy, for example on a Kubernetes runtime image older than the daemon, starts with no code-host credential, and the daemon logs why.
Provider API keys
The same proxy carries model provider API keys. The runtime holds a placeholder, and the request that reaches the provider carries the real key.
| Key | Sessions |
|---|---|
| Organization Infra → Provider keys, for an agent whose Model sign-in is Provider key | Host, srt, and microsandbox, including host sessions a daemon group runs on another member |
| API keys on the daemon's own machine, for the runtimes marked Proxy below | srt and microsandbox |
A Kubernetes install's keys: daemonPool.modelCredentials, modelEgress.clients.<client>.apiKey, and ANTHROPIC_API_KEY, OPENAI_API_KEY, DEEPSEEK_API_KEY, or COPILOT_PROVIDER_API_KEY mapped in daemonPool.runtimeEnvironment | Pool pods (details) |
The proxy adds an organization key's extra headers; they never enter the session. After a key's endpoint changes, start a new session to use it.
These still reach the session as they are:
- a key whose endpoint is plain
http://, since a placeholder is exchanged only over HTTPS; - a key the daemon cannot tie to one HTTPS endpoint for that runtime, such as one sent to a custom port (the daemon logs this once);
- short-lived per-session keys issued by a key server;
- subscription and OAuth sign-ins, covered below; and
- the daemon machine's own keys in a host session, which can read the machine's files anyway.
Trust and network
The proxy terminates TLS for code-host and provider requests, so sessions trust a certificate authority the daemon creates. The daemon points the standard trust variables (SSL_CERT_FILE, NODE_EXTRA_CA_CERTS, GIT_SSL_CAINFO, REQUESTS_CA_BUNDLE) at a bundle of the system roots, that authority, and the authorities the operator or the session's own variables already named. Sessions reach the proxy through HTTPS_PROXY; a client that ignores it, or pins its own certificates, reaches the code host or provider with only the placeholder and is refused.
For operators:
- Egress. The daemon makes the upstream request, so it needs outbound HTTPS to every code host and provider endpoint its agents use. On Kubernetes that is the daemon pool, not the agent pods.
- Private authorities. The proxy verifies the upstream with the daemon's trust roots and the authorities set for the daemon.
- Outbound proxy. A daemon that reaches the internet through its own
HTTPS_PROXYsends the proxy's upstream requests through it too, and honorsNO_PROXY.
Protection by runtime
The rest of this page covers logins saved on a self-hosted Linux daemon. Protection depends on the runtime and login method, and is the same in srt and microsandbox.
| Runtime | OAuth | API key |
|---|---|---|
| Claude Code | Tool rules | Proxy |
| Codex | Tool rules | Proxy |
| DeepSeek Harness | NA | Proxy |
| OpenCode | Unshielded | Proxy |
| pi | Unshielded | Proxy |
| Grok Build | Unshielded | Proxy |
| Qwen Code | Unshielded | Proxy |
| Oh My Pi | Unshielded | Proxy |
| Amp | NA | Proxy |
| Kimi Code | Unshielded | Proxy |
| Cline | Unshielded | Proxy |
| Devin | Unshielded | NA |
| Antigravity ACP | Unshielded | Proxy |
| GitHub Copilot | Unshielded | Proxy |
| Qoder CLI | Unshielded | Unshielded |
| Qoder CN CLI | Unshielded | Unshielded |
- Tool rules: the runtime blocks its tools from reading or changing protected credential files.
- Proxy: the real API key stays on the host (supported sources below).
- Unshielded: tools may read the credential inside the sandbox.
- NA: login mode not covered by this integration.
Claude Code and Codex also keep their tool rules when using the API proxy.
OAuth and tool rules
OAuth credentials are mounted or copied into the session. The runtime handles login and token refresh.
Claude Code and Codex use the same tool rules in SRT and microsandbox. Claude Code restricts Bash and its file tools (including Read and Edit). Codex uses permission profiles to restrict tool access to credential paths. The runtime itself can still read its credentials to authenticate.
These rules apply to the integrated runtime tools. They do not cover arbitrary helper processes or MCP servers. Other runtimes receive OAuth credentials without an additional shield.
API key proxy
For supported logins, the daemon gives the session a placeholder instead of the real API key. The host proxy replaces that placeholder in outgoing request headers only for the provider's approved HTTPS endpoint.
In both srt and microsandbox, this covers the saved keys of every runtime in the table below, and keys set in the daemon's environment or the runtime definition: ANTHROPIC_API_KEY for Claude Code, OPENAI_API_KEY for Codex, DEEPSEEK_API_KEY for DeepSeek Harness, and GitHub Copilot's and Antigravity ACP's keys. In srt, it also covers those variables for OpenCode.
The sandbox's imported credential files contain placeholders. For Oh My Pi, the daemon creates a private SQLite database with placeholders before writing any API-key records. The host's login files remain unchanged.
The proxy uses provider settings from the host. Editing settings inside the sandbox cannot authorize another destination for a key. The authorized provider receives the real key (its responses are not redacted).
Supported saved keys
| Runtime | Key source |
|---|---|
| Claude Code | primaryApiKey in the active global configuration |
| Codex | OPENAI_API_KEY in CODEX_HOME/auth.json |
| DeepSeek Harness | Standard DEEPSEEK_API_KEY entry in .dsh/.credentials.yaml or .dsh/.env |
| OpenCode | API records in auth.json (type: api) |
| pi | API records in auth.json, or provider keys in models.json |
| Grok Build | Per-model keys in config.toml (model.<id>.api_key) |
| Qwen Code | Model-provider keys in settings.json (including legacy security.auth.apiKey) |
| Oh My Pi | API-key records in agent.db |
| Amp | Native CLI entries in secrets.json (apiKey@<service URL>) |
| Kimi Code | Provider keys in .kimi-code/config.toml (providers.<name>.api_key) |
| Cline | Provider API keys in providers.json (apiKey or auth.apiKey) |
| GitHub Copilot | COPILOT_PROVIDER_API_KEY, sent to COPILOT_PROVIDER_BASE_URL |
| Antigravity ACP | GEMINI_API_KEY (the gemini-api-key sign-in method) |
Provider limits
DeepSeek uses https://api.deepseek.com. Grok, Qwen, and Kimi Code need an explicit HTTPS endpoint in the host configuration (for Kimi Code, the provider's base_url). Claude Code, Codex, OpenCode, and pi use supported host provider settings or built-in defaults. Oh My Pi uses built-in provider defaults.
pi, Oh My Pi, and Cline support the default endpoints for Anthropic, OpenAI, DeepSeek, Google, xAI, OpenRouter, Groq, and Mistral. Cline's other providers need an HTTPS baseUrl in the provider entry. Custom Codex providers must set requires_openai_auth = true.
GitHub Copilot needs an HTTPS COPILOT_PROVIDER_BASE_URL. Antigravity ACP uses the Gemini API, or GOOGLE_GEMINI_BASE_URL when it is set to an HTTPS endpoint.
If a recognized API key has no supported route, it stays hidden and that provider is unavailable. OpenCode's other configured providers can still work. DeepSeek rejects a custom endpoint at startup.
Protection covers the saved sources above. It does not automatically cover keyrings, command-based keys, arbitrary headers, custom plugins, or new logins performed inside the sandbox. Amp's separate amp-acp/credentials.json login is outside this protection. Oh My Pi keys stored only in custom model files are also outside it. Cline's AWS credentials and custom headers stay as they are, and so does a Kimi Code provider that reads its key from a variable (api_key_env).
Qoder CLI and Qoder CN CLI keys stay unshielded: a personal access token is exchanged in a request body, and a service account key must keep a format that no placeholder can match. Devin signs in through the browser and has no separate API key login.
Supported endpoints use HTTPS without custom ports or URL credentials. Protected sessions reject custom TLS trust overrides and conflicting credential mounts.
Existing sessions and key changes
A protected VM reloads a changed host key when it resumes after stopping. A running VM keeps its current key. Changing login accounts, provider records, or credential layout can rebuild the VM (see what is preserved).
How is this guide?