Limits and metadata
End-to-end encryption is not anonymity. This is the exhaustive, cited inventory of what remains visible, what defeats the guarantee entirely, and what we will not claim.
Encrypting content is a narrow guarantee, and the narrowness is the point. This page states the boundary precisely. A privacy promise outside this boundary creates liability and misleads users.
E2EE is not anonymity. The relay never needs message plaintext or device private keys. It does need to route, and routing is information.
The opacity ledger
Opacity ledger
| Artifact | Stays on device | Sent to relay | In object store | Visible as metadata |
|---|---|---|---|---|
identityKeyPair private half | yes | no | no | no |
identityKeyPair public half | yes | yes | no | yes |
| Message plaintext | yes | no | no | no |
| Message ciphertext | yes | yes | no | envelope size |
Session record (version: 4) | yes | no | no | no |
| Message keys (deleted after use) | yes | no | no | no |
| One-time prekeys, public halves | yes | yes | no | consumption rate |
recipientUserId passed to send() | yes | yes | no | yes |
deviceId and registration ID | yes | yes | no | yes, device count |
encryptedDeviceName | yes | yes | no | ciphertext length |
Sender certificate from fetchSenderCertificate() | yes | yes, issued by it | no | issuance time |
| Attachment plaintext | yes | no | no | no |
Encrypted attachment bytes via client.media.upload() | staged | no | yes | object size, upload time |
Profile name via encryptProfileName | yes | yes, as ciphertext | no | ciphertext length |
| GroupsV2 encrypted group state | yes, decrypted | yes, encrypted | no | version sequence, change rate |
| Sender-key distribution to a group member | yes | yes, encrypted | no | membership size, timing |
Read receipt from sendReadReceipt(...) | yes | yes | no | timing |
Typing indicator from sendTypingIndicator(...) | yes | yes | no | timing, frequency |
Safety-number decision via confirmSafetyNumber(...) | yes | no | no | no |
| IP address and TLS fingerprint | n/a | yes | yes | yes |
Read the right-hand column as an attacker would. Connection records reveal the social graph, relationship frequency, and approximate sleep schedules. They also reveal group size, membership-change timing, approximate message size, and sending device. For many threat models, this metadata is more valuable than the content.
Sealed sender, stated with its documented limits
Sealed sender removes the sender identifier from the envelope. The relay then handles a message that it cannot attribute to a sender. client.isSealedSenderEnabled reports whether it is active. This improves privacy but does not provide sender anonymity.
Published research is direct about why:
this one-sided anonymity is broken when two parties send multiple messages back and forth; that is, the promise of sealed sender does not compose over a conversation of messages
The mechanism is delivery receipts. Receipts are typically on by default, and each one is an automatic reply that correlates a sealed envelope with an identified fetch. The same work reported that Signal Messenger could link sealed sender users in as few as 5 messages. Follow-up research extended the technique from pairs to deanonymizing entire group conversations.
The property that matters most for your threat model: this attack operates at the application layer. It correlates message and receipt patterns, not network addresses. It therefore works against users behind Tor or a VPN because network anonymity protects a different layer.
Use sealed sender. Do not describe it to users as anonymity.
What defeats the guarantee entirely
A compromised endpoint. End-to-end encryption protects the middle. It does not protect an endpoint. Malware, a hostile OS, a jailbroken device, or an attacker with an unlocked phone can read device plaintext. A person who can see the screen can also read it. No SDK changes this property.
Backups. A backup is a copy, and its encryption defines its protection. A device backup can copy decrypted message rows to a cloud service. If the provider can access the key, the content returns to the custody model in E2EE is not TLS. Your app owns decrypted message rows and local files after the client decrypts or stages them. Your app must exclude or protect them in each platform backup path.
Browser code delivery. In a web application, the server in your threat model ships the encryption code. One malicious or compromised deployment can capture keys before ciphertext exists. There is no general solution today. One practitioner summary states that "these mechanisms for trusting web apps are still pretty early and there's no blessed path."
A non-extractable IndexedDB key is a signing and decryption oracle, not a safe. Cross-site scripting can read the handle and call decrypt() with attacker-selected input. In this attack, "the attacker never touches the raw key bytes" because the handle remains usable. This behavior makes the protection weaker than it appears. The browser store (/local/store/web) documents this boundary directly: encryption at rest is not an XSS defense, and a deployment requires the origin-security review its adapter guide describes.
Deletion. Cryptographic confidentiality creates no remote deletion guarantee. After another participant's device decrypts a message, that participant controls the plaintext. Delete-for-everyone is a cooperative client request, not an enforcement mechanism. It cannot remove a screenshot, export, or modified-client copy. State this limit in your product copy. See Deletion and revocation.
What we will not claim
Not FIPS 140-validated. This is pure-JavaScript cryptography. It is not a FIPS 140 validated cryptographic module and it does not run inside one. The SDK's security documentation uses the phrase "PQXDH uses standardized FIPS 203 ML-KEM-1024 behavior" to describe algorithm behavior, not validation. If procurement requires a validated module, this SDK does not satisfy the requirement.
Many US federal and federal-adjacent programs have this requirement. Configuration cannot change this status. Check the requirement before you build.
Reviewed continuously by adversarial AI agents; not audited by any independent firm. Treat every security property here as documented, tested, and machine-reviewed. Do not treat it as external evidence from a firm. See Security review for what we run today.
Not yet 1.0. The SDK is 0.1.x. Public APIs and persisted formats may change before 1.0.
Next
- Threat model: the same material organised by adversary class.
- E2EE is not TLS: what the content guarantee actually buys.
- Security policy: reporting, scope, and current posture.
- Deletion and revocation: what deletion can and cannot mean here.
Local-first and offline-first
Why the local store is a required adapter and the relay is optional, what changes when the device is the authoritative copy, and the parts of local-first that are still genuinely unsolved.
Threat model
The adversary classes this SDK defends against, the ones it does not, the post-quantum posture with exact specification pins, and the current audit status.