|
| 1 | +# MSC4278: Media preview controls |
| 2 | + |
| 3 | +Matrix caters to a wide variety of networks configurations. Some networks are closed and the users have a high |
| 4 | +degree of safety, and other networks are open to the public internet and are inherently less safe. This proposal |
| 5 | +aims to give the user more universal control over the content they see on Matrix, starting with media previews. |
| 6 | + |
| 7 | +Most graphical Matrix clients display media in the timeline of a room with a preview. Often these are delivered |
| 8 | +without any consent prompt, at least by default. This presents a risk to users who may be joining the network |
| 9 | +and do not have the same safety barriers that experienced users may have configured. |
| 10 | + |
| 11 | +With that in mind, this MSC provides a simple switch for users and homeservers to configure a global media preview |
| 12 | +preference. |
| 13 | + |
| 14 | +For the purposes of this MSC, the term "undesirable content" refers to images that the user does not want to see, |
| 15 | +be it illegal, abusive or otherwise unwanted. |
| 16 | + |
| 17 | + |
| 18 | +## Proposal |
| 19 | + |
| 20 | +This proposal introduces a new account data key, `m.media_preview_config`. |
| 21 | + |
| 22 | +This key contains the following content. |
| 23 | + |
| 24 | +```json |
| 25 | +{ |
| 26 | + "media_previews": "off|private|on", |
| 27 | + "invite_avatars": "off|on" |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +### `media_previews` |
| 32 | + |
| 33 | +A "media preview" is defined as any media in a room that may be rendered automatically without explicit |
| 34 | +user consent. |
| 35 | + |
| 36 | +Clients SHOULD show show or hide media depending upon this setting, on at least the following content types: |
| 37 | + |
| 38 | + - Media message types `m.image`, `m.video`, `m.file` which all can include thumbnail information or be thumbnailed |
| 39 | + by the homeserver. |
| 40 | + - The `m.sticker` event type. |
| 41 | + - Inline media via `img`. |
| 42 | + - Any event which includes thumbnail information or may be thumbnailed by the homeserver. |
| 43 | + - URL Preview thumbnails |
| 44 | + |
| 45 | +The above list is not exhaustive. Other MSCs SHOULD take this setting into account when rendering content that could |
| 46 | +be considered a media preview, such as [MSC4027](https://github.com/matrix-org/matrix-spec-proposals/pull/4027) (Custom Images in Reactions). |
| 47 | + |
| 48 | +The one exception to the rule for now is user avatars in rooms the user has joined. For the purposes of this MSC, |
| 49 | +by joining a room the user *has* consented to seeing the user avatars contained within. See the potential issues |
| 50 | +section for a deeper explanation. |
| 51 | + |
| 52 | +### `invite_avatars` |
| 53 | + |
| 54 | +`invite_avatars` refers to any **room** avatar rendered in the client, where the client has a `membership` of `invite`. |
| 55 | + |
| 56 | +This may typically be rendered in the form of an invite dialog, or a room list preview of a room. |
| 57 | + |
| 58 | +The avatar may refer to: |
| 59 | + |
| 60 | + - The `m.room.avatar` state event. |
| 61 | + - The inviting user's `avatar_url` from their profile (in the case of a DM). |
| 62 | + |
| 63 | +In *all* cases where an avatar may be rendered for a room invite, the preview MUST be controlled by this setting. |
| 64 | + |
| 65 | +Note while this setting is effectively boolean, we've kept the enum form to have symmetry with `media_previews` |
| 66 | +and to allow for future extensions. |
| 67 | + |
| 68 | +### Property value |
| 69 | + |
| 70 | +#### `off` |
| 71 | + |
| 72 | +The client MUST NOT show any previews for any media in affected rooms. Clients will hide the media entirely, |
| 73 | +behind a click-to-view prompt, or some other mechanism where a user is either prevented entirely or must consent |
| 74 | +to see the media. |
| 75 | + |
| 76 | +Users MAY individually consent to seeing media, for example by clicking on a prompt to show a preview. |
| 77 | +If consent is given, the client SHOULD then track that consent and show the media again in the future. The |
| 78 | +mechanism for tracking opt-in/opt-out of media is left as an implementation detail. |
| 79 | + |
| 80 | +#### `private` |
| 81 | + |
| 82 | +Previews for media MAY be shown in "private" rooms without a prompt. |
| 83 | +A private room is any room where: |
| 84 | + |
| 85 | + - The `m.room.join_rules` state exists |
| 86 | + - The `join_rule` key of this state is `invite`, `knock`, `restricted`, `knock_restricted`. |
| 87 | + |
| 88 | +If any other `join_rule` is set, or cannot be determined by the client then the assumption MUST be that the |
| 89 | +room is public and previews MUST NOT be shown. Future join rules may be added to this list, but it's critical |
| 90 | +that clients adopt a safety first approach here. |
| 91 | + |
| 92 | +Rooms without a `join_rule` are treated as "public". This is because such rooms are rare in practice, and missing |
| 93 | +state may be due to a client or server bug. In those cases we want to fail safe, and refuse to display media in rooms |
| 94 | +where we cannot be sure of the join rule. |
| 95 | + |
| 96 | +The user MAY still view specific media if the room is "public", and hide media if the room is "private". This could |
| 97 | +be provided via a button attached to the event, but is an implementation detail. |
| 98 | + |
| 99 | +Note that this setting has no effect for `invite_avatars`. Avatars can only be `off` or `on` for all invites. |
| 100 | +Bad actors can easily send a DM to a user (which would pass the `private` check) containing unwanted |
| 101 | +content. |
| 102 | + |
| 103 | +#### `on` |
| 104 | + |
| 105 | +Media SHOULD be shown in any room without a prompt. |
| 106 | + |
| 107 | +Users SHOULD be able to individually hide media, and this preference MUST be respected over any defaults defined in `m.media_preview_config`. |
| 108 | + |
| 109 | +This value is the **default** setting for both properties when no value is set, to keep with the previous defaults. |
| 110 | + |
| 111 | +### Other values |
| 112 | + |
| 113 | +Clients MUST treat any unknown property value in either defined property as `off`. This is to allow the feature |
| 114 | +to be extended in the future, without unsupported clients falling back to unsafe behaviours. |
| 115 | + |
| 116 | +### Levels |
| 117 | + |
| 118 | +The account data may exist at both the global and room level. The global setting defines the preference for |
| 119 | +all rooms, unless a per-room setting overrides it. |
| 120 | + |
| 121 | +If the client doesn't have access to room level account data, such as for invites then it should just read |
| 122 | +from the global account data. |
| 123 | + |
| 124 | +If `m.media_preview_config` is set at both global and room levels, the client MUST prefer the room account data value |
| 125 | +over the global account data value. E.g. account data of: |
| 126 | + |
| 127 | +```jsonc |
| 128 | +{ // Room-level account data |
| 129 | + "media_previews": "on" |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +```jsonc |
| 134 | +{ // Global account data |
| 135 | + "media_previews": "off", |
| 136 | + "invite_avatars": "off" |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | +would resolve to: |
| 141 | + |
| 142 | +```jsonc |
| 143 | +{ |
| 144 | + "media_previews": "on" |
| 145 | + "invite_avatars": "off" |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | + |
| 150 | +### Notes |
| 151 | + |
| 152 | +Homeservers MAY specify a default value ahead of time for the user, by setting a default |
| 153 | +value internally for the account data. The user MUST be able to mutate this value, as it's |
| 154 | +considered a safety feature. |
| 155 | + |
| 156 | +Not all clients will respect this configuration initially, and many clients will continue to support |
| 157 | +their own variant of this setting in the short term. |
| 158 | + |
| 159 | +## Potential issues |
| 160 | + |
| 161 | +### Holding more state |
| 162 | + |
| 163 | +This requires clients to hold more state about the room than they would do previously to render a room. This may |
| 164 | +present a challenge, particularly for mobile clients who may need this information to render push notifications. |
| 165 | + |
| 166 | +### Spaces |
| 167 | + |
| 168 | +A previous version of this MSC also explored the idea of the setting cascading through a space tree, but |
| 169 | +it was difficult to design for both because it required clients to hold more state about the room (e.g. traversing |
| 170 | +a large amount of state locally to determine the rules) as well as challenges in rendering the setting to users. |
| 171 | + |
| 172 | +A future MSC may explore the possibility of this applying to spaces, but this initial version will operate only |
| 173 | +globally and per-room. |
| 174 | + |
| 175 | +However, not having this feature means many rooms may need to apply their own rules. |
| 176 | + |
| 177 | +#### User Avatars |
| 178 | + |
| 179 | +This MSC explicitly rules out controlling room avatars in joined rooms. Conveying to users why avatars are not |
| 180 | +rendering, and giving the ability to explicitly opt-in/opt-out of user avatars felt beyond the scope of this MSCs |
| 181 | +room focus. |
| 182 | + |
| 183 | +A future MSC may be considered to give greater protection for user avatars. |
| 184 | + |
| 185 | +## Alternatives |
| 186 | + |
| 187 | +This MSC has been iterated on a few times before being published, and several alternatives were considered. |
| 188 | + |
| 189 | +### A well-known property for a global trust policy |
| 190 | + |
| 191 | +This was [originally considered](https://github.com/matrix-org/matrix-spec-proposals/tree/hs/homeserver-content-trust-level) |
| 192 | +to change the default policy on a server, so that users on that server would see previews based on their admin's preferences. |
| 193 | + |
| 194 | +This was rejected as it was far too coarse. Expressing a different rule based on the room you are in |
| 195 | +was not possible, and wouldn't allow homeservers to store different preferences. Also, confusingly |
| 196 | +if the server was a closed registration personal server that happened to federate with the internet |
| 197 | +then it would require you to mark your own server as untrusted, which felt wrong in practice. |
| 198 | + |
| 199 | +### Use join rules to determine safety |
| 200 | + |
| 201 | +This is actually part of the proposal under the "private" flag, but this alone wasn't satisfactory for all users. The join |
| 202 | +rules have no direct bearing on the content in the room, and bad actors inviting many people to a private room |
| 203 | +containing undesirable content would slip under this check. |
| 204 | + |
| 205 | +### Use space membership |
| 206 | + |
| 207 | +Like the above, we could determine that rooms within a trusted space are safe and rooms outside of it are |
| 208 | +not. However, this also comes with drawbacks. It would raise the bar for all clients to expose spaces |
| 209 | +as a feature in order to make their users safer, and in practice spaces are not fully supported either |
| 210 | +by the ecosystem (e.g. Element X) or organisations yet. |
| 211 | + |
| 212 | +### Room state safety flag |
| 213 | + |
| 214 | +Rooms could expose their safeness via a state event, similar to how this proposal does for account data. |
| 215 | +However, this would give administrators too much control over your own client experience. It would put the |
| 216 | +responsibility on safety on room administrators, who may lack the knowledge or time for proper room configuration. |
| 217 | + |
| 218 | +It also exposes another possible attack where users are invited to a room similar to a phishing attack, and the |
| 219 | +room state would override their personal safety settings to deliver undesirable content. |
| 220 | + |
| 221 | +### Trust users you share a DM with |
| 222 | + |
| 223 | +We could seek to trust media if we share a room with a user (e.g. the `m.direct`), which might be a cheap way to |
| 224 | +establish a basis of trust for users. |
| 225 | + |
| 226 | +### Blurring previews |
| 227 | + |
| 228 | +One suggestion would be to blur untrusted previews rather than keeping them as off. There are a few ways that this |
| 229 | +could be achieved, but each have downsides. |
| 230 | + |
| 231 | +1. Use [MSC2448](https://github.com/matrix-org/matrix-spec-proposals/pull/2448) client-side blurhashes. Would prevent |
| 232 | + downloading blocked media but the blurhash is attacker controlled, and can't be trusted for accuracy. |
| 233 | +2. Above, but receiver-side calculation. Would require downloading potentially offensive media to the client and is |
| 234 | + a non-starter for potentially dangerous content. |
| 235 | +3. Server-side generated previews. Does not work for encrypted rooms, and [were ripped out of MSC2448 anyway](https://github.com/matrix-org/matrix-spec-proposals/pull/2448#discussion_r1089753289) |
| 236 | + |
| 237 | +For the moment, hiding media entirely is a simpler and safer solution. |
| 238 | + |
| 239 | +## Security considerations |
| 240 | + |
| 241 | +This property is ultimately held by the homeserver, and a malicious homeserver may expose you to unwanted content. This is |
| 242 | +true today, and users should take caution with who they choose to host their account with. |
| 243 | + |
| 244 | +As with all account data properties, the content MUST be validated. |
| 245 | + |
| 246 | +## Unstable prefix |
| 247 | + |
| 248 | +The property MUST use `io.element.msc4278.media_preview_config` while the property is unstable. |
| 249 | + |
| 250 | +## Dependencies |
| 251 | + |
| 252 | +None. |
0 commit comments