Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions proposals/4358-out-of-room-server-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# MSC4358: Out-of-room server discovery

Currently in Matrix, it is possible for the servers which a new joiner
trusts during the join process to place the joiner into a parallel
branch that is not communicated to any other server.

Consider the following scenario:

![](./images/4358-out-of-room-server-discovery.png)

A room has several members, Blue, Green, Yellow, and Bronze. They have
been participating for some time.

Then, the Blue decides as a room creator to create a concurrent branch
in the room that is only going to be communicated to new joiners.
Blue is also in control of the room alias, and other external links to
the room. This prevents new joiners from seeing the existing members.

## Proposal

When a server joins a room for the first time, it creates a
`room_participation_tag` for itself which is stored permanently. This
tag is derived from a hmac-sha256 of the server name and the
room_id: `hmac-sha256(server_name, room_id)`.

### The `POST /_matrix/federation/v1/discover_common_rooms` endpoint

A new endpoint is specified to allow servers to discover common rooms
without either party revealing which rooms are being queried unless
both parties have provable knowledge of the room.

For the set of rooms the requesting server is interested in,
the server creates a _room participation tag_ for each room
by taking the requested server's name and deriving a hmac-sha256 of
the _server name_ and the `room_id`: `hmac-sha256(server_name, room_id)`.

#### Request body

- The `room_participation_tags` are the tags for which the requesting
server is asking if the requested acknowledges. This is an array of
strings.

#### Response body

The responding server simply responds with the token tags for
which it has a match stored:

- The `recognised_tags` are any of the queried tags which the
requested server acknowledges. This property is an array of strings.

## Potential issues
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protocol doesn't scale and requires more data for more rooms. So a passive scan doesn't really work for a large homeserver.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way to make a passive mechanism that does scale is to incrementally collect tags from other servers and store them. And possibly even allow them to be passed on, but this does mean just storing random noise in most cases.


### Left/Banned members can track new members when queried

If members which have left or are banned from a room are queried about
a key from a server, then they can potentially infer that the querying
server is a member of the room.

### Useless if a victim server hasn't built up knowledge of common peers through other rooms

A server will not know which servers to query if it hasn't interacted
with any other server before through membership in other rooms.

### Not clear when it is appropriate to query common rooms

How often should rooms check for unexpected results?

When joining a new room is a good start. But how frequently otherwise?
Comment on lines +64 to +68
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If epochs were going to be considered, then would be a good time too. It's not clear which servers you would select to try pry information...


## Alternatives

### OPRF key in the create event

An OPRF[^oprf] key could be placed into the create event which is used
instead via `OPRF(room_key, server_name)`. However, it's unclear
if there are any situations where the `room_id` is known and not
the create event.

[^oprf]: https://datatracker.ietf.org/doc/rfc9497/
Comment on lines +72 to +79
Copy link
Contributor Author

@Gnuxie Gnuxie Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically people sometimes share a link to a private room in a public room to share context with some people who are in both rooms (but not all people are in both of them)


Comment on lines +72 to +80
Copy link
Contributor Author

@Gnuxie Gnuxie Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should mention explicitly that the information used in the tag has to be intrinsic to the room. So that the room creators can't erase it or misrepresent it in any possible branch of the room.

## Security considerations

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proposal would allow HS1 to check whether HS2 is participating in a room, so long as HS1 knows HS2's server name and the room ID they want to check for. (The only benefit hash(server_name, room_id) brings is that HS1 needs to know the room IDs they want to check for ahead of time.) Thus, this proposal can leak an HS's participation in a room to HSs not participating in said room, which is not great.


- None considered.

## Unstable prefix

- The endpoint `/_matrix/federation/v1/discover_common`_rooms is `/_matrix/federation/v1/org.matrix.msc4358/discover_common_rooms`

## Dependencies

- None.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.