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.
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.
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.
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.
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.
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 bitsNIST 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.
When Claude Code calls vault_run, the raw MCP response carries only structured metadata — the exit code and which secrets were injected. Subprocess stdout and stderr are structurally omitted from the response, so output can't smuggle a value back to the model. Here's the actual wire format.
Enable MCP debug logging in Claude Code and capture this yourself.
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.
No black boxes. Every algorithm choice has a reason.
Argon2idtime=1, mem=64MBid variant combines side-channel resistance with GPU resistance.AES-256-GCMrandom nonce per opcrypto/rand, never reused.ML-KEM-768NIST FIPS 203X25519Curve25519HMAC-SHA256Argon2idOpaqueVault 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.
app nameenvironment namesecret namesecret valueArchitectural proofs get you started. Third-party validation is how you scale trust.
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.
Real Claude Code session traces showing the exact MCP JSON — tool call in, exit code out, no secret value anywhere in the wire format.
The exact cipher suite used on api.opaquevault.com is documented and verifiable with standard TLS inspection tools.
Independent review of the cryptographic implementation, key derivation, and zero-knowledge architecture by a named security firm. Full report published.
Invite the security research community to find vulnerabilities. Rewards for valid findings. Responsible disclosure policy published.
Process-level assurance for enterprise buyers. Controls covering security, availability, and confidentiality. Report available to enterprise customers under NDA.
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.
Fingerprint: coming soon — published before launchNo. 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.
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.
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.
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.
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.
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.
Start free. No credit card required.
Verify every guarantee yourself before you commit.