// docs
threat model
CozyLabs’s threat model is maintained as a living map from each security objective to the tests that prove it — a meta-test parses the map and fails CI if an objective loses its test. This page is the prose version.
adversaries considered
The relay itself. The defining choice: the server is in the threat model. A compromised or malicious relay can observe routing metadata, reorder or withhold events, and refuse service. It cannot read content (SO-1), forge attribution (SO-3 — clients verify signatures independently), steal keys it never had (SO-2), or grant itself management powers (SO-5 — proofs are signed by human keys).
A database thief. Gets sealed keystores, ciphertext events, wrapped CKs, artifact refs. Everything useful is sealed to keys that were never in the database.
A login-password cracker. Gets a session: metadata-visible, content-blind, mutation-incapable. The sealed keystore can be fetched (that’s the new-device restore path, which by construction can’t demand a management proof) — but it’s sealed under the encryption passphrase’s Argon2id-MODERATE derivation. This is why a passphrase strength floor is treated as load-bearing, not cosmetic.
A fellow member. Holds the CK, reads channel content — that’s what membership means. But direct messages are sealed per-pair to the two participants’ X25519 keys, not under the CK: a third member’s decrypt fails at the crypto layer, asserted by test (ADR-0023).
A compromised agent. Has its own capabilities and nothing else. No management surface (SO-5), no credentials — the broker resolves secrets on its behalf and scrubs every credential field value from results and errors (SO-9). Revocation rotates the CK away from it (SO-7).
An internet attacker on a public deployment. Faces Cloudflare Access (identity or service
token) before any CozyLabs surface, a single public origin, and a data plane (Postgres, OpenBao)
with no published ports at all under the tunnel shape (SO-6, ADR-0014/0015). Per-account
lockouts throttle brute force; rotating JWT_SIGNING_KEY is the break-glass that kills every
session and agent token at once.
the supply chain
Release artifacts are Ed25519-signed into a RELEASE.json manifest with a verify path, built
from a committed, frozen lockfile (SO-8).
accepted residual risk
Named, documented, and deliberate:
- Routing-metadata leakage. The relay learns
{collabId, actorId, seq, kind, ts, opaque refs}per event — the minimum needed to order and fan out. Padding and metadata-hiding are deferred. A security test asserts this is the only plaintext that crosses. - Past content after revocation. Crypto cannot retroactively revoke delivered plaintext; SO-7 protects future content only.
- Key loss is data loss. No passphrase + no recovery code = unrecoverable, because operator-side recovery would mean the operator holds your keys. The product refuses.
- Beta is single-relay. Live fan-out is in-process (ADR-0016); availability, not confidentiality, is the cost of a relay outage.