BYOK: the provider key vault

Bring Your Own Key. Every provider key your organisation uses is stored once, in a vault the gateway can decrypt and nobody can read. Your applications carry only your Vulnetix API key; the provider key is injected by the gateway after your request clears policy.

Store a key

CLI
# From an environment variable — the recommended form
export OPENAI_API_KEY=sk-proj-...
vulnetix ai-firewall key set openai --from-env OPENAI_API_KEY

# Or piped, if the key is in a secret manager
op read "op://vault/openai/key" | vulnetix ai-firewall key set openai --stdin
Warning --key sk-... also works, but puts the key in your shell history. The CLI warns you when you use it. Prefer --from-env or --stdin.

The key is validated before it is sent: an empty key, one over 4096 bytes, or one containing a control character is rejected locally, because a control character would corrupt the upstream header rather than fail cleanly.

Dashboard

Open the AI Firewall dashboard, go to the BYOK tab, choose the provider, and paste the key.

It is encrypted on save. The field will never show it to you again — the dashboard can only tell you that a key is stored and when it was last updated.

Replace or remove a key

There is no “edit”. A rotation is a replace; a revocation is a remove.

vulnetix ai-firewall key set openai --from-env NEW_OPENAI_KEY   # replace
vulnetix ai-firewall key remove openai                          # remove

Removal takes effect on the next request — the gateway reads the stored key fresh every time, so a removed key stops working immediately rather than lingering for the life of a cache.

After removing a key, requests to that provider return a 403:

{
  "error": {
    "message": "no OpenAI API key configured for your organisation: add one with 'vulnetix ai-firewall key set openai' or at https://www.vulnetix.com/vdb-ai-firewall#byok",
    "type": "policy_violation",
    "code": "provider_key_missing"
  }
}

How the encryption works

This is the part worth understanding, because it is what makes the vault different from “we put your key in a database”.

  • Envelope encryption with AWS KMS. The stored value is a KMS ciphertext blob, not a reversible encoding.
  • Bound to your organisation and that provider. The ciphertext is encrypted under an encryption context that names both. KMS enforces it on decrypt: a ciphertext lifted from your organisation’s row and replayed under another organisation does not decrypt. Stealing the database does not get you the keys.
  • Write-only. No API returns a stored key. Not the dashboard, not the CLI, not an admin endpoint — there is no read path in the system at all. The dashboard shows presence and a timestamp; that is the whole surface.
  • Decrypted just-in-time, injected into the upstream request, and never written to a log.

Your Vulnetix credential is stripped before the request goes upstream. The provider sees its own key and nothing else of yours.

What does not change

Your billing relationship with the provider is untouched. The firewall does not proxy your payment, pool your key with anyone else’s, resell your tokens, or take a markup. Your provider quotas, spend limits, and organisation controls all still apply exactly as they did — which is also why the firewall can be free.

Secret hygiene on your own machine

vulnetix ai-firewall install writes a reference to your key ($VULNETIX_API_KEY), never the literal — so a wired config is safe to commit.

Two things are worth knowing:

  • --embed-key is refused when the target is not git-ignored. If you ask the CLI to write the literal key into a file the repository would track, it errors out rather than help you commit a secret.
  • Continue is the exception. ~/.continue/.env holds a literal key, because the IDE extension cannot read your shell environment. The CLI writes it chmod 600. If that is not acceptable in your environment, do not wire Continue.

You can audit for keys that ended up on disk with vulnetix secrets.