This page documents what VaultProof stores, what it reconstructs during proxy calls, and what it does not return to clients.
The CLI or dashboard splits your key before upload. The upload sends serialized shares over TLS; the worker stores both shares as separate authenticated ciphertexts. The plaintext provider key is not stored in the database.
// Step 1 — split before upload: apiKey => share1 + share2 // Split-key encryption, client-side only // Step 2 — upload serialized shares over TLS: POST /api/v1/init/projects/:projectId/keys { "provider": "openai", "share1": "AQ...", "share2": "Ag..." } // Step 3 — stored server-side as ciphertext: { "share1_encrypted": "base64(aes-gcm-ciphertext)", "share2_b64": "enc2:base64(aes-gcm-ciphertext)" } // What is not stored: // The full plaintext provider API key.
How to verify: Inspect the key upload request and the worker code. The full provider key should not appear in the request body or storage row. New Share 2 rows are prefixed with enc2:, which means encrypted-at-rest storage; older legacy rows remain readable for migration.
Share 1 and Share 2 are encrypted with AES-256-GCM using HKDF-derived keys and separate purposes. This protects against database-only exposure. A compromise of both the database and worker encryption environment is a higher-impact service compromise and should trigger provider-key rotation.
// Where each piece lives: 1. Database => share1_encrypted + enc2:share2_ciphertext 2. Worker secret => VAULT_ENCRYPTION_KEY 3. Proxy controls => project id, origin policy, route policy, rate limit // A database dump alone should not reveal provider keys. // A full service compromise is different and requires rotation.
How to verify: Review packages/init-worker/src/crypto/encryption.ts and fast-crypt.test.ts. The tests cover round trips, tamper detection, wrong-key failure, legacy Share 2 compatibility, and the new enc2: encrypted Share 2 wrapper.
During a proxy call, the key is reconstructed just long enough to make the upstream API request, then immediately zeroed from memory:
// What happens during a proxy call: Step 1 Authenticate project identifier and enforce origin/rate controls Step 2 Decrypt Share 1 from storage Step 3 Decrypt stored Share 2 Step 4 Reconstruct full API key from Share 1 + Share 2 Step 5 Make upstream API call (e.g., OpenAI /v1/chat/completions) Step 6 Response received Step 7 Key buffer zeroed. Overwritten with 0x00. Gone.
How to verify: Review packages/init-worker/src/routes/proxy.ts. The proxy fetches shares fresh for each call, reconstructs only for the upstream request, and zeroes the reconstructed byte buffer in a finally block.
Project identifiers are not provider keys, but they can authorize proxy calls. VaultProof enforces origin policy, route configuration, SSRF validation, and rate limits around those proxy calls.
// Project token in a provider-compatible header: Authorization: Bearer vp-proj-... // Controls before upstream dispatch: origin allowlist per-project rate limit registered provider slug validated upstream base URL safe forwarded headers only
How to verify: Review project-auth.ts, ssrf-guard.ts, and rate-limit.ts. Unknown projects, wrong slugs, failed origin checks, and rate-limit exhaustion fail before upstream dispatch.
Provider keys are used by proxy routes. The worker explicitly rejects raw retrieval endpoints that older SDK drafts referenced.
// Raw retrieval path: GET /api/v1/sdk/retrieve // Response: 410 Gone {"error":"Raw key retrieval is disabled..."}
How to verify: Review packages/init-worker/src/index.ts. Vault-only runtime secrets have a separate authenticated CLI injection path; normal provider keys are not returned to browser or SDK clients.
The hosted installer verifies SHA-256 values from the manifest before installing the CLI bundle and provider catalog. The installed CLI uses its bundled catalog by default so provider detection and routing rules do not silently change on every run.
// Default catalog behavior: bundled providers.json // pinned to installed CLI artifact // Explicit opt-in for live catalog: VAULTPROOF_ALLOW_REMOTE_PROVIDER_CATALOG=true vaultproof-init
How to verify: Review packages/init-cli/src/providers.ts, apps/site/install, and apps/site/downloads/vaultproof-init-manifest.json.
How to verify: Clone the repo and run the focused package tests. The security model should be judged against the source and tests for the current init/proxy implementation, not older SDK-route drafts.
VaultProof reduces persistent plaintext exposure and proxy abuse risk. A full service compromise is still serious and should trigger provider-key rotation.