Security model
seekrit's guarantee is simple: the server never has the information needed to read your secrets. This page states that precisely.
What the server stores
- Secret ciphertext (AES-256-GCM blobs).
- Environment DEKs, but only wrapped to principals' public keys — never in the clear.
- Users' public keys, and their private keys only in passphrase-encrypted form.
- For service tokens: a SHA-256 hash of the token and the token's public key.
- Metadata: org/app/environment/secret names, versions, timestamps, roles, and the audit log.
What the server never sees
- Plaintext secret values.
- Any DEK in the clear.
- Any user's private key in the clear.
- Any passphrase.
- The full service token string (only its hash).
Threat model
A full database compromise yields ciphertext and metadata. An attacker learns that
STRIPE_KEY exists in acme/storefront/production and when it changed, but not its value. To
decrypt, they would additionally need a principal's private key, which the database does not
contain.
A compromised or malicious server can deny service, tamper with metadata, or serve altered ciphertext — but AES-GCM authentication means tampered ciphertext fails to decrypt rather than producing wrong plaintext silently. It still cannot read secret values, because it never holds the keys.
A leaked passphrase exposes that user's private key (and therefore every environment granted to them). Treat passphrases like the master credential they are.
A leaked service token grants whatever environments were wrapped to it. Revoke it; rotate the affected environment keys.
Names are metadata, not secrets. Don't encode sensitive information in org, application, environment, or secret names — only in secret values.
Audit trail
Every read, write, grant, revocation, and token action is recorded in an append-only audit log, attributed to the acting user or service token, with contextual metadata (never secret material). The API exposes no update or delete path for audit entries. This gives you an after-the-fact record of who touched what, even though the server can't read the secrets themselves.
Transport and authentication
- All API traffic is authenticated: a Stytch session JWT (verified locally against Stytch's JWKS), a service token, or a local dev header.
- Session JWTs are validated for issuer, audience, and expiry.
- Service tokens are matched by hash and checked for revocation and expiry on every request.
Responsible disclosure
seekrit is early-stage software. If you find a vulnerability, please report it privately through the repository's security policy rather than opening a public issue.