privacy
Privacy Model
Formal description of Static's privacy guarantees, threat model, and known limitations.
Privacy Model
This document describes Static’s privacy guarantees, threat model, and known limitations. It is written for security researchers, privacy-conscious users, and anyone evaluating whether Static meets their threat model.
We aim to be brutally honest in this document. Privacy tools that overstate their guarantees erode user trust and create false confidence. We describe exactly what Static protects, what it does not protect, and where the boundaries are.
Scope and Disclaimers
Current status: Phase 0 (Proof of Concept). The properties described here represent design-level guarantees that are implemented in code but have not undergone formal security audit, penetration testing, or prolonged adversarial deployment. Consider this an alpha-quality privacy system.
- The privacy layer is custom code with no production precedent. It has not been battle-tested at scale.
- MLS implementation uses OpenMLS v0.8, a well-reviewed library, but our integration (StorageProvider, DeliveryService, key export) is custom and unaudited.
- Performance characteristics of privacy features (padding overhead, batch latency, cover traffic bandwidth) are based on controlled tests, not production workloads.
- This document will be updated as the system matures, as audits are completed, and as limitations are discovered.
Threat Model
Static’s privacy design considers six classes of adversaries, ordered roughly by increasing capability.
Adversary 1: Passive Network Observer
Capability: Can observe network traffic between the client and relays, or between relays and the supernode. Cannot modify traffic. Examples: ISP, coffee shop Wi-Fi operator, backbone network tap.
What they see:
- That the client is communicating with an Iroh relay (identifiable by QUIC protocol fingerprint and relay IP address).
- Volume and timing of encrypted traffic.
- The relay’s IP address (but not the supernode’s, if the relay and supernode are different hosts).
What Static protects:
- Message content (MLS encryption inside QUIC encryption — two layers).
- Message destinations (channel IDs are inside the QUIC stream, not visible to the network observer).
- Message sizes within a bucket (padding makes all messages in the same bucket identical in size).
What Static does NOT protect:
- The fact that the user is using Static (QUIC protocol fingerprint is identifiable, though not specific to Static).
- Timing patterns of communication (partially mitigated by batched delivery).
- Traffic volume over time (partially mitigated by cover traffic, if enabled).
Adversary 2: Active Network Attacker
Capability: Can modify, drop, replay, or inject network traffic. Examples: compromised router, state-level attacker performing active interception.
What Static protects:
- Message integrity (QUIC transport authentication + MLS message signatures).
- Message confidentiality (MLS encryption is not affected by transport-level attacks).
- Replay attacks (MLS epoch numbers and message counters prevent replay).
What Static does NOT protect:
- Availability. An active attacker can drop all traffic, causing a denial of service. Static has no defense against network-level DoS beyond reconnection attempts.
- Timing analysis. An active attacker who can selectively delay packets can perform more precise timing analysis than a passive observer.
Adversary 3: Malicious Supernode Operator
Capability: Full control over the supernode. Can read all data the supernode processes, modify supernode behavior, log all metadata. This is the most important adversary for Static’s threat model because supernodes are trusted infrastructure.
What the supernode can see:
- Which connections send messages (but not their IP addresses if relay-only mode is used).
- When messages are sent and received (timestamps).
- Which channels messages are routed to (channel IDs are needed for routing).
- Ciphertext sizes (mitigated by padding to fixed buckets).
- Connection patterns: who is online when, who subscribes to which channels.
- MLS Commits: the supernode orders these and can see which connection submits them.
What the supernode CANNOT see:
- Message plaintext (MLS-encrypted ciphertext only).
- Sender identity at the application layer (the connection identity is an ephemeral key, not the user’s Ed25519 key, though the supernode can correlate a session’s messages).
- Client IP addresses (when relay-only mode is enabled; the supernode sees relay IPs).
What the supernode CANNOT do:
- Decrypt messages (it does not have MLS group keys).
- Forge messages (recipients verify MLS signatures against known member credentials).
- Impersonate members (MLS credentials are bound to the member’s device key, verified client-side).
- Selectively withhold messages without detection (planned: message acknowledgment protocol will detect missing messages; not yet implemented in Phase 0).
What the supernode CAN do (attacks to be aware of):
- Selective denial of service: The supernode can refuse to relay messages from specific connections, effectively silencing a user without other members knowing.
- Ordering manipulation: The supernode orders MLS Commits. It could accept or reject Commits to manipulate group membership (e.g., refusing to process a Remove Commit for a specific member). Mitigated in future phases by multi-supernode consensus.
- Metadata correlation: By observing connection patterns and channel subscriptions over time, a persistent supernode could build profiles of which connections interact with which channels, even across ephemeral session rotations (if other correlation signals exist).
- Archive manipulation: The supernode stores encrypted message archives. It could delete archived messages, preventing offline members from catching up. Members would notice gaps in message history.
Adversary 4: Compromised Group Member
Capability: A legitimate member of an MLS group whose device is controlled by an adversary, or who is willingly acting maliciously.
What they can see:
- All message plaintext in channels they are a member of (they hold the MLS decryption keys).
- Identities of other group members (MLS credentials include public keys).
- Group membership changes (Commits are processed by all members).
What Static protects:
- Messages in channels they are NOT a member of (MLS groups are independent per channel).
- Past messages before they joined (MLS forward secrecy — they receive keys only from the epoch they joined).
- Future messages after they are removed (MLS post-compromise security — keys rotate on removal).
What Static does NOT protect:
- Messages sent while the adversary is a member. There is no defense against a legitimate group member reading messages they are authorized to read.
- Screenshots or plaintext export. Once a message is decrypted on a device, the user can copy, screenshot, or forward it. MLS does not provide deniability or prevent plaintext leakage.
Adversary 5: Device Compromise
Capability: Physical or remote access to a user’s device. Can read the local filesystem, extract keys from memory, and access the SQLCipher database.
What they can access:
- All decrypted messages in the local database (if they can derive or extract the SQLCipher key).
- The device’s private key (which allows decrypting future messages until the key is rotated).
- The MLS group state (which allows decrypting current-epoch messages in all groups the device is a member of).
- The recovery phrase (if the user stored it on the device, which they should not do).
What Static protects:
- Messages in the database are encrypted at rest with SQLCipher. The attacker needs the encryption key.
- Private keys are stored in the OS keychain where available, or in encrypted files with restricted permissions.
- After the compromised device key is rotated (via MLS Update Commit), future messages are secure (post-compromise security).
What Static does NOT protect:
- If the attacker has sufficient access to extract keys from the OS keychain or memory, all local data is exposed.
- Past messages stored in the local database are accessible once the SQLCipher key is obtained.
- If the master key is compromised (e.g., the recovery phrase was stored on the device), the entire identity is compromised.
Adversary 6: Global Passive Adversary
Capability: Can observe all network traffic globally. Can correlate traffic flows across all relays, supernodes, and clients.
This is the strongest adversary and the one Static is least effective against.
A global passive adversary can:
- Correlate traffic entering a relay with traffic exiting it (relay provides no mixing).
- Perform traffic analysis across the entire network to identify communication patterns.
- Observe all users’ connection timing to map social graphs.
Static’s relay routing provides protection against a localized passive observer (one who can see traffic at one point in the network), not against a global observer who can see traffic everywhere simultaneously.
Cover traffic and batched delivery raise the cost of traffic analysis but do not defeat a GPA. Defeating a GPA requires a mix network (like Tor or Nym), which Static does not implement due to the latency impact on real-time messaging.
Encryption Layers
Layer 1: Encryption at Rest (SQLCipher)
All local data is stored in a SQLCipher-encrypted SQLite database.
- Algorithm: AES-256-CBC with HMAC-SHA512 authentication (SQLCipher default).
- Key derivation: The encryption key is derived from the user’s identity key material. On platforms with OS keychain support, the key is stored in the keychain rather than derived on the fly.
- Scope: All messages, community metadata, channel data, settings, attachments, and search indexes are encrypted.
- Limitation: If the device is unlocked and the app is running, the database is open and decrypted in memory. SQLCipher protects data at rest (device powered off or app not running), not data in use.
Layer 2: Encryption in Transit (QUIC + MLS)
Messages are encrypted twice in transit:
-
MLS application-layer encryption: The message plaintext is encrypted with the channel’s MLS group key before leaving the client. This provides end-to-end encryption — only group members can decrypt.
-
QUIC transport-layer encryption: The MLS ciphertext is wrapped in QUIC’s TLS 1.3 transport encryption for the connection to the relay/supernode. This provides transport-level confidentiality and authentication.
The two layers serve different purposes:
- MLS encryption protects content from the supernode and relay operators.
- QUIC encryption protects the MLS ciphertext (including channel IDs and routing metadata) from network observers.
MLS ciphersuite: MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 (default). This provides 128-bit security with X25519 key exchange, AES-128-GCM authenticated encryption, SHA-256 hashing, and Ed25519 signatures.
Layer 3: Ephemeral Session Encryption
Each app session generates a fresh ephemeral X25519 key pair for the Iroh QUIC connection. This key pair:
- Is never reused across sessions.
- Is rotated periodically (default: every 4 hours).
- Provides separation between the user’s long-term identity and their network-layer identity.
- Means that even if a session key is compromised, it cannot be linked to the user’s permanent Ed25519 identity without additional correlation.
Metadata Protection
This section describes precisely what metadata is and is not protected. This is where most privacy systems are least transparent, so we aim for maximum clarity.
What IS Protected
| Metadata | Protection Mechanism | Strength |
|---|---|---|
| Client IP address (from supernode) | Iroh relay routing | Strong (supernode sees only relay IP) |
| Client IP address (from other clients) | Relay-only mode | Strong (no direct peer connections) |
| Message content | MLS E2EE | Strong (cryptographic) |
| Message sender identity (network layer) | Ephemeral session keys | Moderate (prevents cross-session correlation at the network layer) |
| Message size | Fixed-size padding buckets | Moderate (reduces granularity; observer sees bucket size, not exact size) |
| Message timing | Batched delivery | Weak-to-moderate (adds latency jitter; does not prevent long-term timing analysis) |
| Activity patterns | Cover traffic (when enabled) | Weak (raises analysis cost; does not defeat a determined adversary) |
What is NOT Protected
| Metadata | Who can see it | Why it is exposed |
|---|---|---|
| Client IP address | Relay operator | Relays must know the client IP to forward packets. Mitigated by relay rotation. |
| Connection timing | Relay operator, network observer | Observable at the transport level. |
| Supernode address | Network observer | The relay endpoint is visible in network traffic. |
| Channel routing metadata | Supernode | The supernode needs channel IDs to route messages to subscribers. |
| Message timing (within a batch) | Supernode | The supernode sees when batches arrive and which messages they contain. |
| Community membership | Supernode | The supernode manages channel subscriptions and knows which connections are subscribed to which channels. |
| MLS group operations | Supernode | The supernode orders Commits and can see group membership changes. |
| Social graph (who talks to whom) | Supernode (over time) | By correlating channel subscriptions and message routing, the supernode can infer which users communicate. |
| Online/offline status | Supernode | The supernode knows which connections are active. |
Wire Traffic Analysis Resistance
Message Padding
All messages are padded to one of four fixed-size buckets before transmission:
| Bucket | Size (bytes) | Content after padding |
|---|---|---|
| 0 | 256 | Indistinguishable random |
| 1 | 1,024 | Indistinguishable random |
| 2 | 4,096 | Indistinguishable random |
| 3 | 16,384 | Indistinguishable random |
The wire format is:
[mask: 4 random bytes][masked_length: u32 LE XOR mask (4 bytes)][payload][random_padding]
The XOR masking ensures the header bytes are statistically indistinguishable from random data. The padding bytes are generated using a cryptographic random number generator (OsRng), making the entire padded message indistinguishable from random.
What this achieves: An observer cannot determine the exact size of the original message, only which bucket it falls into. A 10-byte message and a 200-byte message both appear as 256 bytes of random data.
What this does NOT achieve: An observer can still distinguish between bucket sizes. A 256-byte message is distinguishable from a 1,024-byte message. The four bucket sizes leak which size class a message belongs to.
Cover Traffic
When enabled (cover_traffic_enabled = true), the client generates dummy encrypted messages at regular intervals:
- Dummy messages are padded and encrypted identically to real messages.
- They are indistinguishable from real messages at the network layer.
- Default interval: approximately one message every 30 seconds.
- Bandwidth overhead: approximately 1 KB per 30 seconds per connection.
What this achieves: An observer cannot determine whether a given transmission is a real message or a dummy. This masks activity patterns — periods of silence become indistinguishable from periods of activity.
What this does NOT achieve:
- Cover traffic does not mask the total volume of communication over longer time windows. A statistical adversary who observes traffic for hours can estimate real message rates by subtracting the expected cover traffic rate.
- It is disabled by default because of bandwidth costs, especially on metered/mobile connections. Users who need this protection must explicitly enable it.
Batched Delivery
Messages are queued and delivered in periodic batches:
- Client batch interval: 1,000 ms (default, configurable).
- Supernode batch interval: 500 ms (default, configurable).
- Messages within a batch are shuffled before transmission.
What this achieves: Reduces the precision of timing correlation. An observer cannot determine the exact moment a user decided to send a message, only the batch window in which it was sent.
What this does NOT achieve: Does not prevent long-term timing analysis. Over many messages, statistical patterns still emerge. Batching adds latency (up to the batch interval) to all messages.
Relay Trust Model
Iroh relays are QUIC packet forwarders. They see:
- The client’s real IP address.
- The destination (supernode) IP address.
- Encrypted QUIC packets (they cannot read the content).
- Traffic volume and timing.
They do NOT see:
- Message content (MLS-encrypted inside QUIC).
- Channel IDs or routing metadata (inside the QUIC stream).
- The user’s identity (connection uses ephemeral keys).
Trust assumption: Relays are semi-trusted. They must be trusted not to log IP addresses or perform traffic analysis. Static mitigates this by:
- Using multiple relays (relay pool) so no single relay sees all traffic.
- Rotating relay selection periodically.
- Allowing community operators to run their own relays.
Non-collusion assumption: The privacy model assumes the relay operator and the supernode operator are not colluding. If they collude, they can link client IP addresses to community memberships (the relay knows the IP, the supernode knows the community). This is a fundamental limitation of relay-based (as opposed to mix-network-based) privacy.
Known Limitations
We list these explicitly because honesty about limitations is more valuable than vague privacy claims.
1. Device Compromise Defeats All Protections
If an adversary gains access to a user’s unlocked device (or extracts keys from a locked device), all local data is accessible. SQLCipher protects data at rest, but a sophisticated attacker who can extract the keychain or memory-resident keys can access everything.
Mitigation: Use device-level security (full-disk encryption, strong passcode, biometric lock). Static cannot compensate for a compromised device.
2. Screenshots and Plaintext Export
Once a message is decrypted and displayed, the user (or malware on their device) can screenshot, copy, or forward the plaintext. MLS does not provide deniability or prevent plaintext leakage after decryption.
Mitigation: None at the protocol level. This is a fundamental limitation of any messaging system that displays plaintext to users.
3. Global Passive Adversary Can Perform Traffic Analysis
Static’s relay routing defeats localized observers but not a global passive adversary who can monitor all network links simultaneously. Such an adversary can correlate traffic across relays to identify communication patterns.
Mitigation: Cover traffic and batching raise the cost of analysis but do not defeat it. True GPA resistance requires a mix network (Tor, Nym), which is incompatible with real-time messaging latency requirements.
4. Supernode Is a Single Point of Availability Failure
Each community currently relies on a single supernode. If the supernode goes offline, message delivery stops (though clients retain their local message history).
Mitigation: Multi-supernode architecture is planned for Phase 2, distributing trust and availability across multiple operators.
5. MLS Scaling Constraints
MLS group operations (Add, Remove, Update Commits) grow in cost with group size. Welcome messages grow linearly with the number of members. For groups over ~200 members, MLS operations become expensive and Welcome delivery requires chunking.
Mitigation: Chunked Welcome delivery is implemented. For very large communities (1000+ members), architectural changes (hierarchical groups, subgroup federation) may be needed.
6. Community-Level Metadata Leaks to Supernode
The supernode knows the full community membership (which connections subscribe to which channels), message timing, and channel routing. Over time, this reveals the social graph of the community.
Mitigation: Relay routing hides IP addresses. Ephemeral sessions limit cross-session identity correlation. But the supernode still sees the community-level interaction pattern within each session.
7. No Deniability
MLS messages are signed with the sender’s device key. A recipient can prove cryptographically that a specific device sent a specific message. There is no plausible deniability mechanism.
Mitigation: None currently. Deniable messaging protocols exist (OTR, Signal’s deniability properties) but are not part of the MLS specification.
8. Recovery Phrase Is a Single Point of Failure
The BIP-39 recovery phrase is the only backup of the master key. If the phrase is lost and all devices are inaccessible, the identity is permanently unrecoverable. If the phrase is stolen, the attacker can fully impersonate the user.
Mitigation: User education. Store the recovery phrase on paper in a secure offline location. Do not photograph it or store it digitally.
9. Cover Traffic on Metered Connections
Cover traffic generates approximately 1 KB every 30 seconds (~2.9 MB/day). On metered mobile connections, this bandwidth cost may be unacceptable. Cover traffic is disabled by default.
Mitigation: Cover traffic is opt-in. The client detects metered connections via platform APIs and warns the user before enabling.
Comparison to Other Systems
| Property | Static | Signal | Matrix (Element) | SimpleX |
|---|---|---|---|---|
| E2EE protocol | MLS (RFC 9420) | Signal Protocol (Double Ratchet) | Megolm + Olm (custom) | Double Ratchet variant |
| Identity model | Ed25519 key pair, no phone/email | Phone number required | Email or phone for registration | No identity required |
| Server trust model | Supernode sees metadata, not content | Signal server sees metadata, not content | Homeserver sees metadata, not content (with E2EE) | Relay sees metadata, not content |
| IP address protection | Relay routing (default on) | No (server sees client IP) | No (homeserver sees client IP) | Tor support (optional) |
| Forward secrecy | Yes (MLS epoch rotation) | Yes (ratchet per message) | Partial (Megolm ratchet, but not per-message) | Yes (per message) |
| Post-compromise security | Yes (MLS Update Commits) | Yes (new ratchet on compromise detection) | Partial (session rotation) | Yes |
| Group size efficiency | O(1) per message, O(n) for Add/Remove | O(n) per message (pairwise) | O(1) per message (Megolm broadcast) | Pairwise (no native groups) |
| Message padding | Yes (4 fixed buckets) | Partial (some padding in Signal Protocol) | No | Yes |
| Cover traffic | Optional (disabled by default) | No | No | No |
| Self-hostable | Yes (supernode) | No (centralized server) | Yes (homeserver) | Yes (relay) |
| Decentralized identity | Yes (no central registry) | No (phone number registry) | Partial (federated usernames) | Yes (no identity required) |
| Offline message delivery | Via supernode archive | Via server queue | Via homeserver | Via relay queue |
Key trade-offs vs Signal: Static provides IP address protection and decentralized identity, but Signal’s centralized infrastructure enables simpler UX, better availability, and more mature security engineering.
Key trade-offs vs Matrix: Static provides IP address protection and simpler encryption (MLS vs Megolm+Olm), but Matrix has a more mature federation model and larger ecosystem.
Key trade-offs vs SimpleX: SimpleX provides stronger metadata resistance (no user identifiers at any layer), but Static provides better group messaging scalability (MLS vs pairwise) and richer community features.
Security Contact
If you discover a vulnerability in Static’s privacy implementation, please report it responsibly. Details on how to report security issues will be published at static.chat/security when the project reaches beta.
In the meantime, open a private security advisory on the GitHub repository or contact the maintainers directly.