Skip to content

Security model (technical)

This page explains how the encryption works and what it does and does not protect, for a technical reader. The plain-language version is the Security model page. The exact envelope, key derivation parameters and DDL live in the backend architecture doc, which is their home; this page does not repeat values.

The goal is that the server can store and relay everything without being able to read any of it.

The password yields two keys. The auth key only signs in; the KEK unwraps the UMK, which wraps each item's content key.
  • The account password is stretched with Argon2id on the device, salted from the account email, and split with HKDF into two independent keys. The auth key is the only credential Supabase Auth receives. The key-encryption key never leaves the device. The password itself is not sent, and the auth key reveals nothing about the other key.
  • The key-encryption key unwraps the User Master Key (UMK), a random key held only in memory, zeroized on drop, and never written to disk or logs.
  • The server keeps several wrapped copies of the UMK, and none of them opens without a secret the server lacks: one under the password’s key-encryption key, one per device under that device’s X25519 key, and optionally one under a key derived from the recovery code. The per-device copy is what lets a device that has signed in before open it after a restart, or after a password reset, without the password.
  • Every clipboard entry and note gets its own random content key. The item is encrypted with AES-256-GCM under it, and the content key is wrapped under the UMK and, for shared items, under each target space key.
  • Devices and space members exchange keys with X25519, so a wrapped key is usable only by its recipient. Device private keys live in the operating system’s credential store: Windows Credential Manager, GNOME Keyring or KWallet.
Every wrapped copy the server holds needs a secret it does not have. Any one secret yields the same UMK.
  • Nothing on the server opens the data. Supabase checks the auth key, but that key unwraps nothing. Guessing it costs a full Argon2id run per attempt, and a correct guess only signs in. Resetting the password server-side cannot produce plaintext.
  • Ciphertext is bound to its item. Each item’s identity is additional authenticated data, so ciphertext moved onto another item fails to decrypt.
  • Sharing never re-encrypts. Adding a space to an item wraps its content key for that space; the ciphertext is untouched. This is why sharing to one more space is cheap and why content is keyed per item rather than under the master key.
  • Spaces keep a keyring. Keys are held newest first. Removing a member makes a new key for everyone left, and old keys stay so earlier items remain readable.
  • Space keys can be checked. An owner can publish a fingerprint of the current space key. When one is published, a member’s app refuses a key that does not match it.
The guarantee holds while the server relays keys as sent. A published fingerprint catches a swapped space key; device keys have no such check.
  • The server is trusted not to tamper. Key exchange uses public keys the server returns, and device keys are not pinned, so an actively malicious server could hand out a key it controls. The space-key fingerprint narrows this for spaces whose owner published one; it does not cover device keys. The guarantee is against a passive server that stores and relays but does not substitute keys.
  • Metadata is visible. The server sees each item’s type, size, timestamps, pinned flag and spaces, plus space names and membership. The full list is on the Security model page.
  • A device is as safe as its system account. Anyone who can use the credential store of a signed-in device can reach its device key, and through the per-device copy, the UMK.
  • Local files are plain. History and notes are stored unencrypted on the device; encryption covers what leaves it.
  • Losing every secret loses the data. Without the password, the recovery code, and any device that was signed in, the UMK cannot be recovered by anyone, including the operator. That is the price of the server holding no usable key.