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.
A threat model is only useful if it names adversaries and states an outcome for each. What follows does that, with the failures in the same breath as the defences.
Adversary classes
Passive relay operator
An operator who honestly runs the relay and reads everything it stores.
Defended. Message content, attachment content, group attributes, and profile names are ciphertext at the relay. The relay never needs message plaintext or device private keys.
Not defended. Everything in the metadata column of Limits and metadata: social graph, timing, frequency, envelope sizes, device counts, group sizes, IP addresses. A passive operator with logs reconstructs a great deal without decrypting.
Compromised or malicious relay
An operator, or an attacker holding the relay, that serves incorrect data on purpose.
Defended. A substituted identity key fails against a pinned composite identity commitment. Replacing the X25519 or Ed25519 component changes the commitment. The client rejects mismatches before it mutates protocol state. UntrustedIdentityError and IdentityKeyChangedError surface the event. Rollback to an older tuple is detectable. Bundle signature checks produce SIGNATURE_VERIFICATION_FAILED or INVALID_PREKEY_BUNDLE.
Partially defended. Against a never-verified first contact, a hostile relay can serve its own key from the outset. Trust-on-first-use is explicitly unverified and does not claim authenticated identity. Only an out-of-band safety-number comparison closes that gap. See Identity change and safety numbers.
Not defended. Denial of service, selective dropping, and delivery delay. Cryptography cannot compel a relay to deliver. The relay also controls prekey vending. Mishandled one-time prekeys can therefore degrade forward secrecy. The relay contract states that "the relay must not hand out the same one-time prekey as if it were still unused," so monitor PREKEY_NOT_FOUND instead of swallowing it.
Network observer
Anyone between devices and the relay.
Defended. Content, by the protocol itself, independently of transport security.
Not defended. Traffic analysis. Connection times, packet volumes, and endpoint addresses remain visible. The published sealed-sender deanonymization result operates at the application layer. It therefore works against users on Tor or a VPN. See Limits and metadata.
Malicious peer
A legitimate participant acting against you.
Not defended, by definition. A peer holds the keys and can screenshot, export, forward, retain, or run a modified client. Cryptographic confidentiality creates no remote deletion guarantee. Group removal must rotate the sender key with rotateGroupSenderKey(groupId). A former member can read data that still uses the old key.
Compromised endpoint
Malware, a hostile operating system, a seized unlocked device, a coerced user.
Not defended. End-to-end encryption protects the middle. Plaintext exists on the device by design, and an attacker at that layer reads it. Forward secrecy limits the damage backwards, and the SDK deletes message keys after use. The compromise exposes present and future messages while it lasts.
Application supply chain and browser code delivery
An attacker who modifies the code that encrypts data.
Not defended, and not solvable by this SDK. In a web deployment, the server ships the encryption code. One malicious deployment can capture keys before ciphertext exists. One practitioner summary states that "these mechanisms for trusting web apps are still pretty early and there's no blessed path." Native and Expo deployments move the trust anchor to a platform signing channel. They do not remove it. The browser store (/local/store/web) is supported, and its support status does not narrow this boundary: code delivery is an origin problem, not a storage problem.
Legal compulsion
A subpoena, warrant, or production order served on you.
Defended, in a specific sense. You can produce only what you hold. Your relay holds envelopes and metadata. See the breach-notification discussion in E2EE is not TLS.
Not defended. Metadata is compellable and is often what authorities request. No protocol choice affects compulsion directed at a user's device or application platform.
Post-quantum posture
The exact specification revisions the implementation targets, and nothing beyond them.
| Specification | Revision |
|---|---|
| X3DH | Revision 1, 2016-11-04 |
| PQXDH | Revision 3, 2023-05-24 (last updated 2024-01-23) |
| Double Ratchet | Revision 4, 2025-11-04 |
| Sesame | Revision 2, 2017-04-14 |
| ML-KEM Braid | Revision 1, 2025-02-21 (last updated 2025-09-26) |
From the SDK's security documentation, verbatim:
- "PQXDH uses standardized FIPS 203 ML-KEM-1024 behavior."
- "Public keys and ciphertexts require exactly
0x0A || raw ML-KEM-1024 bytes." - "PQXDH sessions keep SPQR mandatory."
- "The default SCKA mode is the specification-defined ML-KEM Braid profile using ML-KEM-768 and bounded Reed-Solomon decoding."
- "HEK follows the ML-KEM Braid specification:
SHA3-256(ek_seed || ek_vector)." - "Direct ML-KEM-768 SCKA remains an explicit SDK mode for product-reviewed constraints; it is not the default."
Two consequences follow.
The FIPS 203 line is about algorithm behaviour, not validation. This is pure-JavaScript cryptography and it is not a FIPS 140 validated module. If a procurement requirement names validated cryptography, this does not satisfy it.
There is no wire compatibility with Signal Messenger or libsignal. OpenE2EE is an independent implementation profile of the published Signal Protocol specifications. It is not affiliated with Signal Messenger LLC or Signal Technology Foundation. It does not interoperate with the Signal Messenger service. Messages, identities, and sessions do not cross between the two.
Safety numbers from this SDK never match values that a Signal Messenger client displays. The systems compute them from different inputs. This SDK uses a composite-identity commitment instead of a single Curve25519 key. A user cannot verify a contact by comparing values between the systems. Verification requires two parties who both use this SDK.
DEVIATIONS documents each departure from the specifications and its cost. Several deviations change behavior, not appearance. Skipped-key retention limits, hard device deletion, and client-authority group state each weaken an assumption from the specifications.
Default policy
createSignalProtocolClient defaults to protocol: { postQuantum: 'required', braid: 'required' }. Sessions that cannot negotiate post-quantum material fail rather than proceed, surfacing PQXDHRequiredError. Setting 'compatible' is an explicit opt-in, and the SDK states its limit plainly: it "does not allow downgrade recovery." Choose it only with a specific interoperability reason and a written record. See Security policy.
Where responsibility sits
The client owns protocol coordination; the host application owns persistence, authentication, authorization, and product policy.
Your app owns decrypted message rows and local files after the Signal Protocol client decrypts or stages them.
Your application must authenticate relay access and authorize device registration and linking. It must also define the backup posture of decrypted content. A correct protocol implementation under an application that authenticates nobody protects nobody.
Audit status
The SDK is reviewed continuously by adversarial AI agents; it is not audited by any independent firm. It is 0.1.x. Public APIs and persisted formats may change before 1.0. If your decision depends on external verification, that evidence does not exist yet. Security review documents what we run today.
Next
- Limits and metadata: the same boundary, organised by artifact.
- Security policy: supported versions, reporting, and disclosure.
- Security review: what we test today.
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.
Start
From install to a working encrypted round trip, then the one decision — which adapters you run — that constrains every page after it.