Security

Zero-knowledge by construction. AES-256-GCM in your browser, a key derived from your passphrase through 600,000 rounds of PBKDF2 — the server holds ciphertext it cannot open.

Client-side encryption

Your passphrase derives a 256-bit key with PBKDF2 (600,000 iterations, SHA-256) — well above OWASP 2024 guidance. Provider keys and message history are sealed with AES-256-GCM before they touch the network.

Zero-knowledge by design

The server only ever sees ciphertext. We cannot read your keys, your chats, or your passphrase, and neither can anyone who compromises the database.

No key escrow

There is no recovery backdoor. If you lose your passphrase, your data is unrecoverable. That is the point: nobody but you holds the key.

Per-record IVs

Every encrypted record gets a fresh 96-bit initialization vector, so identical plaintext never produces identical ciphertext.

Independently auditable

The crypto layer is documented end to end with reproducible test vectors. Independent audits are scheduled before general availability.

Rotatable keys

Rotate a provider key or re-key your vault with a new passphrase at any time. Old ciphertext is re-sealed transparently.

The encryption flow

Four steps, all on your device

Passphrase → PBKDF2 600,000 iterations → AES-256-GCM → sealed sync.

  1. 01

    Derive

    PBKDF2 · 600,000 iterations · SHA-256

    Your passphrase + a unique salt run through PBKDF2 to produce a vault key. The passphrase is never transmitted or stored.

  2. 02

    Encrypt

    AES-256-GCM · WebCrypto

    Provider API keys and messages are encrypted with AES-256-GCM using the vault key, entirely inside your browser.

  3. 03

    Store

    Ciphertext + IV only

    Only the ciphertext + IV are sent to the database. The server has no way to decrypt them.

  4. 04

    Decrypt

    Re-derived locally, in-memory

    On next login, you re-enter your passphrase, the vault key is re-derived locally, and your data is decrypted in-memory.

Strict CSP

frame-ancestors none, nosniff, COOP same-origin, X-Frame DENY.

HSTS preload

HTTPS only, max-age 2 years, includeSubDomains.

Zero-knowledge

Server stores ciphertext only. No escrow, no backdoor.

GDPR-friendly

Opt-in analytics only. Export and delete everything from Settings.

What we store

  • Encrypted ciphertext of your provider keys
  • Encrypted ciphertext of your conversations
  • A unique per-account salt and per-record IVs
  • Your email address for magic-link sign-in

What we never store

  • Your passphrase or any derivative we could reverse
  • Plaintext provider API keys
  • Plaintext message content
  • Telemetry, trackers, or analytics on your prompts
Our guarantee to you

If our servers are ever breached, your keys and chats stay yours.

Server compromise does not equal data compromise. Because every sensitive byte is sealed in your browser with a key derived from a passphrase only you know, an attacker who exfiltrates our database walks away with ciphertext and salts — meaningless without your passphrase.

Transport

HTTPS only, HSTS preload (max-age 2 years, includeSubDomains). TLS terminated at the edge.

At rest

Supabase Postgres with row-level security; only your authenticated session can read your rows.

In your browser

WebCrypto AES-256-GCM + PBKDF2 600k. No third-party crypto libraries; native primitives only.

Provider calls

Your decrypted key goes directly to the provider over TLS. We do not log prompts or responses.

Auth hardening

Progressive lockout on failed sign-in (5s → 30s → 2m). Caps-Lock warning. Cookies SameSite=Lax + Secure.

Content safety

Strict CSP with frame-ancestors none, X-Content-Type-Options nosniff, COOP same-origin, X-Frame DENY.

No tracking

Vercel anonymous analytics only, and only after you opt in. No marketing cookies, ever.

Responsible disclosure

/.well-known/security.txt sets the contact and the 72-hour acknowledgement window.

Found something we missed? security@sarmalinux.com. We acknowledge within 72 hours and credit reporters in the changelog.