# How do I give an AI agent API keys without exposing them?

> Keep the key off the agent's machine. A Secret Proxy stores it and adds it to matching HTTPS requests on the way out, so the agent can call the API but never read the key.

- Source: Sanbox knowledge base, by Sanlabs GmbH
- URL: https://sanbox.cloud/kb/security/api-keys-your-agent-cannot-see/
- Type: how-to
- Section: Secrets, egress and blast radius
- Language: en
- Published: 2026-11-06
- Updated: 2026-11-06

Don't put the key where the agent runs. Store it outside the machine and have an egress proxy add it to the agent's requests on their way out. On Sanbox, that's a Secret Proxy: you save a credential once, grant it to a template, and the agent calls the API's normal HTTPS URL while the key never enters the Computer. The same idea works with any proxy you run yourself that can add headers to HTTPS requests and that the machine trusts.

## Run this with your agent

```text
Read https://sanbox.cloud/kb/security/api-keys-your-agent-cannot-see.md and follow it to give my agent a GitHub token it cannot read.
If the Sanbox CLI is missing, install it with `npm install -g @sanlabs/sanbox-cli@latest`
and sign in with `sanbox login`. Show me each command before you create, stop or delete a Computer.
```

## How do agents find secrets?

An agent with a shell can read anything its user can, and it reads files and runs commands to debug. No malice is needed. "Check the config" is enough, and a prompt injection from a web page or an issue makes it deliberate. Keys turn up in:

- **`.env` files.** Compose also reads a `.env` file in the project directory automatically.
- **`docker compose config`**, which prints the resolved configuration with variables filled in.
- **Shell history.** Bash saves commands to `~/.bash_history`, including any `export TOKEN=...` you typed.
- **The environment.** Every command the agent runs inherits exported variables, and `/proc/<pid>/environ` holds the environment a process started with.
- **Home-directory files**, such as private keys in `~/.ssh` and `~/.git-credentials`, which git's store helper writes in plain text.
- **The transcript.** Once a key appears in a command's output, it's in the model's context and on its way to the model provider.

Hiding one file doesn't solve this. If the key is on the machine, assume the agent can reach it.

## How does a Secret Proxy work?

The Computer holds no key. Its outbound HTTPS traffic leaves through Sanbox's gateway, and when a request matches a proxy's host, paths and methods, the gateway adds the credential. The Computer trusts the gateway's certificate authority, so TLS verification still works.

Credentials are read only from stdin, encrypted at application level with AES-256, and never shown in management reads. Proxies also work inside Docker containers and builds.

## Steps: give an agent a GitHub token it can't read

### 1. Create a narrow token

Create a fine-grained GitHub personal access token for one repository, with an expiry and only the permissions the work needs: for example, read access to contents and pull requests, and write access to issues. Save it to a private file outside any repository.

### 2. Describe the proxy

Save the settings, with no token in them, as `proxy.json`. These rules allow reads anywhere under the repository and new issues and comments:

```json
{
  "name": "github-api",
  "host": "api.github.com",
  "authentication": { "type": "bearer" },
  "request_rules": [
    { "path_prefix": "/repos/acme/app", "methods": ["GET"] },
    { "path_prefix": "/repos/acme/app/issues", "methods": ["POST"] }
  ],
  "attach_run_id": false
}
```

### 3. Create the proxy

Creating proxies and grants needs the admin or owner role:

```bash
sanbox secret-proxies create --file proxy.json --secret-stdin --json < ~/.config/github-agent-token
sanbox secret-proxies get github-api --json
```

### 4. Grant it to a template

`--add-network-access` adds an HTTPS rule for `api.github.com` if the network policy doesn't have one:

```bash
sanbox templates secret-proxies grant <template-id> github-api --add-network-access --json
sanbox templates secret-proxies list <template-id> --json
```

### 5. Start or resume a Computer

Grants apply when a Computer starts or resumes. Start a new Computer, or stop and resume a running one:

```bash
sanbox run --template <template-id> --json
sanbox runs stop <run-id> --wait --json
sanbox runs resume <run-id> --wait --json
sanbox runs secret-proxies <run-id> --json
```

### 6. Call the API without a key

