MLS pairwise review
Research, not an audit
These pages are research and development and may not match the live app. Do not treat this as an audit. Shared for testing and demo only. Please use responsibly.
Code-backed review of mls-core and its use inside product cascade v3 (crypto-cascade). Scope is the pairwise (2-party) MLS layer, not an N-party Glitr group ratchet.
Verdict
Pairwise MLS in cascade is a valid RFC 9420 suite-1 use (thin façade over AWS mls-rs) and is already required for session establishment (ContactSession.established needs mls_group_state). It is defense-in-depth next to Signal and PQXDH, not a substitute for group TreeKEM. Formal verify badges in the mls repo remain stubs.
Findings
| ID | Severity | Status | Summary |
|---|---|---|---|
| GLITR-2026-021 | Medium | Confirmed | Façade lacked self-update / remove; pairwise path discarded add-commits (fine for 2-party only). Without remove/update, membership PCS cannot be claimed for groups. |
| GLITR-2026-022 | Low | Confirmed | MLS identity + group export are JSON with secret material; sealing is the caller’s job (@encrypted mailbox / protocol secrets). Export without at-rest seal is plaintext key material. |
| GLITR-2026-023 | Low | Confirmed | Key-package refresh ran on responder after welcome only; initiator glare re-establish and published-KP hygiene needed explicit policy tests. |
| GLITR-2026-024 | Info | Info | Coarse mls-core errors (GroupOperation / InvalidMessage) are intentional (no oracle leakage). Cascade maps them to fail-closed Crypto / InvalidCiphertext / DecryptionFailed. |
| GLITR-2026-002 | Medium | Mitigated (product) | Groups historically pairwise-fan-out the chat plaintext. N-party GroupSession + commit/welcome delivery is the remediation path. |
Review axes
API honesty
- Exposed: identity, key package, create/add/join,
process_commit, app encrypt/decrypt, export/import. - Phase-2 façade adds:
self_update,remove_member, roster helpers. - Suite 1 only; BasicCredential; in-memory KP + group storage inside the client.
Key-package lifecycle
- Profile publishes one
mlsKeyPackage. - Responder refreshes after welcome consumes the package.
- Cascade tests cover refresh so a second join with the stale published package fails.
Welcome + glare
- First cascade message packs Signal + PQXDH + MLS welcome inside the outer RSA+ML-KEM wrap.
maybe_yield_initiatorclears Signal, PQXDH, and MLS together (GLITR-2026-001).
State export
export_group/export_identityare opaque-to-app JSON; must stay inside sealed collections (ProtocolSession,GroupProtocolSession,protocolSecrets).
Commit handling
- Pairwise establish uses welcome only; the add commit is applied locally by the committer and is not needed by the sole joiner.
- N-party groups must deliver commits to existing members (
process_commit) and welcomes to joiners.
Claims
- Do not describe Glitr groups as “MLS groups” unless
GroupSession+ membership commits are active. - Inner cascade stack is AES → MLS → Signal → PQXDH (see Cryptography).
Phase-2 patch priorities
- Expose
self_update/remove_member/ roster onmls-core. - Harden KP refresh + glare MLS alignment tests in
crypto-cascade. - Introduce
GroupSessionand replace plaintext fan-out for group chat payloads.
Catalog: Findings.
