The live security architecture page told security reviewers that the client
key is transmitted to CipherStash:
"The SDK sends a key derivation request to ZeroKMS with the client key
component."
"ZeroKMS combines the authority key and client key to produce a key seed."
That inverts the property the architecture exists to provide. Corrected per
product review:
- The application requests a seed by sending a key ID. The request carries no
key material. The ID is what gives each data key a unique identity, so the
same value can be decrypted later by asking for the same ID.
- ZeroKMS applies proxy symmetric re-encryption to the authority key alone and
returns the key seed. It never receives the client key.
- The application processes the seed with the client key, then an HMAC-based
KDF expands the result into a per-value data key. Only the seed crosses the
boundary, and it crosses inward.
Two further claims on the same page were wrong:
- "No caching needed" / data keys "never cached". No *data key* is ever cached,
but Proxy caches keyset-scoped ciphers (cipher_cache_size,
cipher_cache_ttl_seconds). The page now states both.
- kms/index.mdx: "Root keys are stored in AWS KMS. ZeroKMS handles key
derivation and wrapping." AWS KMS protects the authority key at rest; no
per-value data key is wrapped or stored.
- kms/keysets.mdx: keysets scope the authority key, not a per-keyset root key
from which ZeroKMS derives data keys.
Standardises on AES-256-GCM-SIV across the corpus (was split 6/3 with plain
AES-256-GCM, including two compliance pages).
Brings #63 into v2. Merged cleanly, no conflicts.
Why
#63 corrected the live security architecture page on main, which told vendor security reviewers that the client key is transmitted to CipherStash. v2's copy of content/stack still says that. Two consequences:
What comes across
The seven files from #63: reference/security-architecture.mdx (key derivation, trust model, both data-flow paths, the caching section), cipherstash/kms/index.mdx, cipherstash/kms/keysets.mdx, plus AES naming in proxy/getting-started.mdx, deploy/troubleshooting.mdx, reference/comparisons/fhe.mdx, reference/use-cases/compliance.mdx.
Checks
This is the second sync in one day
#60 was the first, for the identity-API fixes. Both were reactive, and both existed because a fix landed on main while v2 ran ahead of it.
IA.md called this on day one: "Decide day 1: soft freeze on main docs changes for the week vs daily rebase of v2." That decision was never made. The failure mode is silent, because a merge that cleanly reverts a fix produces no conflict and no test failure. The validate-content guard (#61) catches the deprecated-API subset, but nothing catches a reverted prose correction.
Worth picking one before the launch merge: freeze main, or sync on a schedule.