Security and vault
How the OpenLLM vault encrypts your provider credentials in your browser behind a recovery phrase, what our servers can see, and what to do if a key leaks.
To route your requests, OpenLLM has to hold your provider credentials: API keys, custom endpoint keys, and marketplace keys. A database that stores them in readable form would be a single place to steal all of them. The vault is how OpenLLM avoids that. This page explains how it works, what it does not protect, and what to do when something leaks.
How the vault works
Your vault is protected by a recovery phrase of 12 words. OpenLLM generates it in your browser when you create your vault. It works like a password that OpenLLM never receives.
- From the phrase, your browser derives a wrapping key with Argon2id and uses it to seal a random vault key with AES-256-GCM. The server stores only the sealed vault key and a salt.
- Your provider credentials are encrypted with the vault key in your browser, before they are sent. The server stores only ciphertext.
- Your chat transcripts and memory text are encrypted with the same vault key.
- Each
sk-llm-…API key carries its own sealed copy of the vault key. When a request arrives with your key, the server unseals the vault key, decrypts the one credential the request needs, calls the provider, and wipes both from memory.
You don't type the phrase every day. Each browser unlocks the vault with a PIN (4 or 6 digits, set per browser) or a passkey such as Touch ID. After you unlock, the vault stays open in that browser for the time you choose under Settings → Account → Vault → Auto-lock: 24 hours (the default), 7 days, or 14 days. Select Lock now to close it early.
To set up a PIN or passkey, view your phrase, or approve a new device, see Recovery, PIN and reset.
Subscription logins work differently. They stay on your own machine, and the daemon uses them there, from each vendor's own CLI login. They are not stored in the vault.
What our servers can and cannot see
| Data | Stored as | Readable by OpenLLM |
|---|---|---|
| Recovery phrase | Not stored | Never |
| PIN | Not stored. Only the sealed vault key in your browser. | Never |
| Vault key | Sealed with your phrase, each passkey, and each API key | Only in memory, during a request made with one of your API keys |
| Provider credentials | Ciphertext | Only in memory, during a request that uses them |
Prompts and responses sent to /v1 | Not stored, except a 10-minute cache when you send an Idempotency-Key | While the request runs |
| Chat transcripts | Ciphertext, encrypted in your browser | No |
| Chat titles | Plaintext | Yes |
| Memory text | Ciphertext | Only in memory, during a request made with one of your API keys |
| Memory search vectors | Plaintext | Yes. They reveal roughly what a memory is about, not its wording. |
| Generated media and chat attachments | Unencrypted files at public, unguessable URLs | Yes |
| Request metadata (model, provider, token counts, latency, status, cost estimate, key id) | Plaintext | Yes |
| Subscription logins | Stay on your device | No |
For what is kept and for how long, see Privacy.
If a key leaks
What someone can do depends on what they got:
| Leaked item | What it exposes |
|---|---|
An sk-llm-… API key | Everything the key can do on its own. The holder can call the API as you, which spends your plan allowances and your connected providers. The key also unlocks your vault key, so it can decrypt your saved provider credentials and read and write your memories. It can also reset your vault or delete your account. Treat every API key as a master key. |
| Your recovery phrase | Your whole vault, for anyone who can also sign in to your OpenLLM account: provider credentials, chats, memories, and new API keys. |
| Your PIN alone | Nothing. A PIN only opens the sealed vault key stored in the one browser where you set it, so it is useless without that browser profile. |
| A browser with your vault unlocked | What you can do in that browser while it stays unlocked: copy your API keys, use your providers in chat, read your chats and memories, and create keys. Showing your recovery phrase still asks for the PIN or passkey. |
| A passkey | Your vault, for anyone who can use the passkey and also sign in to your OpenLLM account. On its own, a passkey opens nothing. |
| Your sign-in (Google, GitHub, or email and password) | Your account without the vault: chat titles, usage, devices, and your media library. They can't decrypt credentials, chats, or memories, but they could reset your vault or delete your account. |
What to do
- A leaked API key: open Devices & keys and delete the key. It stops working at once and every client using it gets
401. Create a new key for the clients that need one. If the key may have been used by someone else, replace the provider API keys you saved in OpenLLM at each provider, and consider resetting your vault, which replaces the vault key itself. - A leaked recovery phrase: reset your vault right away. This replaces the phrase and the vault key, and revokes every API key. See Reset your vault.
- A lost or stolen computer: delete the keys of the devices on it in Devices & keys. If its browser had your vault unlocked, also reset your vault.
- A compromised sign-in: secure your Google or GitHub account, or change your OpenLLM password, first, then check Devices & keys for keys you don't recognize.
Limitations
The vault narrows what a breach exposes. It doesn't make OpenLLM a place where nothing can go wrong. These are the trade-offs you accept by using it:
- An API key decrypts your credentials. Every
sk-llm-…key carries the vault key, so anyone holding one can use your saved provider credentials. This is how requests work without your browser, and it is why a leaked key needs deleting at once. - The server sees plaintext while a request runs. Prompts, responses, the provider credential, and any memory text exist in readable form in memory for the length of a request. OpenLLM does not store prompts or responses, apart from the 10-minute idempotency cache.
- Memory search vectors are plaintext. They are needed for search and reveal what a memory is about. Memory text is also sent to AWS Bedrock to compute them.
- Generated media and chat attachments are public. Anyone with the URL can open the file. See Chat.
- Chat titles are plaintext, so a sensitive first line shows in the chat list on the server.
- Included models are served by third parties. Requests to included
openllm/models go to OpenRouter and Alibaba DashScope on OpenLLM's own accounts. See Included models. - Request metadata is kept for the life of your account to show usage and cost: model, provider, token counts, latency, status, cost estimate, and key id. See Privacy.
- A compromised machine running the daemon is compromised. The daemon holds an API key and uses your subscription logins there. Malware on that machine can use both. If you turned on remote sessions there, it also accepts terminal sessions opened from your OpenLLM account in a browser.
- The recovery phrase can't be recovered. OpenLLM has no copy. If you lose the phrase and every PIN and passkey, the only way back is a vault reset, which deletes what the vault protects.
Further reading
- Recovery, PIN and reset
- Privacy and the full privacy policy
- Devices
Last updated on
Memory and integrations
Give Claude Code, Codex and your other clients a shared, encrypted memory through the OpenLLM MCP server, and add marketplace tools such as context.dev.
Recovery, PIN and reset
Save your 12-word recovery phrase, unlock your vault with a PIN or passkey, get back in after you lose access, and reset the vault as a last resort.