David Teller 3 weeks ago committed by GitHub
commit 1c1b0e4bf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,227 @@
# **MSC3531: Letting moderators hide messages pending review**
Matrix supports **redacting** messages as a mechanism to remove unwanted
content. **Redacting** events, as defined in the Matrix spec, is a mechanism that
entirely removes the content of an event. Users can redact their own events, and
room moderators can redact unwanted events, including illegal content.
At present, there is no manner of **undoing** these redactions.
Historically, redacting messages has been useful for two use cases:
1. a user accidentally posting a password, credit card number or other confidential information,
in which case the information must be scrubbed as fast as possible from all places;
2. a moderator removing spam, bullying, etc. from a malicious user / spam bot.
Experience shows that redacting messages for case 2. is not always the best solution:
1. moderators make mistakes and there is currently no way for them to fix these;
2. in many cases, it may be desirable for a moderator to quickly hide a message
before having a conversation with other moderators to determine whether the
message should be let through (e.g. discussing whether the local room's CoC
should allow a possibly inflamatory political message - or a newbie moderator
waiting for experienced moderators to come online to ask them for clarifications
on borderline content);
3. some bots automatically remove messages based on heuristics (e.g. users sending
too many messages or too many images) but may get it wrong, in which case the
moderator currently cannot fix the errors of these bots.
In addition, proposals such as MSC3215, which aims to decentralize moderation,
will very likely increase the number of moderators - and in particular, the
number of moderators who may not be familiar with moderation tools, hence will
make mistakes.
For all these reasons, it would be very useful to have a mechanism that would
let moderators undo their own redactions. Unfortunately, reversing a redaction
is tricky, as we cover in the **Alternatives** section.
Rather, we propose a spec to let moderators *hide messages pending review*. This
mechanism is entirely client-based and will not prevent hidden messages
from being distributed, only from being seen by non-moderator users. This spec
can then be used by clients or bots such as Mjölnir to implement two phase
redaction:
1. a first phase during which messages are flagged for moderation (either by
a bot or manually) and hidden from general consumption;
1. a second phase during which moderators may either restore the message or
`redact` it entirely.
## **Proposal**
We introduce a new type of event: `m.visibility`.
Events with type `m.visibility` are ignored by clients if they are invalid or sent by users with
a powerlevel insufficient to send a *state event* `m.visibility`. This relation controls whether *clients* should
display an event or hide it.
An event of `m.visibility` MUST with the following *content* fields:
| Content Key | Type | Description |
|----------------|---------|-------------|
| `m.relates_to` | Visibility Relation | **Required** The payload for this event |
| `visible` | `boolean` | **Required** If `true`, clients should show the affected event normally. If false, clients should mark the affected event as hidden pending review. |
| `reason` | `string` | Optional. If `visible` is `false`, a reason that clients MAY display to indicate why the affected event is hidden pending review. |
Visibility relation
| Content Key | Type | Description |
|----------------|-----------|-------------|
| `rel_type` | `string` | **Required** Must be `"m.reference"` |
| `event_id` | `eventId` | **Required** eventId of the event affected by this visibility change. Must be a past event in this room. |
### Server behavior
No changes in server behavior.
### Client behavior
1. When a client receives an event `event` with type `m.visibility`
relating to an existing event `original_event` in room `room`:
1. If the `event` is well-formed and powerlevel of `event.sender` in `room` is greater or equal
to the powerlevel needed to sent **state event** `m.visibility`
1. If `event` specifies a visibility of "hidden", mark `original_event` as hidden
1. In every display of `original_event`, either by itself or in a reaction
1. If the current user is the sender of `original_event`
1. Label the display of `original_event` with a label such as `(pending moderation)`
1. If `event.content` contains a string field `reason`, this field may be used to display a reason for moderation.
1. Otherwise, if the current user has a powerlevel greater or
equal to `m.visibility`
1. Display `original_event` as a spoiler.
1. Label the display of `original_event` with a label such as `(pending moderation)`
1. If `event.content` contains a string field `reason`, this field may be used to display a reason for moderation.
1. Otherwise
1. Instead of displaying `original_event`, display a message such as `Message is pending moderation`
1. If `event.content` contains a string field `reason`, this field may be used to display a reason for moderation.
1. Otherwise, if `event` specifies a visibility of "visible", mark `original_event` as visible
1. Display `original_event` exactly as it would be displayed without this MSC
1. Otherwise, ignore
1. Otherwise, ignore
1. When a client prepares to display a message `original_event` with visibility "hidden", whether by itself or in a reaction
1. (see 1.1.1.1.1. for details on how to display `original_event`)
1. If an event `event` with `rel_type` `m.visibility` and relating to an existing event `original_event` is redacted, update the display or `original_event` as per the latest event with `rel_type` `m.visibility` in this room relating to the same `original_event`.
If several reactions race against each other to mark a message as visible or
hidden, we consider the most recent one (by order of `origin_server_ts`) the
source of truth.
For simplicity, if a user gains or loses the powerlevel `m.visibility`, this
does **not** affect any of the `m.visibility` relations already sent by that user.
This may, however, affect how hidden events are displayed to this specific user.
### Example use
A moderation bot such as Mjölnir might implement two-phase redaction as follows:
1. When a room protection rule or a moderator requires Mjölnir to redact a
message `original_message` in `room`
1. Copy `original_message` to a "moderation pending" room as message `backup_message`, with some UX to
decide whether `backup_message` should be PASS or REJECT.
1. Mark `original_message` in `room` as hidden, using the current MSC.
1. When a moderator marks `backup_message` as PASS
1. Mark `original_message` in `room` as visible, using the current MSC.
1. Remove `backup_message` from the "moderation pending" room.
1. When a moderator marks clone `backup_message` as REJECT
1. Send a message `m.room.redaction` to `room` to fully redact message `original_message`.
1. Remove `backup_message` from the "moderation pending" room.
1. If, after <some retention duration, e.g. one week>, a clone `backup_message` has been
marked neither PASS nor REJECT
1. Behave as if `backup_message` had been marked REJECT
## Potential issues
### Abuse by moderators
This proposal does not give substantial new powers to moderators, so we don't
think that there is cause for concern here.
### Race conditions
There may be race conditions between e.g. an edition (https://github.com/matrix-org/matrix-doc/pull/2676) and marking a message visible/hidden. We do not think that this can cause any real issue.
### Hidden channel
As messages are hidden but still distributed to all clients in the room, it is
entirely possible to write a client/bot that ignores hiding and one could
imagine using hidden messages to semi-covertly exchange messages in a room.
As there are already countless ways to implement this, we don't foresee this to
cause any problem.
### Liabilities
It is possible that, in some countries, if moderators decide to mark content as
hidden but fail to redact it, this could make the homeserver owner legally
responsible for illegal content being exchanged through this covert channel.
We believe that using a bot that automatically redacts hidden messages after a
retention period would help administrators avoid such liabilities.
## Alternatives
### Server behavior changes
We could amend this proposal to have the server reject messages with type
`m.visibility` if these messages are sent by a user with a powerlevel below
`m.visibility`. However, this would require changes to the flow of encryption
to let the server read the relation between events, something that is less than
ideal.
We prefer requiring that clients ignore messages sent by users without a sufficient
powerlevel.
### A message to undo a redaction
As the original objective of this proposal is to undo redactions, one could
imagine a message `m.room.undo_redaction` with the following behavior:
* The ability to send a `m.room.undo_redaction` is controlled by a
powerlevel, just as `m.room.redaction`.
* When a server receives a `m.room.undo_redaction` for event E, event E loses
its "redacted" status, in particular in any future `sync` or
`/room/.../event/...` or other, the original event E is returned, rather
than its redacted status.
* When a client receives a `m.room.undo_redaction` for an event E, they need
to refetch event E from the homeserver.
This proposal would have the benefit of removing the hidden channel.
However, servers are intended to redact events immediately and permanently, though
regulations for some areas of operation require the contents to be preserved for a
short amount of time. In any case, it is not possible to determine
how long a server is willing or able to keep event contents, so we can only assume
it has not kept them at all. Any attempt to undo redaction would, at best, race
against this retention duration, which may differ across homeservers in the same
room, and might end up causing divergence between the room views.
Thus, undoing is not possible, in practice.
### Injecting content in redacted messages
An alternative mechanism to undo redactions would be to let moderators un-redact
a message by injecting new content in it. This would let clients or moderation
bots such as Mjölnir implement undoing redactions by first backing up redacted
messages (in a manner similar to what we discuss in "Example use"), then if a
redaction is canceled, reinjecting content. We decided not to pursue this
mechanism as it is more complicated and it opens abuse vectors by malicious
moderators de facto modifying the content of other user's messages (even if this
could be mitigated by clients displaying who has modified a user's messages).
### Letting users hide their own messages
There would be use cases for users hiding their own messages, e.g. marking a
task as complete. We believe that this complicates the present MSC, as it
introduces edge cases that deserve their own discussion, e.g.:
- can a moderator make a message hidden by a user visible?
- how do we reinterpret a sequence of visibility change messages interleaving
self-hide, self-unhide, moderator-hide, moderator-unhide when one or more
of the messages in the sequence gets redacted?
For these reasons, we prefer postponing such feature to a further MSC.
## Security considerations
### Old clients
Old clients that do not implement this MSC will continue displaying messages that
should be hidden. We believe that it's an acceptable risk, as it does not expose
data that is meant to be kept private.
## Unstable prefix
During the prototyping phase:
- message type `m.visibility` should be prefixed into
`org.matrix.msc3531.visibility`.
Loading…
Cancel
Save