-
Notifications
You must be signed in to change notification settings - Fork 446
MSC4490: Surfacing room contacts when a join or knock does not succeed #4490
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
Open
ll-SKY-ll
wants to merge
4
commits into
matrix-org:main
Choose a base branch
from
ll-SKY-ll:Surfacing-room-support-contacts-on-failed-joins
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+159
−0
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
42bd977
Create xxx-surfacing_room_support_contacts_on_failed_joins.md
ll-SKY-ll 8ad226a
Update and rename xxx-surfacing_room_support_contacts_on_failed_joins…
ll-SKY-ll f63d47d
Update and rename xxx-surfacing_room_contacts_when_a_join_or_knock_do…
ll-SKY-ll 4aa0f74
Update 4490-surfacing_room_contacts_when_a_join_or_knock_does_not_suc…
ll-SKY-ll File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
proposals/4490-surfacing_room_contacts_when_a_join_or_knock_does_not_succeed.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| # MSC4490: Surfacing room contacts when a join or knock does not succeed | ||
|
|
||
| When a user's attempt to join or knock on a room is rejected — because they are | ||
| banned, because their server is denied, or for any other reason — they typically | ||
| see a generic message such as "You have been banned from this room" or "This | ||
| server is not permitted to join this room". They are given no path to contest | ||
| the decision, even when the room has explicitly published a contact for exactly | ||
| this purpose. | ||
|
|
||
| [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489) | ||
| introduces the `m.room.contact` state event, which lets a room advertise | ||
| responsible contacts. However, a user who is banned or whose server is blocked | ||
| generally cannot read room state, so they cannot read that event through normal | ||
| means. This proposal lets the resident server include the room's published | ||
| contact information in the rejection response, so the joining server can forward | ||
| it to the user's client for display. | ||
|
|
||
| ## Proposal | ||
|
|
||
| This builds on [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489) | ||
| and changes only the *delivery* of already-published information on a failed | ||
| join or knock; it introduces no new place for a room to declare contacts and | ||
| defines no new error conditions. | ||
|
|
||
| ### Federation response | ||
|
|
||
| When a resident server rejects a remote user's attempt to join or knock on a | ||
| room — at whichever point in the join or knock handshake the rejection is issued | ||
| (currently the `make_join`, `send_join`, `make_knock`, and `send_knock` | ||
| endpoints) — and that room has an `m.room.contact` state event with the empty | ||
| state key, the server MAY include the content of that event in the error | ||
| response under a dedicated `contact` key: | ||
|
|
||
| ```json | ||
| { | ||
| "errcode": "M_FORBIDDEN", | ||
| "error": "You are banned from this room", | ||
| "contact": { | ||
| "contacts": [ | ||
| { | ||
| "matrix_id": "@alice:example.org", | ||
| "email_address": "appeals@example.org", | ||
| "role": "m.role.admin" | ||
| } | ||
| ], | ||
| "support_page": "https://example.org/room-support-page" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The `contact` value, when present, MUST be the verbatim `content` of the room's | ||
| `m.room.contact` state event. This proposal adds only an OPTIONAL field to | ||
| existing rejection responses: it does not change the `errcode` or HTTP status | ||
| code of any response and introduces no new error conditions or error codes. A | ||
| server MAY omit the field (for example if the event is absent, or by policy), | ||
| and consumers MUST treat its absence as "no contact information available" | ||
| rather than as an error. | ||
|
|
||
| Because this only adds an optional field to error responses that are already | ||
| produced by the join and knock endpoints, it introduces no new authentication, | ||
| rate-limiting, or guest-access requirements on either the Server-Server or | ||
| Client-Server side, and no new request path. | ||
|
|
||
| ### Client-Server delivery | ||
|
|
||
| When a user's own server receives a federated join or knock rejection containing | ||
| `contact`, it SHOULD propagate that object to the client in the corresponding | ||
| Client-Server API error response (e.g. the response to | ||
| `POST /_matrix/client/v3/join/{roomIdOrAlias}`, | ||
| `/_matrix/client/v3/rooms/{roomId}/join`, or | ||
| `/_matrix/client/v3/knock/{roomIdOrAlias}`) under the same `contact` key. | ||
|
|
||
| For a purely local rejection (the user's own server is the resident server and | ||
| rejects the join or knock), the server MAY populate `contact` directly from | ||
| local room state using the same rules. | ||
|
|
||
| ### Client behaviour | ||
|
|
||
| A client that receives a rejection containing `contact` SHOULD, instead of (or | ||
| in addition to) the generic rejection message, present the contact information | ||
| so the user can seek help or appeal — for example, "You have been banned from | ||
| this room. To appeal, contact @alice:example.org or visit \<support_page\>." | ||
| Clients MUST apply the same security treatment defined in | ||
| [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489): the | ||
| data is an unverified claim by the room, contacts MUST NOT be shown as verified | ||
| identities, and `support_page` MUST be handled with the client's normal | ||
| untrusted-URL safety measures. | ||
|
|
||
| ## Potential issues | ||
|
|
||
| - **Information disclosure to rejected users.** This intentionally exposes the | ||
| contact event to a user who could not otherwise read room state. As the event | ||
| is explicitly intended to be reachable by people seeking to appeal — including | ||
| banned users — this is the desired behaviour. No other room state is exposed. | ||
| - **Server discretion causes inconsistency.** Because inclusion is OPTIONAL, | ||
| whether a rejected user sees contact info depends on the resident server's | ||
| implementation and policy. This is acceptable: the field is a best-effort | ||
| courtesy, and the fallback is exactly today's behaviour. | ||
|
|
||
| ## Alternatives | ||
|
|
||
| - **Require clients to fetch the event via a peek/`/state` request after a | ||
| failed join.** Rejected users generally cannot peek or read `/state`, so this | ||
| does not work for the banned/blocked case that motivates the proposal. | ||
| - **A dedicated "appeal info" endpoint keyed by room ID.** This adds a new | ||
| endpoint (with its own auth, rate-limiting, abuse, and enumeration concerns) | ||
| to deliver data the rejection response can already carry inline. Inlining is | ||
| simpler and leaks no more than the rejection itself. | ||
| - **Folding this into [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489).** | ||
| Kept separate deliberately so that the state event (useful to existing members | ||
| and in-room bots on its own) is not blocked | ||
| on federation and client changes. | ||
|
|
||
| ## Security considerations | ||
|
|
||
| In addition to the considerations inherited from | ||
| [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489) | ||
| (impersonation, email harvesting, `support_page` phishing, and the | ||
| no-authorisation-signal rule, all of which apply unchanged to the forwarded copy): | ||
|
|
||
| - **Disclosure scope.** The `contact` field MUST contain only the `content` of | ||
| the room's `m.room.contact` event; a resident server MUST NOT place any other | ||
| room state inside this field. The event's content is the only thing the room | ||
| has designated as publicly contactable. This says nothing about other fields | ||
| in the rejection response, which remain governed by their own definitions. | ||
| - **Spoofed rejection responses.** A malicious resident server could attach an | ||
| arbitrary `contact` object to a rejection, directing a rejected user's appeal | ||
| to an attacker-controlled address. This is bounded by the fact that the | ||
| resident server already controls the room's state and the rejection itself; a | ||
| user who does not trust the resident server has no stronger guarantee | ||
| elsewhere. Clients MUST therefore present the contact as room-supplied and | ||
| unverified. | ||
| - **Untrusted content handling.** The `contact` object is room-controlled | ||
| content delivered to a non-member, and a receiving server MUST treat it as | ||
| untrusted. It MUST apply the same size and validation limits it already | ||
| applies to the response in question, and MUST handle a malformed or oversized | ||
| object gracefully — dropping the field rather than failing the rejection it | ||
| accompanies. A resident server MAY decline to include the field for any | ||
| reason. | ||
|
|
||
| ## Unstable prefix | ||
|
|
||
| Until this proposal is accepted, the response field uses | ||
| `net.codestorm.msc4490.contact` (rather than the bare `contact`), in both the | ||
| Server-Server and Client-Server rejection responses: | ||
|
|
||
| | Proposed (this MSC) | Unstable form | | ||
| |----------------------------|---------------------------------| | ||
| | `contact` (response field) | `net.codestorm.msc4490.contact` | | ||
|
|
||
| The embedded object reuses the event content defined by | ||
| [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489) | ||
| and follows that proposal's own unstable-prefix rules for its inner fields. | ||
|
|
||
| ## Dependencies | ||
|
|
||
| This proposal depends on | ||
| [MSC4489](https://github.com/matrix-org/matrix-spec-proposals/pull/4489) | ||
| (`m.room.contact` state event), which MUST be accepted first. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation requirements: