Docs menu+

Encryption, key caching, audit log, and the threat model.

#Security

mcpvault is local-first. Nothing leaves your machine. There is no server, no account, no telemetry. The threat model below is everything that can happen to your credentials.

#Encryption at rest

The vault file at ~/.mcpvault/vault.enc is encrypted with AES-256-GCM. The encryption key is never stored in clear it is derived from your master password using Argon2id with parameters tuned for interactive use:

Argon2id:
  memory cost:  64 MiB   (m=65536)
  time cost:    3        (t=3)
  parallelism:  1        (p=1)
  salt:         16 random bytes per vault
  output:       32 bytes (256-bit AES key)

These parameters are the OWASP recommended baseline for interactive logins. A modern laptop derives the key in ~400ms; a brute-forcer needs ~64 MiB of RAM per attempt, which destroys GPU and ASIC parallelism.

The master password is never written to disk. It exists only in the process that prompted for it, long enough to derive the key, then is zeroed.

#Key caching

To avoid re-prompting on every command, the derived session key (not the password) is cached in your OS keyring:

| OS | Backend | File |

|---|---|---|

macOSKeychain Serviceslogin.keychain
Linuxlibsecret (gnome-keyring / kwallet)~/.local/share/keyrings/*

The cached key is protected by your OS login. Without your OS password, neither the cache nor the vault file is useful.

Lock at any time:

bash
mcpvault lock

This zeros the cached session key. Next command will re-prompt for the master password.

#Credentials never leave the wrapper

Wrappers run as separate processes. Their job is:

  1. 1Read the active label from ~/.mcpvault/active.json on every tool call.
  2. 2Decrypt the credential for that label, in-memory only.
  3. 3Call the upstream API (Supabase, GitHub, etc.).
  4. 4Return the API's response to the chat client.

The chat client never sees the bearer token. It sees only the API result.

This means:

  • An LLM cannot exfiltrate your token through prompt injection. It does not have the token.
  • A compromised chat client cannot dump your credentials. They are not in its memory.
  • Tool results are still readable by the LLM sensitive data inside an API response (a customer email, a project name) is visible to the model. Treat tool results like normal LLM context.

#Audit log

Every tool call writes one line to ~/.mcpvault/vault.log:

2026-05-15T14:22:31Z supabase work supabase_run_sql
2026-05-15T14:22:33Z github  personal github_list_repos

Format: timestamp, service, label, tool name. No credentials, no arguments, no responses. The log is append-only and rotates at 10 MB.

mcpvault audit pretty-prints recent activity. Useful for "what did the agent touch on Tuesday?" without exposing secrets.

#What is NOT in the threat model

  • Malware running as your user: if an attacker has code execution as your OS user, they can read the OS keyring entry and decrypt the vault. mcpvault assumes your OS account is yours.
  • A coerced master password: rubber-hose attacks defeat any encryption.
  • Token compromise upstream: if Supabase leaks its database of tokens, mcpvault can't help. Rotate tokens periodically.
  • Stolen disk only (no OS login): the vault file alone is useless without the password. Adversary needs both files (vault.enc + the OS keyring entry) AND your OS password to skip the master-password prompt.

#Rotating the master password

bash
mcpvault unlock # if locked mcpvault password rotate # prompts for current + new password

This re-derives a new key with a new salt, re-encrypts the vault, and updates the OS keyring entry. Existing wrapper processes are unaffected; they pick up the new key on next call.

Security — mcpvault docs