Security
This page states what the system guarantees and what it does not. The second part matters more.
We are not zero-knowledge, and will not claim to be
At rest there is only ciphertext: values are encrypted under an environment key, and that key under a root key kept outside the database. A stolen dump without the root key is worthless.
But the running server sees values when it reveals them in the dashboard and when it writes them. The machine path, by contrast, is honestly client-side: the SDK receives ciphertext plus a key wrapped for its identity and decrypts locally.
Nothing lasts forever
A client secret can be revoked, an access token lives for minutes, an enrollment token for minutes and exactly one use. The root key rotates too: re-encryption touches environment keys rather than values, so it costs about as much as you have environments.
A repeat is a signal, not an error
Trading a one-time enrollment token twice, or presenting a rotated refresh token again, means two parties hold the secret. The system does not merely refuse: it kills the sessions and raises an event that reaches the administrators.
Perimeter
- rate limiting on sign-in and token exchange — per address and per subject;
- SSRF checks on webhook targets, twice: when saved and before every delivery;
- request and value size ceilings, in the application and at the reverse proxy;
- the browser refresh token in an httpOnly cookie, the access token in memory only;
- CSP, HSTS and frame denial on static delivery.
FAQ
- Is this zero-knowledge?
- No. At rest there is only ciphertext and a stolen database without the root key reveals nothing, but the running server does see values when revealing them in the dashboard. The machine path is fully client-side.
- What if the service is unavailable?
- The SDK keeps values in process memory and survives an outage until the next restart: your services do not go down with us. The exit is always open — dumping an environment to a plain .env is one CLI command.
- What stops you reading our secrets?
- Technically nothing: the encryption key is held by us, and in that we are no different from any managed store. What differs is what you can see: every read lands in a separate hash-chained audit stream, and values marked restricted are never shown in the interface at all — only services fetch them, under their own identity.