Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agent-vault.dev/llms.txt

Use this file to discover all available pages before exploring further.

Agent Vault is designed around a single principle: Agent Vault never reveals vault-stored credentials to agents. Credentials are encrypted at rest, decrypted only in memory at proxy time, and injected into outbound requests server-side. No credential value stored in the vault is ever returned in an API response or written to a log. This page covers the cryptographic primitives, token model, network protections, and operational safeguards that make this possible.
Passthrough services are an operator-chosen exception: they allowlist a host without storing or injecting any credential. The guarantees below apply to credentials stored in the vault — a credential the client holds outside the vault is not protected by Agent Vault, but the host allowlist, netguard, TLS interception, and audit logging still apply.

Encryption at rest

All credentials stored in a vault are encrypted using AES-256-GCM, an authenticated encryption scheme that provides both confidentiality and tamper detection. Agent Vault uses a KEK/DEK key-wrapping architecture:
  1. A random 256-bit DEK (Data Encryption Key) is generated on first boot. This key encrypts all credentials and the CA private key.
  2. If a master password is set, Argon2id derives a KEK (Key Encryption Key) that wraps the DEK. The KEK is never stored — it is derived in memory, used to unwrap the DEK, then wiped.
  3. If no master password is set (passwordless mode), the DEK is stored in plaintext in the database. Security depends on filesystem access controls — suitable for PaaS platforms where the platform manages volume isolation.
ParameterValue
Data encryptionAES-256-GCM
Key wrappingAES-256-GCM
KDF (for KEK)Argon2id
Time cost3 iterations
Memory cost64 MiB
Parallelism4 threads
DEK length256 bits (random, crypto/rand)
KEK length256 bits (Argon2id output)
Salt length128 bits (random per setup)
Each encryption operation uses a fresh random nonce generated from crypto/rand. Credential values are decrypted in memory only at proxy time to resolve auth headers, then discarded. Password changes are lightweight: changing the master password re-wraps the DEK under a new KEK — a single database update with zero credential re-encryption. You can also add a password to a passwordless instance or remove a password entirely using agent-vault master-password set|change|remove.
The master password is never stored on disk. If set via the AGENT_VAULT_MASTER_PASSWORD environment variable, Agent Vault unsets it from the process immediately after reading. The KEK derived from the password is wiped from memory after unwrapping the DEK.

Password hashing

User passwords are hashed with Argon2id using the same parameters as master key derivation. Each user gets an independent random salt. Password verification uses constant-time comparison (crypto/subtle.ConstantTimeCompare) to prevent timing attacks. KDF parameters are stored per user, so Agent Vault can upgrade hashing parameters in the future without invalidating existing accounts. Changing a password (agent-vault account change-password or POST /v1/auth/change-password) invalidates all existing sessions and issues a fresh token. User sessions are long-lived but idle-expired. A login is good for up to a year of activity; if a session goes 30 days without making a request, it is automatically rejected as expired. Active operators effectively never have to log in again, while a stolen ~/.agent-vault/session.json that goes unused loses access in 30 days. Operators can view and revoke individual sessions with agent-vault auth sessions list / revoke, or invalidate every session at once via account change-password.

Token model

All tokens are generated from crypto/rand (256 bits of entropy) and hashed before storage. The raw token is returned to the caller exactly once; Agent Vault only stores the hash.
TokenPrefixStorage hashTTLNotes
User sessionav_sess_SHA-2561 year absolute, 30-day idleBumped on each authenticated request
Scoped sessionav_sess_SHA-256Configurable (5 min – 7 days, default 24h)Vault-bound, minted by vault run
Agent tokenav_agt_SHA-256Configurable (or no expiry)Instance-level agent identity
Inviteav_inv_SHA-25615 minutesSingle-use, burned on redemption
Approvalav_appr_SHA-25624 hoursGrants read-only access to a proposal
Vault inviteav_uinv_SHA-25648 hoursFor onboarding human users
All tokens use SHA-256 for fast lookup.

