Security
The auth model, credential encryption, and what the gateway redacts by default.
Auth model
Two kinds of keys, both checked via Authorization: Bearer <key> or x-api-key: <key>:
MASTER_KEY— full access. Required on every/admin/*route. Also usable on/v1/*(operator traffic); master-key requests never go through rate limiting, budgets, or the response cache.- Virtual keys — created via
POST /admin/keys, scoped to a set of allowed public models, with optional RPM/TPM limits and a spend budget. Used on/v1/*only. See Virtual keys.
/v1/models and /v1/models/{model} are the only unauthenticated endpoints — deliberately, like any
provider's public model listing. Everything else, including /v1/models/{model}/deployments
(per-deployment operational detail), requires a key. See Model discovery.
Virtual keys at rest
A virtual key is never stored in plaintext: only its SHA-256 hash and a 10-character prefix (for
display and search in GET /admin/keys) are persisted. The raw key is returned exactly once, at
creation — there is no way to retrieve it again afterward. Rotate by creating a new key and disabling
or deleting the old one.
Deployment credentials at rest
Every credential (apiKey, baseUrl, etc.) is encrypted with AES-256-GCM before being stored. Each
versioned envelope records a key id and purpose authenticated as AAD, and gets its own random IV. GCM's auth tag means
tampering with the stored ciphertext makes it fail to decrypt rather than silently returning garbage.
No admin API response — GET, POST, or PATCH on /admin/deployments— ever includes credentials,
encrypted or not; they're stripped before the response is built.
Losing every copy of a keyring entry while envelopes still reference it makes those values permanently
unrecoverable. Keep the keyring outside the database it decrypts and never commit it. For the online
rotation procedure for both MASTER_KEY and the encryption keyring, see
Operations → Secrets.
What the gateway redacts publicly
/v1/modelsand/v1/models/{model}expose aggregated capability/pricing data, but never deployment labels, credentials, database ids, or the exact upstream model id./v1/models/{model}/deployments(authenticated) exposes an opaque, deterministic per-deployment id (a truncated hash of the real one) and live metrics, but still never credentials or the upstream model id.- Operation logs (
GET /admin/logs) persist summaries and HMAC fingerprints, not request or response bodies.
Observability payloads
Forensic samples use purpose-bound AEAD envelopes under the versioned keyring, expire automatically, and never fall back to plaintext. HMAC fingerprints use a separate derived subkey. OpenTelemetry never receives payload bodies. See Environment variables and Observability.
Runtime extensions
Extension code is trusted, operator-uploaded ESM — it runs in-process with the same access as the
gateway itself. Only upload code you've reviewed; there is no sandboxing beyond the per-hook timeout and
consecutive-failure circuit breaker described in Extensions. Treat
POST /admin/extensions/artifacts with the same care as deploying new gateway code, because that's
effectively what it is.
Reporting a vulnerability
Follow SECURITY.md in the repository root. Do not open public issues for security problems.
What to read next
- Virtual keys — scopes, budgets, rotation.
- Environment variables — every secret and its format.
- Production checklist — what to verify before going live.