From 1cafc1657fbf75bc9265c34c64b00cdfba3cbaa8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 27 May 2025 15:48:37 -0600 Subject: [PATCH 1/5] MSC: Redact on ban --- proposals/4293-redact-on-ban.md | 103 ++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 proposals/4293-redact-on-ban.md diff --git a/proposals/4293-redact-on-ban.md b/proposals/4293-redact-on-ban.md new file mode 100644 index 00000000000..b0f2876d509 --- /dev/null +++ b/proposals/4293-redact-on-ban.md @@ -0,0 +1,103 @@ +# MSC4293: Redact on ban + +[MSC2244 (accepted)](https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/2244-mass-redactions.md)-style +mass redactions are incredibly helpful for cleaning up large volumes of spam, but still require sending +a dedicated event to clean up the spam. In a typical case, a user will get kicked/banned from a room +and the moderators will further redact some or all of their messages. Mass redactions have more use +cases, but the specific case of "redact everything upon ban" is something which may be easily backported +to existing room versions. + +This proposal suggests adding a new flag to membership events to indicate to clients and servers that +all of that user's events should be redacted in addition to being kicked or banned. The flag isn't +protected from redaction itself, so may have some consistency issues, but overall should still provide +relatively high amounts of protection to rooms. + +This proposal is exploratory and subject to change. Implementations may validate the idea through +early feature support, but MUST expect that things will change (or become completely rejected). + +## Proposal + +A new flag is added to [`m.room.member`](https://spec.matrix.org/v1.14/client-server-api/#mroommember) +events where the target user is kicked or banned (**TODO**: Allow on self-leaves too?): `redact_events`. +This flag is a boolean and, when `true`, causes servers (and clients) to redact all of the user's events +as though they received an [`m.room.redaction`](https://spec.matrix.org/v1.14/client-server-api/#mroomredaction), +including adding [`redacted_because`](https://spec.matrix.org/v1.14/client-server-api/#redactions) to +`unsigned` where applicable. + +**Note**: This also means that if the user was kicked/banned with a `reason`, that event is automatically +compatible with the redaction `reason` field and shows up accordingly. + +This redaction behaviour continues until the membership event itself is redacted (thus removing the +field) or another membership event removes the field. For example, if the user is unbanned, the moderator +MAY NOT choose to carry the `redact_events` flag to that kick (unban) event. Or, when the user rejoins +after a kick, the flag is implicitly dropped. + +Other membership states with the flag no-op, such as joins. + +Moderation bots and similar MAY still wish to issue (mass) redactions upon kick/ban to protect users +on servers or clients which don't have this feature. + +Example ban: + +```jsonc +{ + // Irrelevant fields excluded + "type": "m.room.member", + "state_key": "@spam:example.org", + "sender": "@mod:example.org", + "content": { + "membership": "ban", + "reason": "flooding", // this is copied to `redacted_because`, leading to clients showing it + "redact_events": true + } +} +``` + +The new field is proxied through to the event by the [`/kick`](https://spec.matrix.org/v1.14/client-server-api/#post_matrixclientv3roomsroomidkick) +and [`/ban`](https://spec.matrix.org/v1.14/client-server-api/#post_matrixclientv3roomsroomidban) +sugar APIs, like `reason` is. + +## Potential issues + +It's a little annoying that the flag is redacted when the membership event is redacted, however it's +extremely rare for a moderator/admin to redact a kick or ban event. We can fix this in a room version +trivially if it proves to be an issue. + +Clients may miss the membership event if they are using lazy loading, though servers should already +be tracking which membership events the client has received and needs to render events in the timeline. +This should mean that those clients will still receive the event. + +Servers which miss the event will eventually receive or retrieve it, just like they would with any +other event. + +## Alternatives + +Mass redactions are the cited major alternative, where a single event can target approximately 1500 +other events in the room. New rooms can benefit from that functionality, especially for cases not +covered by this proposal, while existing rooms can be given an option to protect their users with +relative ease. + +## Security considerations + +As the room moderator/administrator would already send redactions, and may still for full protection, +it's not deemed any more risk than today. This may change if self-leaves are permitted to also carry +the field. + +There may also be implementation or reliability bugs which inhibit the "stop redacting now" point +from working as intended. Server implementations in particular should ensure that an event received +after a membership event which asks for redaction is *really* affected by that redaction. ie: whether +it's just a late delivery, or if there's a join waiting for state res to make a determination. + + +## Unstable prefix + +While this proposal is not considered stable, implementations should use `org.matrix.msc4293.redact_events` +instead of `redact_events`. + +## Dependencies + +This MSC has no direct dependencies. + +## Credits + +Credit goes to Erik of the Spec Core Team for the suggestion to look into this. From b9391a028b3ba199a20c52a0b262f18650430a8f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 10 Jun 2025 17:18:56 -0600 Subject: [PATCH 2/5] Add some clarity --- proposals/4293-redact-on-ban.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/proposals/4293-redact-on-ban.md b/proposals/4293-redact-on-ban.md index b0f2876d509..f5d8941761d 100644 --- a/proposals/4293-redact-on-ban.md +++ b/proposals/4293-redact-on-ban.md @@ -22,17 +22,27 @@ events where the target user is kicked or banned (**TODO**: Allow on self-leaves This flag is a boolean and, when `true`, causes servers (and clients) to redact all of the user's events as though they received an [`m.room.redaction`](https://spec.matrix.org/v1.14/client-server-api/#mroomredaction), including adding [`redacted_because`](https://spec.matrix.org/v1.14/client-server-api/#redactions) to -`unsigned` where applicable. +`unsigned` where applicable. An `m.room.redaction` event is not actually sent, however. **Note**: This also means that if the user was kicked/banned with a `reason`, that event is automatically compatible with the redaction `reason` field and shows up accordingly. -This redaction behaviour continues until the membership event itself is redacted (thus removing the -field) or another membership event removes the field. For example, if the user is unbanned, the moderator -MAY NOT choose to carry the `redact_events` flag to that kick (unban) event. Or, when the user rejoins -after a kick, the flag is implicitly dropped. +Similar to regular redactions, if the sender of the membership event can't actually redact the target's +events, the redaction doesn't apply. This means having a power level higher than or equal to `redacts` +*and* `events["m.room.redaction"]` (if set). Normally, `m.room.redaction` events could be rejected +due to the power levels - that rejection behaviour doesn't apply with the `redact_events` field. +Instead, the target's events are simply not redacted. -Other membership states with the flag no-op, such as joins. +If the sender is allowed to redact, the redaction behaviour continues until the membership event itself +is redacted (thus removing the field) or another membership event removes the field. For example, if +the user is unbanned, the moderator MAY NOT choose to carry the `redact_events` flag to that kick +(unban) event. Or, when the user rejoins after a kick, the flag is implicitly dropped. + +Events which are delivered after the ban are likely [soft failed](https://spec.matrix.org/v1.14/server-server-api/#soft-failure) +and are still redacted if the current membership event in the room has a valid `redact_events` +field. + +Other membership states with the flag no-op, such as joins, knocks, and invites. Moderation bots and similar MAY still wish to issue (mass) redactions upon kick/ban to protect users on servers or clients which don't have this feature. @@ -60,8 +70,13 @@ sugar APIs, like `reason` is. ## Potential issues It's a little annoying that the flag is redacted when the membership event is redacted, however it's -extremely rare for a moderator/admin to redact a kick or ban event. We can fix this in a room version -trivially if it proves to be an issue. +extremely rare for a moderator/admin to redact a kick or ban event. This can be fixed in a future +room version, like what is proposed by [MSC4298](https://github.com/matrix-org/matrix-spec-proposals/pull/4298). + +Though extremely rare, if an existing server in the room didn't apply the redactions *and* a sender's +ban was redacted, a new server to the room may backfill through that existing server and see unredacted +events without knowing it's supposed to redact them due to the ban having lost the `redact_events` +field. This is fixed for future room versions by implementing something like [MSC4298](https://github.com/matrix-org/matrix-spec-proposals/pull/4298). Clients may miss the membership event if they are using lazy loading, though servers should already be tracking which membership events the client has received and needs to render events in the timeline. @@ -88,7 +103,6 @@ from working as intended. Server implementations in particular should ensure tha after a membership event which asks for redaction is *really* affected by that redaction. ie: whether it's just a late delivery, or if there's a join waiting for state res to make a determination. - ## Unstable prefix While this proposal is not considered stable, implementations should use `org.matrix.msc4293.redact_events` From 6d92bbaa5b024c869b25fdf8355ed92bc85b36c3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 20 Jun 2025 17:55:04 -0600 Subject: [PATCH 3/5] Add more considerations --- proposals/4293-redact-on-ban.md | 53 ++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/proposals/4293-redact-on-ban.md b/proposals/4293-redact-on-ban.md index f5d8941761d..384e2973fa3 100644 --- a/proposals/4293-redact-on-ban.md +++ b/proposals/4293-redact-on-ban.md @@ -12,26 +12,23 @@ all of that user's events should be redacted in addition to being kicked or bann protected from redaction itself, so may have some consistency issues, but overall should still provide relatively high amounts of protection to rooms. -This proposal is exploratory and subject to change. Implementations may validate the idea through -early feature support, but MUST expect that things will change (or become completely rejected). - ## Proposal A new flag is added to [`m.room.member`](https://spec.matrix.org/v1.14/client-server-api/#mroommember) -events where the target user is kicked or banned (**TODO**: Allow on self-leaves too?): `redact_events`. -This flag is a boolean and, when `true`, causes servers (and clients) to redact all of the user's events -as though they received an [`m.room.redaction`](https://spec.matrix.org/v1.14/client-server-api/#mroomredaction), -including adding [`redacted_because`](https://spec.matrix.org/v1.14/client-server-api/#redactions) to -`unsigned` where applicable. An `m.room.redaction` event is not actually sent, however. +events where the target user is kicked or banned: `redact_events`. This flag is a boolean and, when +`true`, causes servers (and clients) to redact all of the user's events as though they received an +[`m.room.redaction`](https://spec.matrix.org/v1.14/client-server-api/#mroomredaction), including +adding [`redacted_because`](https://spec.matrix.org/v1.14/client-server-api/#redactions) to `unsigned` +where applicable. An `m.room.redaction` event is not actually sent, however. **Note**: This also means that if the user was kicked/banned with a `reason`, that event is automatically compatible with the redaction `reason` field and shows up accordingly. Similar to regular redactions, if the sender of the membership event can't actually redact the target's events, the redaction doesn't apply. This means having a power level higher than or equal to `redacts` -*and* `events["m.room.redaction"]` (if set). Normally, `m.room.redaction` events could be rejected -due to the power levels - that rejection behaviour doesn't apply with the `redact_events` field. -Instead, the target's events are simply not redacted. +*and* `events["m.room.redaction"]` (if set). We maintain the `events` check despite not actually sending +events of that type to keep the same expectations within rooms. If the sender doesn't have permission +to redact an event normally, no redaction is applied. If the sender is allowed to redact, the redaction behaviour continues until the membership event itself is redacted (thus removing the field) or another membership event removes the field. For example, if @@ -67,6 +64,28 @@ The new field is proxied through to the event by the [`/kick`](https://spec.matr and [`/ban`](https://spec.matrix.org/v1.14/client-server-api/#post_matrixclientv3roomsroomidban) sugar APIs, like `reason` is. +## Fallback behaviour + +Servers which don't support this feature may be served redacted events over federation when attempting +to fill gaps or backfill. This is considered expected behaviour. + +Clients which don't support this feature may see events remain unredacted until they clear their local +cache. Upon clearing or invalidating their cache, they will either receive redacted events if their +server supports the feature or unredacted events otherwise. + +To (primarily) help protect users on unsupported *clients*, implementations SHOULD continue to try +sending individual redaction events in addition to the redact-on-ban flag. They MAY cease to do so +once they are comfortable with the level of adoption for this proposal. Servers in particular SHOULD +assist clients and send individual redaction events on their behalf, meaning clients SHOULD wait a +little bit before trying to issue redactions themselves. For example, a client may ban a user, wait +a minute, then start sending redactions if it hasn't seen an `m.room.redaction` event targeting some +of the banned user's events. Servers MAY deduplicate redactions to lower federation load, as they +always could. + +**Note**: It is possible due to implementation and real-world constraints that not all individual +redactions will "make it" over federation to another server. This is why mass redaction approaches +are preferred, as they are significantly more reliable. + ## Potential issues It's a little annoying that the flag is redacted when the membership event is redacted, however it's @@ -85,6 +104,11 @@ This should mean that those clients will still receive the event. Servers which miss the event will eventually receive or retrieve it, just like they would with any other event. +Moderation bots/clients which attempt to reduce the amount of duplicate work they do may need to +inspect `redacted_because` instead of checking for its presence to determine which kind of redaction +was applied to a given event. This is especially true if the moderation bot/client is providing the +fallback support described above. + ## Alternatives Mass redactions are the cited major alternative, where a single event can target approximately 1500 @@ -92,6 +116,13 @@ other events in the room. New rooms can benefit from that functionality, especia covered by this proposal, while existing rooms can be given an option to protect their users with relative ease. +## Future considerations + +It may be desirable to place this behaviour on self-leaves too, allowing for faster removal of one's +own messages/events. This proposal doesn't suggest adding this functionality here to maintain narrow +scope on T&S functionality. A future proposal may introduce this, or rely on regular mass redactions +instead. + ## Security considerations As the room moderator/administrator would already send redactions, and may still for full protection, From 687db4ccfc6e2dae07a7f34b6d9f76e2ec756f0f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 26 Jun 2025 13:45:04 -0600 Subject: [PATCH 4/5] Misc clarifications --- proposals/4293-redact-on-ban.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/proposals/4293-redact-on-ban.md b/proposals/4293-redact-on-ban.md index 384e2973fa3..b9093f126e3 100644 --- a/proposals/4293-redact-on-ban.md +++ b/proposals/4293-redact-on-ban.md @@ -31,9 +31,13 @@ events of that type to keep the same expectations within rooms. If the sender do to redact an event normally, no redaction is applied. If the sender is allowed to redact, the redaction behaviour continues until the membership event itself -is redacted (thus removing the field) or another membership event removes the field. For example, if -the user is unbanned, the moderator MAY NOT choose to carry the `redact_events` flag to that kick -(unban) event. Or, when the user rejoins after a kick, the flag is implicitly dropped. +is redacted (thus removing the field), another membership event removes the field, or the flag is set +to `false`. Events already redacted up to that point remain redacted after the flag changes to a falsey +value. For example, if the user is unbanned, the moderator MAY NOT choose to carry the `redact_events` +flag to that kick (unban) event. Or, when the user rejoins after a kick, the flag is implicitly dropped. + +In essence, the `redact_events` flag applies to all events which topologically come before the falsey +value. Events which are delivered after the ban are likely [soft failed](https://spec.matrix.org/v1.14/server-server-api/#soft-failure) and are still redacted if the current membership event in the room has a valid `redact_events` @@ -109,6 +113,21 @@ inspect `redacted_because` instead of checking for its presence to determine whi was applied to a given event. This is especially true if the moderation bot/client is providing the fallback support described above. +If a user is banned using `redact_events: true`, unbanned, rejoins, sends more events, and is banned +again using `redact_events: true`, the user's events between bans will be subsequently redacted. The +events redacted by the first ban may also be re-redacted by servers/clients depending on implementation. +This is considered expected behaviour, and implementations can internally track which events they've +already auto-redacted to avoid duplicate work. + +With respect to the fallback behaviour, a client might not know if a server is applying fallback +redactions and may not wish to wait an arbitrary amount of time to see if it does. One solution would +be to have the server expose a [capability](https://spec.matrix.org/v1.15/client-server-api/#capabilities-negotiation), +however such a flag would be longer lived than the fallback behaviour itself (hopefully). Instead, +clients which don't implement watchdog functionality SHOULD send redactions anyway, even if it +duplicates the server's fallback efforts. Further, as already mentioned above, server MAY deduplicate +redactions to lower their federation load, though this is closer to a SHOULD considering clients are +already sending their own redaction events (like in the case of Mjolnir). + ## Alternatives Mass redactions are the cited major alternative, where a single event can target approximately 1500 From aabe7518cc96cd14fbf68dda7de12ab5077e993f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 11 Jul 2025 15:40:12 -0600 Subject: [PATCH 5/5] Update proposals/4293-redact-on-ban.md Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> --- proposals/4293-redact-on-ban.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/4293-redact-on-ban.md b/proposals/4293-redact-on-ban.md index b9093f126e3..eb25667e566 100644 --- a/proposals/4293-redact-on-ban.md +++ b/proposals/4293-redact-on-ban.md @@ -25,7 +25,7 @@ where applicable. An `m.room.redaction` event is not actually sent, however. compatible with the redaction `reason` field and shows up accordingly. Similar to regular redactions, if the sender of the membership event can't actually redact the target's -events, the redaction doesn't apply. This means having a power level higher than or equal to `redacts` +events, the redaction doesn't apply. This means having a power level higher than or equal to `redact` *and* `events["m.room.redaction"]` (if set). We maintain the `events` check despite not actually sending events of that type to keep the same expectations within rooms. If the sender doesn't have permission to redact an event normally, no redaction is applied.