Network security

Agent Vault includes a network guard that validates every outbound proxy connection at the IP level, preventing agents from using the proxy to reach internal infrastructure.

Policy

Outbound proxy connections are validated against the resolved IP. By default, every RFC-1918, loopback, link-local, IPv6 ULA, and CGN range is blocked, plus cloud metadata endpoints. Set AGENT_VAULT_ALLOW_PRIVATE_RANGES=true for local/trusted deployments where the proxy needs to reach internal services on private IPs. To keep the block on but punch narrow holes for known internal services, set AGENT_VAULT_NETWORK_ALLOWLIST=10.163.0.0/16,192.168.1.1 (CIDRs or bare IPs, comma-separated). Cloud metadata endpoints stay blocked regardless.

Always blocked

Cloud provider metadata endpoints are blocked unconditionally — including when allowlisted — to prevent credential theft via SSRF:
  • 169.254.169.254/32 (AWS, GCP, Azure instance metadata)
  • fd00:ec2::254/128 (AWS IMDSv2 IPv6)

Blocked when AGENT_VAULT_ALLOW_PRIVATE_RANGES=false

RFC-1918 and other reserved ranges are additionally blocked under the default policy, unless explicitly allowlisted:
  • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (private)
  • 127.0.0.0/8, ::1/128 (loopback)
  • 169.254.0.0/16, fe80::/10 (link-local)
  • fc00::/7 (IPv6 unique local)
  • 100.64.0.0/10 (carrier-grade NAT)
  • 0.0.0.0/32

DNS rebinding protection

Agent Vault resolves hostnames to IP addresses, validates every resolved IP against the block list, then connects directly to the validated IP. This prevents DNS rebinding attacks where a hostname resolves to a safe IP during validation but a different (internal) IP during connection.

Transport security

All proxied requests are forwarded over HTTPS, regardless of how the agent connects to Agent Vault locally. The agent’s session token never reaches the target service: on the explicit /proxy ingress it travels in Authorization and is stripped; on the transparent HTTPS_PROXY ingress it travels in Proxy-Authorization (which is hop-by-hop and never forwarded). Real credentials are injected server-side based on the vault’s services. Other client request headers — vendor headers like anthropic-version, conditional request headers, tracing IDs — flow through to the upstream unchanged. The broker only takes over the headers it is responsible for injecting (the auth slot for the configured auth type) plus hop-by-hop and broker-scoped headers; see Header forwarding for the precise rules. This means:
  • Agents authenticate to Agent Vault with a token that grants no direct access to credentials.
  • The agent’s token never reaches the target service.
  • Credential values only exist in the outbound request headers, never in the agent’s address space.

Transparent proxy (HTTPS_PROXY) transport

The MITM listener that backs HTTPS_PROXY is itself TLS-wrapped with a cert signed by the software-backed root CA. This means the CONNECT handshake carrying the agent’s session token is encrypted end-to-end between the client and the broker — session tokens are never exposed in plaintext on the wire, even on an untrusted local network.
  • Root CA private key is encrypted at rest with the DEK (same key that wraps credentials). See Encryption at rest.
  • DNS rebinding protection and netguard apply to both the transparent proxy and the explicit /proxy endpoint — every outbound connection is resolved and validated against the IP blocklist before Agent Vault dials the upstream.
  • Rate limiting shares one (actor, vault) budget across both ingress paths; switching from one to the other does not bypass the limit.

Access control

Agent Vault enforces access at two independent layers. For full details, see Permissions.
  • Instance roles (owner, member) control who can manage users, vaults, and server settings. Both users and agents have instance-level roles. Owners can see and join any vault, but must explicitly join to access vault contents.
  • Vault roles (admin, member, proxy) control who can approve proposals, manage agents, and use the proxy within a specific vault.
  • Agents are instance-level entities that can access multiple vaults via the X-Vault header. Vault-scoped sessions (from vault run) are limited to a single vault.
  • Proposal approval requires a valid user session. Read-only approval tokens let you view the proposal, but submitting an approval (providing credentials, clicking “Allow”) requires logging in.
  • Email domain restrictions — Owners can restrict signups to specific email domains (e.g., @acme.com). This applies to email/password registration, Google OAuth signup, and vault invite acceptance. The first user (owner) is exempt. Configure via Manage > Settings in the web UI or agent-vault owner settings set --allowed-domains.

