# Threat Model This document describes what Shade protects against and what it doesn't. Read this before deploying Shade in any context where the answers matter. ## Assets The thing we're protecting: - **Message plaintext** — the actual content of encrypted messages between peers - **Identity private keys** — long-term Ed25519 signing key + X25519 DH key - **Session state** — Double Ratchet root keys, chain keys, DH keypairs ## Adversaries we consider ### 1. Network attacker (active) Can intercept, modify, drop, replay, and inject network traffic between clients and the prekey server, and between two clients. **Mitigations:** - All identity-key writes to the prekey server are signed (Ed25519). Tampering is detected. - Signed requests have a 5-minute replay window. - The Double Ratchet binds message headers to ciphertext via AES-GCM AAD, so header tampering breaks decryption. - Forward secrecy: even if an attacker captures all traffic, compromising a key later doesn't help them read past messages. **NOT mitigated:** - Initial session establishment can be MITM'd if users don't verify identity fingerprints. The prekey server could distribute a fake bundle on first contact. Always compare safety numbers out-of-band for high-stakes communications. ### 2. Malicious or compromised prekey server The server holds identity public keys and prekey bundles. It can serve them to anyone. **Mitigations:** - The server only stores PUBLIC keys, never private ones. - Write operations are signed with the identity private key, so the server can't forge new identities or replenishments without the user's key. - Bundle fetches are unauthenticated, so a malicious server can serve fake bundles. Detection requires out-of-band fingerprint comparison. **NOT mitigated:** - A malicious server can substitute one user's prekey bundle with the server operator's own keys, enabling MITM at session establishment. Users must verify safety numbers to detect this. ### 3. Compromised endpoint (post-compromise) Attacker briefly gains code execution or filesystem access on a user's device, exfiltrates session state, then loses access. **Mitigations:** - Forward secrecy: messages sent BEFORE the compromise cannot be decrypted with the leaked state. Old chain keys are zeroed after use. - Post-compromise security: as soon as a peer initiates a new DH ratchet step, the leaked state becomes useless for new messages. - Memory zeroization: message keys and chain keys are wiped from JS memory after use (best-effort — V8 may retain copies). **NOT mitigated:** - An ongoing endpoint compromise can read messages in real time and exfiltrate identity private keys. - Attackers with persistent access can intercept new identity rotations. ### 4. Compromised device storage Attacker gains access to the persistent storage (e.g., steals the SQLite file or dumps the PostgreSQL table). **Mitigations:** - Stored data includes private keys but is unencrypted at rest. Shade does NOT encrypt the storage layer — it assumes the database is in a trusted environment. **NOT mitigated:** - Filesystem-level encryption (LUKS, FileVault) is the user's responsibility. - Database TLS in transit is the user's responsibility. ### 5. Side-channel attacks (timing) Attacker measures timing of identity verification operations to recover key bits. **Mitigations:** - All comparisons of secret material use constant-time XOR-accumulator comparison (`constantTimeEqual`). - AES-GCM and the underlying primitives are constant-time as implemented by SubtleCrypto and @noble/curves. **NOT mitigated:** - JavaScript JIT compilation can introduce timing variability that's hard to control. - We don't claim resistance to power-analysis or fault-injection attacks (out of scope for a JS library). ### 6. Denial of service Attacker floods the prekey server to exhaust resources or one-time prekeys. **Mitigations:** - Per-IP rate limiting on registration and bundle fetches. - Per-identity rate limiting on replenish and delete. - 64KB body size limit on POST endpoints. - Address validation rejects path traversal and malformed inputs. **NOT mitigated:** - Application-level DDoS at the network layer is your hosting platform's responsibility. ## Assumptions 1. **The user has a secure way to bootstrap trust.** Either: - Trust on first use (TOFU) — accept the first identity key seen for a peer - Out-of-band verification — compare safety numbers in person/video before trusting 2. **Cryptographic primitives are sound.** We trust X25519, Ed25519, AES-256-GCM, HKDF-SHA256, HMAC-SHA256. 3. **The runtime is honest.** A malicious Bun/Node/browser runtime can defeat any JS library. 4. **The prekey server is reachable.** If it's offline, new sessions can't be established (but existing sessions continue working). ## Residual risks | Risk | Severity | Mitigation | |------|----------|------------| | MITM at first session establishment | High | Compare safety numbers out-of-band | | Identity private key theft from device | Critical | Filesystem encryption, secure enclave (future) | | Prekey server operator runs a "key oracle" attack | Medium | Distributed/federated prekey servers (future) | | Side-channel via JIT timing variability | Low | Constant-time primitives reduce but don't eliminate | | Metadata visibility to prekey server | Low | Acceptable for most use cases; mix networks for stronger metadata protection |