feat(llm-proxy): mission containers reach their models through a key-adding proxy (flagged)
deploy / test (push) Failing after 1m52s
deploy / build (push) Skipped

Container-tier missions held the platform's provider keys in their environment,
readable by an agent with Bash and public egress. With CLAWMATES_LLM_PROXY=1
(and CLAWMATES_LLM_PROXY_SECRET), a container instead holds a per-mission token
where each key was, ANTHROPIC_BASE_URL points at the server's proxy on :8089
(not published, not routed by Traefik), and the GLM/Kimi hops' base URLs are
rewritten in the mission's config copy. The proxy verifies the token
(HMAC(secret, mission_id) — stateless, survives redeploys), refuses it unless
the mission is running, swaps in the real credential and streams the response.

Spiked first on gw-04: Claude Code on a subscription OAuth token, given only a
placeholder and a base URL, sent nothing but POST /v1/messages there and
answered once the placeholder was swapped. Off by default; no behaviour change
until enabled.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-23 12:35:01 -05:00
co-authored by Claude Opus 5.5
parent 60a1fef5e5
commit 72fb0dcb6f
5 changed files with 415 additions and 2 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ futures = "0.3"
serde = { workspace = true }
serde_json = { workspace = true }
sqlx = { workspace = true }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "stream"] }
cm-auth = { path = "../cm-auth" }
cm-billing = { path = "../cm-billing" }
cm-brain = { path = "../cm-brain" }