Skip to content

[WIP] MSC4299: trusted users #4299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
114 changes: 114 additions & 0 deletions proposals/4299-trusted-users.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# MS4299: Trusted Users
Copy link
Member

Choose a reason for hiding this comment

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

Needs "Security Considerations" as per https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/0000-proposal-template.md#security-considerations

The problem with adding a general concept ("trusted users") is that it's hard to gauge whether it is fit for purpose until there are actual use cases which use it. Different MSC authors may see "trusted users" in different ways and have different non-overlapping sets of requirements. For this reason, I don't think adding this concept is a good idea at this time.

Random comments whilst reviewing:

  • It's not possible to express groups of users. This limits the applicability of this proposal: companies/organisations likely won't be able to use this. For example, you can't whitelist a server (e.g everyone on :element.io) or a space (e.g everyone who is a member of this space). Similarly, the inability to express groups means this list is going to grow very large, which will add significant overhead to an initial sync (we already see this with push rules in account data which has per-room settings).
  • It's not cryptographically secure. The notion of "trust" in Matrix is general grounded in whether we trust the other user's cryptographic keys. This is not what is happening here. The server can modify this list at will. This limits the applicability of this proposal: you can't use trusted users for security-sensitive operations. For example, the MSC proposes to allow URL previewing from trusted users, but since the set of trusted users is controlled by the server, this is not safe.

Copy link
Author

Choose a reason for hiding this comment

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

Hm, when drafting this up I did not really consider any security considerations to be of note. I was under the assumption that people would only be using servers they trust, but considering server-side manipulation is considered a CVE I'll bring that back to the drawing board.

It's not possible to express groups of users.

In a prior comment I considered changing it from explicitly users, to "entities", which would allow for users, server names, glob patterns, and I could presumably also work rooms (spaces) into that. Hopefully, that will tick off that checkbox.

The notion of "trust" in Matrix is general grounded in whether we trust the other user's cryptographic keys.

Assuming the issue here comes down to the wording, do you have any suggestions on what better terminology would be? I'm hesitant to use anything like "friends", as that implies that there's an agreement between the entites, but something like "known" is too vague and "safe" might be misleading. Especially if we're considering that the server could tamper.

Choose a reason for hiding this comment

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

I assume the issue is if this ended up controlling any cryptography-related functions. That's not the use we're intending, though, although it should be kept in mind.

If we need to cryptographically secure the list, we do have the cross signing/back up key that we could use to authenticate the text. This does conflict with the idea of companies having a preset trusted list for accounts on the server though.

Regarding expressing groups of users, I'm not entirely sure how well that fits in with the metaphor of a contact list. It would end up with this being closer to an LDAP directory in mental model. That's a thing for email (I know both Outlook and Apple Mail can read contacts from directories), but it's not something that will be familiar to mobile users, more used to WhatsApp-like messaging.

That, plus the crypto concerns, raises the question as to what extent those ideas should be mixed. Having a secure contact list would also require that a method like spaces isn't supported, because that can be manipulated by the server. It would make sense to leave that kind of stuff to a dedicated MSC.

this list is going to grow very large, which will add significant overhead to an initial sync