Inside the Computer, the agent uses the normal URL. The second command checks that no GitHub token reached the environment:

```bash
sanbox exec <run-id> -- curl --fail-with-body https://api.github.com/repos/acme/app/pulls
sanbox exec <run-id> -- 'env | grep -i github || echo "no GitHub variables in the environment"'
```

### 7. Rotate or revoke

A rotation applies from the next matching request, including in running Computers. Revoking a grant applies from each Computer's next start or resume:

```bash
sanbox secret-proxies rotate github-api --secret-stdin --json < ~/.config/github-agent-token-new
sanbox templates secret-proxies revoke <template-id> github-api --json
```

## What are the rules?

- **HTTPS on port 443 only.** Plain HTTP requests and requests to IP addresses never receive the credential.
- **The network policy must allow the host.** A grant alone doesn't open it.
- **Unmatched requests pass through without the credential**, keeping whatever authentication the caller sent.
- **Some clients bring their own trust store.** Java's keystore needs `/dev/sanbox/runtime-ca.pem` added. Don't turn off TLS verification to make a client work.
- **Changes apply on the next start or resume**, except rotation, which applies at once.
- **Errors carry headers.** Intercepted responses include `X-Sanbox-Request-ID`, and gateway errors add `X-Sanbox-Error-Code`. A 401 or 403 can still come from the API itself.

## What about git push?

This recipe covers GitHub's REST API at `api.github.com`. Pushing code over HTTPS goes to `github.com` and is a separate setup that this page doesn't cover. A safe default is to copy the repository in with `sanbox cp`, review the agent's diff and push it yourself.

## What this doesn't do

- **It keeps the key off the machine; it doesn't prevent misuse.** The agent can still do anything the token and the proxy's rules allow, and send data it can read to any host the network policy allows. Keep tokens narrow and paths tight.
- **It doesn't protect keys you put on the disk yourself.** Files are copied as they are into forks and snapshots.
- **It keeps no request history.** No per-request log is stored, so log on the API side if you need an audit trail.
- **The run ID header isn't authentication.** If you turn on `attach_run_id`, the API must still authenticate the request before it trusts `X-Sanbox-Run-ID`.

## Related

- [How do I restrict which domains an AI agent can reach?](https://sanbox.cloud/kb/security/restrict-which-domains-an-agent-can-reach/)
- [Give your agent its own computer, not SSH to production](https://sanbox.cloud/kb/security/agent-own-computer-not-ssh-to-production/)
- [Why can't my AI agent reach a website or package registry?](https://sanbox.cloud/kb/errors/why-cant-my-agent-reach-a-website/)
- [How do I give every employee their own AI agent computer?](https://sanbox.cloud/kb/teams/agent-computer-for-every-employee/)

## Sources

- [Docker: Variable interpolation](https://docs.docker.com/compose/how-tos/environment-variables/variable-interpolation/), `.env` files (checked 2026-11-06)
- [Docker: docker compose config](https://docs.docker.com/reference/cli/docker/compose/config/) (checked 2026-11-06)
- [GNU Bash manual: History facilities](https://www.gnu.org/software/bash/manual/html_node/Bash-History-Facilities.html) (checked 2026-11-06)
- [Linux man page proc_pid_environ(5)](https://man7.org/linux/man-pages/man5/proc_pid_environ.5.html) (checked 2026-11-06)
- [git-credential-store](https://git-scm.com/docs/git-credential-store), plain-text storage (checked 2026-11-06)
- [GitHub: Authenticating to the REST API](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api), bearer tokens (checked 2026-11-06)
- [GitHub: Managing your personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), fine-grained tokens (checked 2026-11-06)

## Next step

Talk to us at sales@sanlabs.ai. Sanlabs' forward-deployed engineers build agent use cases with your team, with experience in aviation, pharmaceuticals, supply chain and logistics, and internal admin workflows. How we work: https://sanbox.cloud/kb/teams/forward-deployed-engineering.md

Existing customers can use Sanbox from a coding agent: install the CLI with `npm install -g @sanlabs/sanbox-cli@latest`, sign in with `sanbox login`, then run `sanbox skill` for the full agent guide.
