Guide · Security

Pass API tokens to a coding agent without leaking them

A sandboxed agent still has to authenticate to its provider API. h5i keeps the real key on the host and lets the box authenticate through a credential-injecting proxy, so a prompt-injected agent has no reusable token to read or exfiltrate.

When you run Claude Code or Codex inside an h5i env sandbox, the agent still needs a credential to reach api.anthropic.com or api.openai.com. The obvious approaches all put the token where the agent can read it: an environment variable shows up in /proc/self/environ, and a credential file sits on disk in the box. A prompt-injected agent can read either one. On a tier without an airtight network boundary it could even send the key somewhere.

The idea: keep the token on the host

h5i runs a small credential-injecting proxy on the host. The box is pointed at it with a base URL override and a per-run dummy token. The proxy strips the dummy, injects the real credential, and forwards the request to the provider over TLS. The genuine token never enters the box: it lives only in the proxy's memory on the host.

flow
box ──http(dummy)──▶ 10.0.2.2:PORT  (host loopback)
                     h5i proxy: verify dummy → inject REAL key
                     └──TLS──▶ https://api.anthropic.com  (real key, host only)

Step 1: export the token on the host

Set the credential in the shell you launch h5i from. h5i reads it with the same precedence the runtime's own CLI uses.

~/my-project
# Claude: ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then CLAUDE_CODE_OAUTH_TOKEN
$ export ANTHROPIC_API_KEY=sk-ant-...

# Codex: OPENAI_API_KEY
$ export OPENAI_API_KEY=sk-...

Step 2: create and enter a sandboxed env

Create an agent env on a tier that can enforce network egress. The credential proxy engages automatically when the profile is an agent runtime and a host token is present. No extra flag.

~/my-project
$ h5i env create review --isolation container
  env 'review' created  (profile agent-claude, isolation container)
$ h5i env shell review
  h5i:review$

Prefer the kernel-level tier when you want an airtight L3/L4 boundary rather than an HTTP-level one. The credential handling is the same.

~/my-project
$ h5i env create review --isolation supervised

Step 3: verify the token is not in the box

Inside the session, the base URL points at the host proxy and the only token present is the per-run dummy. Your real key is nowhere in the box.

h5i:review
h5i:review$ env | grep -i anthropic
ANTHROPIC_BASE_URL=http://10.0.2.2:47213
ANTHROPIC_AUTH_TOKEN=h5i-proxy-9f3c1a...   # a per-run dummy, not your key

h5i:review$ printenv ANTHROPIC_API_KEY       # the real key is absent

# supervised tier: the stored credential file is scrubbed from the box copy too
h5i:review$ cat ~/.claude/.credentials.json
cat: /home/agent/.claude/.credentials.json: No such file or directory

# and the agent still works — it authenticates through the proxy
h5i:review$ claude -p "summarize the staged diff"
  The change adds a retry around the upload and a test for the timeout path…

What makes it secure

Tier differences at a glance

tiers
                     container                supervised
real token in box    never (no HOME mount)    scrubbed from HOME copy
egress boundary      L7 CONNECT allowlist     L3/L4 nftables, proxy-only
box reaches          proxy at 10.0.2.2        proxy at 10.0.2.2 (1 nft accept)
host requirement     rootless podman          slirp4netns + nft

Check what a host can actually enforce before you rely on it:

~/my-project
$ h5i env probe            # isolation tiers available on this host
$ h5i env capabilities     # the enforced tier, egress, and limits

Turning it off

Sometimes you want the box to use its own in-box login instead, for example to bill a subscription that is logged in inside the box rather than a host-exported key. Set H5I_CREDENTIAL_PROXY=off and the proxy stays out of the way.

~/my-project
$ H5I_CREDENTIAL_PROXY=off h5i env shell review
Defense in depth. The proxy removes the token as a target. Pair it with least-privilege tools and egress limits, and audit the agent's reasoning trace for injection attempts, so a hijacked agent is both contained and visible.

Frequently asked questions

Why not just export the API key inside the agent box?

An environment variable is readable by the agent and everything it spawns via /proc/self/environ. A prompt-injected agent could read the key and, on a tier without an airtight egress boundary, exfiltrate it. The credential-injecting proxy keeps the real key on the host so there is nothing reusable to steal.

How does the agent authenticate if the token is not in the box?

The box is pointed at a host-side proxy with a base URL override and a per-run dummy token. The proxy strips the dummy, injects the real credential, and forwards the request to the provider over TLS. The genuine token lives only in the proxy's memory on the host.

Which host environment variables does h5i use for the credential?

For Claude it checks ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then CLAUDE_CODE_OAUTH_TOKEN. For Codex it uses OPENAI_API_KEY. This matches each runtime's own precedence. Export the token on the host before creating or entering the env.

Can the agent point the proxy at a different host to steal the token?

No. The proxy forwards to a single upstream host pinned per runtime. It ignores the request's own Host header and reuses only the path, so it cannot be aimed at an attacker host. The upstream address is DNS-pinned once at startup.

Does this work on the kernel-level supervised tier too?

Yes. On the supervised tier the box's network egress is locked by nftables to the proxy alone, and the credential file is removed from the box's per-env HOME copy, so the token is absent from the box entirely. The container tier never mounts host HOME, so there is nothing to remove there.

How do I turn it off for a session that should log in inside the box?

Set H5I_CREDENTIAL_PROXY=off. The box then keeps its own in-box login, which is useful when you want to bill a subscription logged in inside the box rather than a host-exported API key.

Try h5i in your repo

One cargo install, then h5i init. Give each agent a sealed sandbox that authenticates without holding your keys.

Star on GitHub All guides