This depends on how people use this. My own contacts list, for example, has around 300 cards (most of them representing people I've met and exchanged numbers with IRL) - this is pretty high compared to my peers. I imagine a lot of people will only have ~10 trusted users on the list, and a limited few will have automation that add thousands of users. I'm not sure to what extent we want to support the latter case.
If it is something we want to support, we can explore ideas to allow pulling down parts of the list at a time and checking with the server if specific accounts are on it.

Copy link
Author

Choose a reason for hiding this comment

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

I don't believe this proposal is remotely suitable for anything to do with cryptography, either existing bands should be used for what's relevant, or someone far smarter than me should open another proposal with this in mind if necessary.

This depends on how people use this.

It's best to consider most usecases. I'd like to add all of my servers and all of my accounts as "trusted users" for example, and I know people who would find some way to stuff policy lists into this. Having wider targets is a net-gain either way.

Choose a reason for hiding this comment

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

The notion of "trust" in Matrix is general grounded in whether we trust the other user's cryptographic keys.

I also think this is a confused way of putting this - we've verified the user, we trust that the channel is secure, we do not inherently trust a verified user.

Copy link
Author

Choose a reason for hiding this comment

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

"trust" is heavily referenced in MSC4161, which should be kept in mind. Specifically, "Verified User" references it a lot.

Choose a reason for hiding this comment

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

I'm only seeing it in MSC4161 in instructing to not use the TOFU terminology, and in terms of 'trusted device,' which makes sense. From what I'm reading, it instructs the usage of the 'verified user' terminology that I used.


> TODO: *trusted* is misleading and conflicting

Currently, Matrix has a way to assign specific users as "ignored", declaring to both your client and server that you
would not like to interact with a given user, and in some situations would not like them to interact with you.
However, there is no mechanism to do the inverse - assign specific users as "trusted", even more so define what
"trusted" even means. This proposal will aim to tackle both of these issues, while allowing for plenty of
expansion in the future as needs of the protocol change.

## Proposal

For clarity's sake, the following words are used with the associated context throughout this proposal:

- Entity/Entities: something that matches an entity that can be trusted (i.e. user ID, room ID, server name, glob pattern)
- Ignored: [entities that are ignored OR blocked][4283]
- Non-trusted: entities who are neither trusted nor ignored (the default state)
- Trusted: entities who are explicitly added to the trusted users account data object

> TODO: users -> entities

While this proposal does not aim to tackle what to *do* with user trust (that's for followup MSCs to define), it lays
the foundations for defining that an entity can be "trusted" at all.

Currently, we already have [the ignored users list][1], which allows you to define which users you never want to see.
This proposal introduces a "trusted users list", which behaves semantically similarly to the ignored users list,
but the inverse. Clients and servers may wish to give "trusted" users special treatment, like they currently do
with ignored users. Examples include (but are not limited to) servers filtering invites to only allow trusted users to
send them, clients disabling media previews and only enabling them by default for trusted users, only allowing
users to initiate calls that reach the recipient if the recipient trusts them, and preventing profile fields
(display name, avatar, custom fields) being sent to non-trusted users. However, these capabilities are not defined in
this proposal itself.

Clients can create an account data entry with the type `m.trusted_users`, with the following format:

```json5
{
"trusted_users": {
"@user1:example.com": {}, // specific user
"@*:example.com": {}, // all users matching the glob pattern
"example.com": {}, // all users on the homeserver example.com
"!roomid:example.com": {}, // all members of the specified room
}
}
```

> TODO: restrict globs to server names (i.e. wildcard domains) and user IDs?

This event's content should be an object, whose keys are generic strings that are intended to represent an entity.
Note that here, the objects following the trusted entities (hereon referenced as the "trust configuration") are
empty objects - this is to allow for namespaced fields to be added by later MSCs to further extend the capabilities
of trust (such as aforementioned examples).

An **example** of an extended trust configuration could be:

```json
{
"trusted_users": {
"@user1:example.com": {
"com.example.allow_custom_colours": true
},
"@*:example.com": {}
}
}
```

If a user does not trust any users, their account data would look like `{"trusted_users": {}}`.

A user **must not** be ignored *and* trusted, they are mutually exclusive states.

Choose a reason for hiding this comment

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

What mechanism exists to enforce this? Otherwise it doesn't really make sense to specify 'must' for this.

It also conflicts with the idea of using this as 'per-user settings' that Emma floated - for something like hiding a user's avatar in mutual rooms. Perhaps that works better as a different MSC, given it doesn't match the semantics of 'trusted users', though

Copy link
Author

Choose a reason for hiding this comment

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

The server should enforce it, i.e. refuse to update the trust account data if there's a conflict with the ignored users

It also conflicts with the idea of using this as 'per-user settings' that Emma floated - for something like hiding a user's avatar in mutual rooms. Perhaps that works better as a different MSC, given it doesn't match the semantics of 'trusted users', though

I agree. Keeping ignores at all kinda conflicts with this, since something like {"trusted_users":{ "@bad:example.com": {"ignored": true } } } would probably better, but as noted in the "Alternatives" section, this would be an expensive and high-friction endeavour, which is most likely suited for a different MSC entirely.

In the event that there is a desynchronisation between the ignored users account data, and the trusted users
account data, the ignored users should take priority over trusted users.
Servers *should not* automatically remove trust from users when the client asks to ignore them, nor vice versa.
Clients *should*, consequently, attempt to atomically remove trust before attempting to ignore

Choose a reason for hiding this comment

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

Is there an API clients can use to do this atomically?

Copy link
Author

@nexy7574 nexy7574 Jun 12, 2025

Choose a reason for hiding this comment

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

That would be an implementation detail, but I'm pretty sure adding a new API endpoint would take this MSC out of "just another specced account data type" and into an actual API update, which brings its own set of challenges. I'd like to avoid that if possible.

To add - generally, clients already have the ignore list to hand anyway, and in this case will also have the trusts - checking for conflicts before sending any events wouldn't be difficult


## Potential issues

As this MSC aims to target functionality both in clients and in servers, there are likely to be inconsistencies in
the implementations. Hopefully, by not defining any actual uses for trust in this MSC, and instead relying on them
being proposed in followup proposals, servers will be able to advertise support for their individual functionalities,
and clients will be able to feature-gate appropriately.

This proposal also has potentially overlapping behaviour with other proposals, see the alternatives section below.

Due to ignores and trusts being mutually exclusive, there is the risk that they will become desynchronised, and
have overlapping entries. As defined above, ignores should take priority over trusts.

## Alternatives

- [MSC4155][4155] implements invite filtering by defining allowed/ignored/blocked users & servers. The allow function

Choose a reason for hiding this comment

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

What it does have over this one is the ability to define whole servers - I'm not sure that makes sense for this MSC given its semantic role, and I think they co-exist well enough, a tough some thought should be given to their interaction (does being trusted override being filtered by this/are trusted users added to the allowlist?)

Copy link
Author

Choose a reason for hiding this comment

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

The argument for whole-server trusts could be made (I'd want to trust timedout.uk, nexy7574.co.uk, and transgender.ing for example, since I know all users on there are good & trusted users), but does add additional complexity, and is way less applicable in practice than specific user IDs.

The wording could be changed from users to entities though, which opens us up to setting trust levels for both users and servers, and potentially even glob patterns, which would also be quite powerful. I'll think on that.

Copy link
Author

Choose a reason for hiding this comment

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

does being trusted override being filtered by this/are trusted users added to the allowlist?

I think in this case, user trusts would be the implicit default, with any explicit definitions in MSC4155 overriding it (i.e. if a user is trusted but explicitly blocked in 4155, the result would be blocked, and vice-versa). But that's just my two cents, I've only lightly linked it to 4155.

of that proposal has potentially overlapping functionality and semantics with this one, although lacks the future
extensibility that this one aims to provide. Contrarily, 4155 could be used to build on top of this one.
- Doing away with ignores, and instead only using trusts, and adding the ability to mark a trust as an ignore/untrust,

Choose a reason for hiding this comment

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

Other alternatives

  • semantically 'per-user settings' rather than trusted, perhaps with a m.trusted key

Also to think about, defining the default settings for behaviours specified by keys when they are unset for a particular user. Ie a 'trusted_user_default_settings' map

Copy link
Author

Choose a reason for hiding this comment

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

Defining "defaults" is difficult given the followup MSCs I have in mind don't exist yet. imo followup proposals that aim to add trust features should tune their expectations to having their value as a false-y/nil/null/whatever value, since defining and updating defaults seems difficult in this context.

or some other semantically similar meaning. This would be complicated and just generally expensive

## Security Considerations

- Server-side manipulation: a homeserver's administrators are able to modify account data without notice, which could
be used to cause unexpected client/server behaviour. The aforementioned URL preview example
[was already a CVE in matrix-react-sdk][CVE-2024-42347], so additional care must be taken when considering followup
capabilities.

## Unstable prefix

Until this proposal is accepted, implementations should make use of the account data event type
`uk.timedout.msc4299.trusted_users`, instead of `m.trusted_users`.

[1]: https://spec.matrix.org/unstable/client-server-api/#mignored_user_list
[4283]: https://github.com/matrix-org/matrix-spec-proposals/pull/4283
[4155]: https://github.com/matrix-org/matrix-spec-proposals/pull/4155
[CVE-2024-42347]: https://github.com/matrix-org/matrix-react-sdk/security/advisories/GHSA-f83w-wqhc-cfp4

## Dependencies

None.