docs(agent): clarify claude oauth env
test / unit (pull_request) Successful in 29s
test / integration (pull_request) Successful in 43s

This commit is contained in:
2026-05-28 18:20:09 -04:00
parent cacba087c9
commit cdb1870b1c
14 changed files with 41 additions and 40 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ entry and pushes straight at gitea/github with ssh-gate doing dumb
L4 forwarding. There is no boundary between "the agent thinks this
commit is fine" and "the secret hits an external remote." If a
compromised or careless agent stages a `.env`, slips a token into
a fixture, or commits the `BOT_BOTTLE_OAUTH_TOKEN` itself, `git
a fixture, or commits the `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` itself, `git
push` ships it.
Host-side pre-commit / pre-push hooks are the usual defense, but
+2 -2
View File
@@ -230,7 +230,7 @@ common upstreams (Anthropic, GitHub, Gitea, npm) as
```
┌── Host (macOS) ──────────────────────────────────────────────────┐
│ Secrets at rest (keychain / .env): │
│ BOT_BOTTLE_OAUTH_TOKEN, GITHUB_TOKEN, │
│ BOT_BOTTLE_CLAUDE_OAUTH_TOKEN, GITHUB_TOKEN, │
│ GITEA_SERVER_TOKEN, NPM_TOKEN │
│ │ docker run -e KEY (no =VALUE on argv) │
│ ▼ │
@@ -315,7 +315,7 @@ Why the agent can't reach the sidecar's environ:
+ validate route shape, role enum, path uniqueness, singleton-
role constraints.
- **`bot_bottle/backend/docker/prepare.py`** — drop the
legacy `BOT_BOTTLE_OAUTH_TOKEN` → `CLAUDE_CODE_OAUTH_TOKEN`
legacy `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` → `CLAUDE_CODE_OAUTH_TOKEN`
forward entirely. cred-proxy is the only path the Anthropic
OAuth token reaches the bottle. When a route claims the
`anthropic-base-url` role, write `ANTHROPIC_BASE_URL`
+1 -1
View File
@@ -261,7 +261,7 @@ cred_proxy:
- path: /anthropic/
upstream: https://api.anthropic.com
auth_scheme: Bearer
token_ref: BOT_BOTTLE_OAUTH_TOKEN
token_ref: BOT_BOTTLE_CLAUDE_OAUTH_TOKEN
role: anthropic-base-url
- path: /gitea/dideric/
upstream: https://gitea.dideric.is
@@ -78,7 +78,7 @@ The remaining credible designs reduce to three:
### Anthropic / Claude Code
**Today's wiring** (`bot_bottle/cli/start.py`): the host's
`BOT_BOTTLE_OAUTH_TOKEN` is forwarded into the bottle as
`BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` is forwarded into the bottle as
`CLAUDE_CODE_OAUTH_TOKEN` via `docker run -e CLAUDE_CODE_OAUTH_TOKEN`
(no `=value`, so the value never lands on argv — good). Inside the
bottle, claude runs as `node` (UID 1000) with
@@ -63,7 +63,7 @@ For a known-leaked or suspected-leaked token:
1. Revoke the entry at `claude.ai/settings/claude-code`.
2. Run "Log out all sessions" under Settings → Account → Active Sessions.
3. Run `claude setup-token` to mint a replacement, and rotate it into
`BOT_BOTTLE_OAUTH_TOKEN` immediately.
`BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` immediately.
4. Email Anthropic support at `support.anthropic.com`. Security issues
sometimes get attention that GitHub issues do not.
@@ -88,7 +88,7 @@ already on the attacker's box. Detection has to be at *commit* time
Two surfaces are exposed:
1. **The bot-bottle repo itself.** Development happens on a host
with `BOT_BOTTLE_OAUTH_TOKEN`, Gitea tokens, and other
with `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN`, Gitea tokens, and other
credentials in the environment. A fixture, test snapshot, log
capture, or pasted-in debug output could carry one of them into a
tracked file. The repo's Gitea remote is private, but mirrors or
@@ -254,7 +254,7 @@ cred_proxy:
- path: /anthropic/
upstream: https://api.anthropic.com
auth_scheme: Bearer
token_ref: BOT_BOTTLE_OAUTH_TOKEN
token_ref: BOT_BOTTLE_CLAUDE_OAUTH_TOKEN
role: anthropic-base-url
egress:
allowlist: [example.com]
+1 -1
View File
@@ -33,7 +33,7 @@ on top of working onboarding.
### Onboarding friction
A first-time user today goes through five steps: install Docker,
install `uv`, set `BOT_BOTTLE_OAUTH_TOKEN`, write
install `uv`, set `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN`, write
`bot-bottle.json`, run `./cli.py start`. One of those is
"author a JSON manifest." Polished tools in this category let
users skip that step on day one. The fix is an `init` subcommand
+3 -3
View File
@@ -102,7 +102,7 @@ work:
- **Typing latency.** Interactive Claude sessions over SSH have visible
per-keystroke latency; usually fine on wired/fiber, less fine on
Wi-Fi-to-cloud. Mosh helps if it's bothersome.
- **Token shipping.** `BOT_BOTTLE_OAUTH_TOKEN` has to live on the
- **Token shipping.** `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` has to live on the
remote box for the launcher to forward it into containers. Use the
provider's secret-injection path (cloud-init user-data,
`flyctl secrets`, Tailscale-served local file, etc.). Never echo the
@@ -130,7 +130,7 @@ The minimum-viable workflow, no bot-bottle code changes:
(`curl -fsSL https://get.docker.com | sh`).
3. SSH in.
4. `git clone` bot-bottle on the VM, drop a manifest in place,
inject `BOT_BOTTLE_OAUTH_TOKEN` via the provider's secrets path.
inject `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` via the provider's secrets path.
5. `./cli.py start <agent>` — the existing launcher handles the rest.
6. On exit: destroy the VM. No host artifacts persist.
@@ -157,7 +157,7 @@ Build a custom OCI image `FROM docker:dind` that bakes in:
the dind storage. Without this step, the first in-VM `docker build`
runs `apt-get` and a global `npm install -g
@anthropic-ai/claude-code`, which adds 3090 s to every cold start.
- A `flyctl secrets`-injected `BOT_BOTTLE_OAUTH_TOKEN`, exposed to
- A `flyctl secrets`-injected `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN`, exposed to
the VM's PID 1 as an env var.
- An entrypoint that starts dockerd, waits for it to be healthy, then
either drops into a shell or directly runs `cli.py start <agent>`.
@@ -79,7 +79,7 @@ The agent's conversation channel is therefore wide open as an exfil
path. A prompt-injected agent that has been told a secret can ship
it to Anthropic as conversation text, formatted however it likes,
and pipelock sees only `CONNECT api.anthropic.com:443`. The
`BOT_BOTTLE_OAUTH_TOKEN` itself rides this exact path.
`BOT_BOTTLE_CLAUDE_OAUTH_TOKEN` itself rides this exact path.
### 3. Out-of-band channels exist regardless
@@ -134,7 +134,7 @@ per-bottle gate that:
Two concrete instances worth implementing:
**Anthropic-API gate.** Holds `BOT_BOTTLE_OAUTH_TOKEN`. Agent's
**Anthropic-API gate.** Holds `BOT_BOTTLE_CLAUDE_OAUTH_TOKEN`. Agent's
`ANTHROPIC_BASE_URL` points at the gate; gate injects
`Authorization: Bearer …` and forwards to api.anthropic.com. The
token is no longer in the bottle's env. Once the token is out,