Critique of the Matrix Protocol

Matrix is becoming a bit of a successor to XMPP as an interoperable cross-platform messaging protocol. It has a lot of potential and has a lot of backing by major institutions and kinda has clients on every major platform and 3DS.

But, it has a lot of flaws, and some architectural decisions have led to major vulnerabilities and general bugs in the past.

Rundown

The one-sentence description of how Matrix works is “e2ee rich-text IRC but structured like email”, but this skims over lots of important details.

The principal organizaion structure is based on “homeservers”, which host user accounts and store-and-forward messages between users. Users are referenced by a username and homeserver, as in @trey:foobar.style. Rooms are referenced by name and homeserver, as in #fractal:gnome.org. While rooms reside on a particular homeserver, users on any homeserver can participate in them (ignoring manual blocks, etc.). There is an optional end-to-end encryption scheme based on (meg)olm, an encryption library developed specifically for use in Matrix.

Servers do TLS mutual authentication with each other and both the server-server and client-server protocols are typically done over HTTP and WebSockets.

There is work to make Matrix run over lighter-weight protocols, but that effort is stalled and we’ll discuss that more later.

Issues

Architectural

// TODO

Merging layers of the stack leads to complexity with client bookkeeping and sloppy message format.

Cryptographic

// TODO

Philosophical

// TODO

If you want to make a chat client that works in web browsers, you don’t do that by building the whole stack around web technologies. You do that by making the protocol transport-agnostic and building web-compatible gateways.

Building on the web technologies leaks web conventions into software architecture. This is acceptable if the software is limited to web settings, but messaging protocols have very general audiences so that’s a faulty target.

Event format

Many inefficiencies are introduced by layering JSON encrypted as base64 as JSON strings. Here’s how messages are actually transmitted over the wire and stored on-disk.

// TODO rephrase, more elaboration

Encrypted event structure:

{
  "type": "m.room.encrypted",
  "sender": "@trey:foobar.style",
  "content": {
    "algorithm": "m.megolm.v1.aes-sha2",
    "ciphertext": "AwgGEpABxF4p2xr1zArApWGEEjOalPMKI6FKOu4mZQyoT/mrkhozCtDQt8x1/oKs1tjnrtOb5Z8pLM9Wv+pNVNpvtJ3CYCeLyhT4yfO1IO/CJxtQj08Kwanj9ZnXtRiYMwN+DB8mDfTVM9/OigJnM3SuJQXAQ+ogU3qsAdI6Dl9+Rjmr0Hmmq0Mk0ofFyUZNeJ1WP9fKxyebxA4LUvEbPNcAOVpGEGOc0EfxosQgmG3QVnWQmEghshVf2ylYSmYz/Wl827j+bKp3cV+I8k0yZb/S9dveDwxzFDJldqwN",
    "device_id": "TUBSVHMNHM",
    "sender_key": "r6owoH0Srn0Htbh/sOfSMFrtERyw6yqT4MKD5+9XyV4",
    "session_id": "WxbtTGXv924ktPy9/XpQsCE/tzR89IV3aZW+oY9Q8SU"
  },
  "origin_server_ts": 1675127915756,
  "unsigned": {
    "age": 69
  },
  "event_id": "$EjXD9Bc1U5rFcKXZsjkhow09KgYJJIBXD3xe53v1ulk",
  "room_id": "!abXyAjYGkYYqNbHJoB:matrix.org"
}

Decrypted nested event structure:

{
  "content": {
    "msgtype": "m.text",
    "body": "oh right it's monday"
  },
  "type": "m.room.message",
  "room_id": "!abXyAjYGkYYqNbHJoB:matrix.org"
}

Articles Index