OAuth security

When Google OAuth is enabled, Agent Vault applies several security measures:
  • No automatic account linking — OAuth callbacks never link to existing accounts from unauthenticated contexts. If a Google email matches an existing email/password user, sign-in is rejected with a generic error. This prevents pre-hijack attacks.
  • Safe linking from settings — Authenticated users can connect OAuth providers from account settings, where identity is already proven.
  • PKCE (S256) — All OAuth flows use Proof Key for Code Exchange to prevent authorization code interception.
  • CSRF state parameter — 32-byte random state, SHA-256 hashed in the database, single-use, 10-minute expiry.
  • ID token validation — RS256 signature verified against Google’s JWKS (cached 1 hour), with issuer (accounts.google.com), audience (client ID), and expiry checks.
  • No token storage — Google access and refresh tokens are not stored. Only ID token claims are used at login time.
  • Generic error messages — OAuth errors do not reveal whether an email is registered.
  • Timing attack prevention — Login attempts for OAuth-only users run a dummy KDF hash to prevent timing-based auth method detection.
  • Owner protection — The first user must register with email/password. OAuth login is rejected when no users exist.

Rate limits

Request rate limiting

Agent Vault enforces a tiered, in-memory rate limiter on every HTTP ingress. Each tier is keyed on the principal appropriate for that endpoint, so one noisy client cannot drown out another:
TierKeyed onCovers
AUTHClient IPAnonymous endpoints (login, registration, OAuth callback)
AUTHEDSession token hashInvite redemption, proposal approval, authenticated CRUD
PROXY(actor, vault) scopeProxy path and MITM ingress
GLOBALServer-wideIn-flight request ceiling and RPS backstop
Requests that exceed a tier return 429 Too Many Requests with a Retry-After header so clients can back off. Operators pick a profile via AGENT_VAULT_RATELIMIT_PROFILE (default, strict, loose, off) or tune individual tiers in Manage Instance → Settings → Rate Limiting. Setting AGENT_VAULT_RATELIMIT_LOCK=true pins limits to env vars and makes the UI read-only, which is recommended on PaaS deployments. See environment variables for the full knob list.

Resource caps

Hard caps prevent unbounded growth in vault state:
ResourceLimit
Pending proposals per vault20
Pending agent invites per vault10
Pending user invites per vault50
Active sessions per agent10
Rules per proposal10
Credential slots per proposal10

Database security

Agent Vault uses SQLite with the following hardening:
  • File permissions: Database file is created with mode 0600 (owner read/write only).
  • Parameterized queries: All queries use prepared statements, preventing SQL injection.
  • WAL mode: Write-ahead logging for crash resilience.
  • Foreign key cascades: Deleting a vault automatically cleans up all associated credentials, proposals, agents, and sessions.

Sensitive data handling

A summary of how each category of sensitive data is stored:
DataStorage formatReadable after storage?
CredentialsAES-256-GCM ciphertext + nonceYes, by vault members and admins via CLI (credential get, credential list --reveal). Proxy-role agents cannot read values.
User passwordsArgon2id hash + salt + paramsNo
Session tokensSHA-256 hashNo (raw returned once at creation)
DEK (data encryption key)Wrapped by KEK (password mode) or plaintext (passwordless mode) in master_key tableYes, in memory while server runs
Master passwordNot storedN/A (KEK derived in memory, wiped after DEK unwrap)
Key material is zeroed after use via WipeBytes() on a best-effort basis. Sensitive byte slices are never converted to strings (Go strings are immutable and cannot be wiped from memory).