Securing the gateway
The trust model
Section titled “The trust model”costhelm’s core security property is a credential boundary: the gateway
owns every provider key; callers hold none. An agent runtime built on the
gateway cannot leak a key it never had — and rotating a key touches one
.env, not every consumer.
The shipped defaults assume a localhost or private-network deployment:
auth off, bind 0.0.0.0:8111. Before exposing the port any wider:
1. Turn on API-key auth
Section titled “1. Turn on API-key auth”COSTHELM_API_KEYS="key-one,key-two" costhelm serve- Guards everything under
/v1/*./healthzand the dashboard pages stay open (the pages’ own/v1/*reads need a key — they prompt once and keep it in localStorage). - Send
Authorization: Bearer <key>orX-API-Key: <key>. Comparison is constant-time. - Failure is a 401 with a structured envelope naming the fix.
- Multiple keys are for rotation: add the new key, roll consumers, remove the old.
Generate a key however you like, e.g.
python -c "import secrets; print(secrets.token_urlsafe(32))".
2. Bind narrowly, terminate TLS in front
Section titled “2. Bind narrowly, terminate TLS in front”costhelm serve --host 127.0.0.1 # localhost onlyFor anything crossing a network boundary, put a TLS-terminating reverse proxy (Caddy, nginx, Cloudflare Tunnel) in front — API keys over plain HTTP are only acceptable on loopback.
3. Mind the telemetry
Section titled “3. Mind the telemetry”Prompt/completion capture on spans is off by default and should stay
off against any shared collector — it is the highest-PII payload the
gateway handles. Enable COSTHELM_OTEL_CAPTURE_CONTENT=1 only against a
localhost collector holding test data.
4. Budgets are a security control too
Section titled “4. Budgets are a security control too”A leaked consumer key spends money. Ceilings per key-holder’s principal
(tenant:partner-x, agent:external-bot) bound the blast radius, and
POST /v1/budget with limit_usd: 0 is an immediate kill switch for one
principal — no restart, nothing else affected.