Security

We can't read your secrets.

Every secret is encrypted on your device before it reaches our servers. The decryption key never leaves you.

Zero-knowledge encryption

  • XChaCha20-Poly1305 on every secret value, with the variable ID bound as associated data. X25519 sealed boxes wrap each org key to each member.
  • Argon2id derives your key from your vault passphrase. libsodium does all the math; no homegrown crypto.
  • We store ciphertext, sealed boxes, public keys, and your encrypted private key. We do not store your passphrase or any plaintext secret.

Recovery without a back door

  • At signup we show a one-time recovery code. Save it offline; it wraps a second copy of your private key.
  • Forget your passphrase? The recovery code lets you back in and reset it.
  • Lose both? Your data is permanently unreadable. We have no override.

Transport and hosting

  • TLS 1.2+ on every endpoint, certificates rotated automatically. The CLI verifies certs and refuses plaintext fallback.
  • Managed Postgres with provider-managed encrypted backups. Two app slots behind Caddy for zero-downtime deploys; root login disabled.
  • Even if every server-side secret were exposed, no organization data is decryptable.

Honest note: HSTS preload and a strict Content Security Policy are queued for the next hardening pass.

Access and accountability

  • Better Auth with email OTP, password, and GitHub OAuth. HTTP-only session cookies. Role-based access: owner, admin, member.
  • Each CLI/API token carries its own X25519 keypair. We store only a SHA-256 hash plus the sealed key; the token string is shown once.
  • Project, environment, variable, and token events are recorded with actor, action, and timestamp. Our logger redacts secrets everywhere.

Honest note: TOTP 2FA, login events, and client IP in the audit log are not yet shipped.

The trade-offs

What zero-knowledge costs you.

  • Forget your passphrase AND lose your recovery code and access is gone. We cannot reset it.
  • New members cannot read existing secrets until an existing member is online to seal the org key for them.
  • No server-side search, no webhooks with values, no email previews. Anything that would need plaintext server-side does not exist.
  • Removing a member immediately revokes their sessions, API tokens, and wrapped copy of the org key. Re-encryption of existing variables happens the next time an admin loads the org page. Anything they already pulled to disk is already plaintext on their machine; we cannot un-cache it.

Roadmap

What we have not built yet.

If any are blockers, tell us at jordan@jtlee.dev.

  • TOTP / authenticator 2FAAuthenticator apps alongside email OTP for stronger step-up.
  • Scoped tokensCI tokens limited to a single project or environment.
  • Rate limitingThrottle sign-in, OTP, and token endpoints against brute force.
  • Login events in audit logCapture sign-in, OAuth link, and client IP for end-to-end review.

Responsible disclosure

Found something? We want to know.

Email jordan@jtlee.dev with a description and reproduction steps.

For product questions unrelated to security, see the docs.