// Security

Don't trust us.
Verify us.

Zero-knowledge is a claim anyone can make. Here's how OpaqueVault proves it — at the protocol level, on the wire, and in your AI agent's context window. No source code required.

// Three provable guarantees

Encrypted at rest.
In transit.
In use.

Most security products prove two. The AI agent boundary is new — OpaqueVault treats it as a provable property, not a promise: the wire contract for all three is published, frozen by test, and verifiable from your own terminal.

01

At rest

The server stores only ciphertext. No plaintext values, no master passwords, no Key Encryption Keys. Every secret is encrypted with AES-256-GCM before it leaves your machine.

// Verify it yourself

Call the API directly. The response is always an encrypted blob — never a plaintext value.

# Secrets are addressed by a keyed name hash —
# even the name never travels in plaintext.
curl https://api.opaquevault.com/v1/apps/myapp/secrets/by-hmac/$NAME_HMAC \
  -H "Authorization: Bearer $OV_API_KEY"

# Response — every field is ciphertext or a nonce:
{
  "id": "6f2c…",
  "encrypted_dek": "xY8zQ1…",
  "dek_nonce": "pL5mN6…",
  "ciphertext": "7x9mK2…",
  "ct_nonce": "aB3cD4…",
  "encrypted_name": "rT4vW8…",
  "name_nonce": "kJ2hG9…",
  "name_hmac": "$NAME_HMAC",
  "algorithm": "AES-256-GCM",
  "version": 3,
  "dek_alg": 2
}

No decrypt endpoint exists. The server cannot return a plaintext value — ever.

02

In transit

All traffic between ov mcp serve and api.opaquevault.com uses a post-quantum hybrid KEM — ML-KEM-768 + X25519. If either primitive is broken, the other protects you.

// Verify it yourself

Inspect the TLS handshake. The cipher suite includes ML-KEM-768 alongside X25519.

openssl s_client \
  -connect api.opaquevault.com:443 \
  -groups X25519MLKEM768 2>&1 \
  | grep "Server Temp Key"

# Server Temp Key: X25519MLKEM768, 1216 bits

NIST FIPS 203 (ML-KEM-768), negotiated as the X25519MLKEM768 hybrid group at TLS 1.3. Transport only — data at rest is protected by the AES-256-GCM envelope.

// Defense in depth

Subprocess output doesn't
come back at all.

vault_run injects secrets into a subprocess, and that subprocess prints whatever it wants. So OpaqueVault doesn't return its output. The MCP response carries an exit code and a redaction marker — stdout and stderr are structurally omitted, never read into the payload. You read them on your own terminal, where the model isn't looking.

Behind that sits the interceptor, a backstop over every result the MCP toolsdo return. It runs inside ov mcp serve on the same detection engine as ov scan — AWS keys, GitHub tokens, Stripe keys, private keys, JWTs, connection strings, high-entropy blobs. In the default block mode a match drops the whole result and Claude receives an error instead.

What it isn't: the interceptor never sees your prompts — text you type or paste into Claude Code goes straight to the model without passing through ov. And a subprocess you've granted secrets to can always encode what it sends. This is a hygiene layer, not a boundary.

Read the interceptor docs →
claude code session
Claudevault_run(["./deploy.sh"], secrets: ["AWS_ACCESS_KEY_ID"])
# deploy.sh echoes the injected key into its own logs.
{ "exit_code": 0, "redacted": true,
    "redacted_fields": ["stdout", "stderr"] }
# Not filtered — never read into the response at all.
// The cryptographic stack

Every primitive.
Justified.

No black boxes. Every algorithm choice has a reason.

Primitive
Used for
Why
Argon2idtime=1, mem=64MB
Master password → KEK derivation
Memory-hard. Resistant to GPU and ASIC brute-force. PHC winner. The id variant combines side-channel resistance with GPU resistance.
AES-256-GCMrandom nonce per op
DEK encryption (KEK wraps DEK) + secret encryption (DEK wraps plaintext)
NIST standard. Authenticated encryption — integrity guaranteed. 256-bit keys. Nonces from crypto/rand, never reused.
ML-KEM-768NIST FIPS 203
Transport key encapsulation (post-quantum half of hybrid)
Lattice-based KEM. Resistant to quantum attacks. NIST security level III (~AES-192). Part of the mandatory hybrid — no fallback.
X25519Curve25519
Transport key exchange (classical half of hybrid)
Fast, side-channel resistant, widely audited elliptic curve DH. Paired with ML-KEM-768 — if quantum computers break ML-KEM, X25519 still holds classically.
HMAC-SHA256
Audit log secret references
Secret IDs in logs are hashed with a server-side key. The log proves access without revealing which secret was accessed to someone without the HMAC key.
Argon2id
API key hashing
Memory-hard hash for storing API key fingerprints. The plaintext key is shown once at creation and never stored — only the Argon2id hash and its salt live in the database.
// Multi-app namespacing — zero-knowledge unchanged

