-
Notifications
You must be signed in to change notification settings - Fork 401
MSC3779: "Owned" State Events #3779
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
base: main
Are you sure you want to change the base?
Changes from all commits
76c147c
837c360
ed050fa
68a0463
ece4284
8d68c29
54ac53b
67b6fa8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# MSC3779: "Owned" state events | ||
|
||
## Problem | ||
|
||
[Live location sharing](https://github.com/matrix-org/matrix-spec-proposals/pull/3489) and [group VOIP signalling](https://github.com/matrix-org/matrix-spec-proposals/pull/3401) both need non-admin users to be able to create state events, but the default room power levels prevent this. | ||
|
||
This means that to allow normal users to place a call or share their live location, either: | ||
|
||
* users must be granted a higher power level, or | ||
* rooms must have non-default power levels to allow anyone to create state events. | ||
|
||
We anticipate that other future applications will have a similar need for normal users to be able to create state events. | ||
|
||
## Proposal | ||
|
||
We propose allowing unprivileged users to create "owned" state events, where the `state_key` equals their MXID, or starts with their MXID plus underscore. | ||
andybalaam marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could probably get behind @toger5 's suggestion to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to disagree with @toger5 on the array solution. Someone has brought this up in the past, but it seems like this would require a monumental effort from every Matrix client/server/app in the ecosystem to support the new room version:
Overall, this feels like too little benefit for such a difficult transition path. The key space for room state is already infinite, so we don't really benefit from having "more" state keys to play with either. As for what suggestion I would make, if the issue is that:
Then maybe we can combine the "magic state key" approach and the ownership field approach into a solution where:
Or perhaps, an even more minimal solution would get rid of the namespacing, and just rely on opting-in to ownership for an event type to mitigate squatting. Then it would be up to the specifications of each event type with ownership semantics to say how they avoid letting the application get DOS'd by squatters. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I would advise against this specific approach as it sounds like it would be incredibly brittle in the face of state resets. Imagine if a state reset chooses the "wrong" power level and now suddenly a large subset of events lose ownership semantics. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there are very useful thoughts in this thread. I think this MSC's focus is not perfectly collected with the word "owned". It tries to provide a per member space outside the power levels. Basically moving state events outside the realm of controlling room properties and just using it to share "instant access" data with other members that has no impact on the room properies (live location, rtc membership). |
||
|
||
This will require a new room version since it affects room permissions. | ||
|
||
(Note: this is inspired by [MSC3757 Restricting who can overwrite a state event](https://github.com/matrix-org/matrix-spec-proposals/pull/3757), but these two proposals are independent.) | ||
|
||
### Affected events (state_key starts with sender MXID) | ||
|
||
For example, to start sharing a live location: | ||
|
||
```json5 | ||
{ | ||
"type": "m.beacon_info", | ||
"state_key": "@matthew:matrix.org_uiyeesknsfbhhbsdf", | ||
"sender": "@matthew:matrix.org", | ||
"content": { | ||
// details omitted | ||
Johennes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
``` | ||
|
||
The above event will be allowed even if the user does not have the `state_default` power level because the state key starts with the sender's MXID plus underscore. | ||
|
||
Similarly, if the state key were exactly the sender's MXID it would also be allowed: | ||
|
||
```json5 | ||
{ | ||
"type": "m.beacon_info", | ||
"state_key": "@matthew:matrix.org", | ||
"sender": "@matthew:matrix.org", | ||
"content": { | ||
// details omitted | ||
} | ||
} | ||
``` | ||
|
||
### Unaffected events (where state_key does not start with sender) | ||
|
||
Events like the following will NOT be affected: | ||
|
||
```json5 | ||
{ | ||
"state_key": "@andyb:matrix.org_uiy", // NOT affected - wrong MXID | ||
"sender": "@matthew:matrix.org", | ||
// Other parts omitted | ||
} | ||
``` | ||
|
||
```json5 | ||
{ | ||
"state_key": "", // NOT affected - must start with MXID | ||
"sender": "@matthew:matrix.org", | ||
// Other parts omitted | ||
} | ||
``` | ||
|
||
For these events the existing rules on power levels will apply. (Note: in fact, the first event will be rejected by rule 8 of the Authorisation Rules even if the sender has a sufficient power level, because the state_key does not equal the sender's MXID.) | ||
|
||
### Unaffected events (where event type is a special case) | ||
|
||
Events such as `m.room.power_levels` that require `state_key` to be `""` will not be affected. | ||
|
||
Events such as `m.room.create` and `m.room.member` which have special handling in the Authorisation Rules will not be affected. | ||
|
||
## Spec wording | ||
|
||
In section 7.5 of the Client-Server API, the section [m.room.power_levels](https://spec.matrix.org/v1.2/client-server-api/#mroompower_levels) paragraph 3 should be changed to read: | ||
|
||
> The level required to send a certain event is governed by `events`, `state_default` and `events_default`. If an event type is specified in events, then the user must have at least the level specified in order to send that event. If the event type is not supplied, it defaults to `events_default` for Message Events **and owned State Events**, and `state_default` for **other** State Events. **Owned state events are events with a `state_key` that equals the sender's MXID, or starts with the sender's MXID plus an underscore.** | ||
andybalaam marked this conversation as resolved.
Show resolved
Hide resolved
AndrewFerr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
In section 5 of the Server-Server API, [5.1.1 Definitions](https://spec.matrix.org/v1.2/server-server-api/#definitions) paragraph 1 should be changed to read: | ||
|
||
> #### Required Power Level | ||
> A given event type has an associated *required power level*. This is given by the current `m.room.power_levels` event. The event type is either listed explicitly in the events section or given by either `state_default` **(for non-owned state events)** or `events_default` **(for message events and owned state events)**. **Owned state events are events with a `state_key` that equals the sender's MXID, or starts with the sender's MXID plus an underscore.** | ||
|
||
Additionally, to improve clarity, we propose that the relevant section be explicitly mentioned in the room version definition, section "3.4 Authorisation rules". Rule 7 should be changed to read: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Additionally, Rule 8 should be removed:
...as that would override Rule 7 by rejecting all owned state events with a state key of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scratch that -- Rule 8 is still needed for preventing users from setting state they don't own. It could be reworded as such:
Or if we want to re-state the definition of an owned state event instead of referencing it:
|
||
|
||
> If the event type’s *required power level* **(see "m.room.power_levels" in the Room Events section of the Client-Server API)** is greater than the `sender`’s power level, reject. | ||
|
||
No additional restrictions are made about the content of the `state_key`, so any characters that follow the `sender` + `_` part are only required to be valid for use in a `state_key`. | ||
|
||
## Alternatives | ||
|
||
### Manually set power_levels | ||
|
||
In Element Call, rooms are created with `m.room.power_levels` set to allow the `m.call.member` event to be emitted by users with power level 0. This only works if you control the room creation process. Given that we probably want people to be able to participate in calls and share live locations in any room by default, requiring each room's power levels to be changed seems onorous. | ||
|
||
### Change the default power_levels for some event types | ||
|
||
We could modify the default power levels of a room to include a list of the event types that we want to be allowed, but this would create a growing, centrally-managed list of event types, and make life difficult for applications whose event type has not yet been included in the spec. | ||
|
||
### Combine this proposal with MSC3757 | ||
|
||
We did consider bundling this MSC as part of [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757) but since they are actually independent and that MSC has already received some review we felt that the more principled approach was to keep them separate. We do prefer that they be included in the same room version if accepted. | ||
|
||
### Prevent propagation of non-empty state_keys on special events | ||
|
||
Under "Beware of non-empty state_keys on special events" below, we discuss the potential problem that unprivileged users can create state events that look like important events e.g. `m.room.power_levels` and `m.room.topic`, but are actually invalid, since those events require `state_key` to be empty. | ||
|
||
We considered the idea of using auth rules to prohibit events that use standard event types but have non-standard `state_key`s, but rejected it for the following reasons: | ||
|
||
* Event bodies should not be trusted by clients (see [Room Event Format](https://spec.matrix.org/v1.2/client-server-api/#room-event-format)), so it is already established that clients should take care to validate events before acting on their contents. Blocking these events could give the impression that event bodies are actually trustworthy, encouraging clients to be sloppy and reducing the security of the whole system. | ||
* Before this MSC, if clients obey e.g. `m.room.topic` with a non-empty `state_key`, their current behaviour is incorrect and could be exploited by users with permission to send state events. This MSC does not actually change the rules here. | ||
|
||
However, if the team feels that this idea should be implemented, I (@andybalaam) have no objection. | ||
|
||
## Security considerations | ||
|
||
### Attacks on room state | ||
|
||
Restrictions on creation of state events were introduced to prevent graffiti (e.g. changing room topic) and denial-of-service attacks which increase the size of the room state to unmanageable levels. By allowing all users to create some state events by default, we make it possible for a room's state to be modified by users who do not have any special permission. | ||
|
||
By restricting these events to those with a state_key unique to the sender, we prevent unauthorised users from modifying room topics or other similar state, and we make it clear who is responsible for any such state. | ||
andybalaam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
If an individual user is sending too many state events, the server should apply rate limiting. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sending many state events will still impact the current state of the room, which comes during an initial sync. Also an initial sync will contains state event like those one, which can be pretty outdated, to take the example of an old location sharing. Has this been considered? (my feeling is like it look a bit of a hack to use the state of a room to send data such as "user location sharing state" to the room) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, this was considered, and the I think the right answer is to allow deleting state. It is already possible for a user with sufficient permissions to create huge numbers of state events, so this problem already exists to some extent. I tried to call out this problem in 8d68c29. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deleting state events is pretty much science fiction at this point (as far as I'm aware) and it's not clear how and whether it can be done safely. So I'm not sure it's a good idea if we have to rely on it ever happening. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I initially felt similarly but was convinced by conversations with others that this is exactly what state is for: things that are true now, and you shouldn't need to go searching in the timeline to find out about. We shouldn't let the lack of state deletion bias us away from using state as it was intended: instead we should implement state deletion! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. state deletion is not particularly scifi; we should just get on and do it. for instance, hiding deleted state events from the CS API would be trivial. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Somewhat late, there is a document! #3901 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
While this is true, there is a pretty big difference between allowing moderators to attack a room and allowing anyone who has joined to do so.
I think it's worth noting that this is a recovery mechanism, rather than something that prevents an attack. For state deletion which is purely CS API side this will still affect federated joins (and DB usage, and state resolution perf). My main concern is that since these state events will basically be invisible to clients, so even if the room has an active moderator who knows the dangers and how to deal with it, the moderator wouldn't even notice it happening. This would allow a malicious client to slowly create an unbounded number of state events in the room, which would a) make syncs very very slow even with lazy loading, and b) make federated joins incredibly slow, and possibly wouldn't ever complete with enough state events. The latter would not be fixable even with deleting of state over CS API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would MSC3757 be a preferred alternative, then? It aims to simply restrict who can overwrite an "owned" state event, meaning it still provides protection against users writing arbitrary/unspecced state events via required PLs for event types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that most rooms allow any user to send e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As it turns out, that's because So for rooms that explicitly a PL of 0 for something like |
||
|
||
If many users are performing a distributed attack on room state, this should be managed via moderation tools. | ||
|
||
Any other proposal that allows non-admin users to update room state (e.g. by special-casing particular event types) will likely allow similar attacks, and users with sufficient permission can already attack a room in this way. | ||
|
||
What is currently missing is the ability to clean up state after an attack. We believe this should be handled by allowing deleting state from a room, but since the exact definition of how to do that is tricky, we don't attempt to address it in this MSC. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a fatal wound in this proposal I think. The inability to clean up historical state events is at best a resource drain and at worst an invasion of privacy (think, you're leaving an audit trail of where you've been physically for live location sharing). I think I've mentioned to you before that there is a strong use case for an additional transport mechanism for these kinds of "ephemeral but I want the latest value" types of data. I would rather we invested time into said mechanism (so the data is outside the realm of the DAG) than further pollute the DAG with data: we already see the pain we have with having profile changes in the DAG, which is why MSC4218 is A Thing. The sad part is that we almost have such a mechanism today: receipts are exactly this kind of "epehemeral but keep the latest value" type of thing, but clients cannot send arbitrary ephemeral events, see MSC2477. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
MSC3489 is explicitly "Live location sharing with history" for use cases where you want that (e.g. cycle ride tracking). MSC3672 is for not keeping history by using ephemeral events.
We should distinguish between "state pollution" (lots of "obsolete" state keys in the language of MSC3901 Deleting state) and audit trails, which are not really about state but about things being non-ephemeral events.
(Possibly, but if so I don't remember!)
This is interesting: I would say things like "X is in a call" and "Y is sharing live location" do have the property of normally only wanting the latest value, but do not necessarily have the property of being ephemeral in the sense that when I join a room I do want to be told the latest value. This is even more true of some other kinds of state events e.g. something relating to a shared document or similar: these could last a long time and I don't want to have to keep telling everyone they exist every n seconds just in case people don't know yet. I think it is natural that rooms "age" and we should expect to upgrade them regularly. So why not invest time into MSC3901 or similar to make the existing mechanism (room state) work better for things that fit quite closely to its purpose (keeping hold of data that is true "now", even if I join much later than it was first created)? |
||
|
||
### Beware of non-empty state_keys on special events | ||
|
||
Clients and servers should take special care to ensure that important event types such as `m.room.power_levels` and `m.room.topic` have no effect when the `state_key` is set to start with the sender's MXID instead of the empty string as they usually do. This proposal allows some such events to be created by unprivileged users, and they should be ignored in contexts where `state_key` should be empty. |
Uh oh!
There was an error while loading. Please reload this page.