Apps and environments
are metadata only.

OpaqueVault scopes secrets by app / environment / name — somy-saas/production/DATABASE_URL and side-project/dev/DATABASE_URLcan coexist without collision.

App and environment names are metadata stored alongside the encrypted blob. They are not key material and play no role in encryption or key derivation. The zero-knowledge guarantee is identical whether you have one app or twenty: the server stores (ciphertext, nonce, encrypted_DEK, DEK_nonce) — useless without the user's master password.

Layer
Stored as
Visible to server?
app name
Plaintext metadata
Yes — contains no secret material
environment name
Plaintext metadata
Yes — contains no secret material
secret name
AES-256-GCM ciphertext + keyed hash for lookups
No — the server sees only the hash and ciphertext
secret value
AES-256-GCM ciphertext
Never
// Building trust over time

The audit roadmap.

Architectural proofs get you started. Third-party validation is how you scale trust.

Live at launch

API schema published

The full API response schema is public. Anyone can call the API and inspect the encrypted blob format. The absence of a decrypt endpoint is verifiable.

Live at launch

MCP wire traces published

Real Claude Code session traces showing the exact MCP JSON — tool call in, exit code out, no secret value anywhere in the wire format.

Live at launch

TLS cipher suite published

The exact cipher suite used on api.opaquevault.com is documented and verifiable with standard TLS inspection tools.

Q3 2026

Third-party security audit

Independent review of the cryptographic implementation, key derivation, and zero-knowledge architecture by a named security firm. Full report published.

Q4 2026

Bug bounty program

Invite the security research community to find vulnerabilities. Rewards for valid findings. Responsible disclosure policy published.

2027

SOC 2 Type II

Process-level assurance for enterprise buyers. Controls covering security, availability, and confidentiality. Report available to enterprise customers under NDA.

// Responsible disclosure

Found a vulnerability?

Email [email protected]. We'll respond within 48 hours. Please give us reasonable time to fix before public disclosure. We don't pursue legal action against good-faith researchers.

PGP key for encrypted reports
Fingerprint: coming soon — published before launch
// FAQ

Security, answered.

Can OpaqueVault's servers decrypt my secrets?

No. The server stores only your encrypted secret values plus opaque metadata — app and environment labels and timestamps. Secret names are themselves encrypted, with a keyed hash used for lookups. Your Key Encryption Key is derived from your master password with Argon2id and never leaves your machine. There is no decrypt endpoint and no key escrow, so there is no path by which OpaqueVault could produce your plaintext — even under subpoena.

What encryption does OpaqueVault use?

Each secret value is sealed with AES-256-GCM under a per-secret Data Encryption Key (DEK); the DEK is wrapped by a Key Encryption Key (KEK) derived from your master password with Argon2id. Transport uses an ML-KEM-768 + X25519 hybrid, so a session stays confidential even against a future quantum computer.

Are the Argon2id parameters chosen by the server?

No — they are hardcoded in the client. This matters: a secrets service that lets the server pick key-derivation parameters could serve weak ones and make your KEK easier to crack. Because OpaqueVault fixes the parameters client-side, a compromised or malicious server cannot weaken your key derivation.

How does OpaqueVault keep secrets away from an AI agent?

There is no tool that returns a secret value to the model — no get_secret. The agent calls vault_run, which injects secrets as environment variables into the subprocess it launches and returns only structured metadata: the exit code and which secrets were injected. Subprocess stdout and stderr are not returned to the model at all — they go to your terminal or the agent log, so output cannot carry a value back into the model context. An honest boundary: a subprocess you deliberately hand a secret to can still use it — the guarantee is that values never enter the model context, chat history, logs, or .env files on normal or accidental paths.

Is OpaqueVault quantum-safe?

Transport uses an ML-KEM-768 + X25519 hybrid, which resists "harvest-now, decrypt-later" attacks — where an adversary records encrypted traffic today to break it with a future quantum computer. Secrets at rest are sealed with AES-256-GCM.

What can OpaqueVault see if it is compelled or breached?

Encrypted secret values and opaque metadata — app and environment labels, timestamps, and keyed name hashes; secret names themselves are stored encrypted. Never a key and never a way to decrypt the values. There is no server-side key material that could turn ciphertext back into plaintext, so a breach or legal demand cannot produce your secrets.

Zero-knowledge.
Provably.

Start free. No credit card required.
Verify every guarantee yourself before you commit.