Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions packages/federation-sdk/src/services/invite.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,12 @@ export class InviteService {
| 'm.room.encryption'
>[],
): Promise<void> {
const isRoomNonPrivate = strippedStateEvents.some(
(stateEvent) =>
stateEvent.type === 'm.room.join_rules' &&
stateEvent.content.join_rule === 'public',
const joinRuleEvent = strippedStateEvents.find(
(stateEvent) => stateEvent.type === 'm.room.join_rules',
);
const isRoomNonPrivate = joinRuleEvent
? joinRuleEvent.content.join_rule === 'public'
: true /* default, if no event */;
Comment on lines +163 to +168
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reconsider the default value for isRoomNonPrivate.

When no m.room.join_rules event is found, the code defaults isRoomNonPrivate to true, treating the room as public/non-private. This appears inconsistent with the Matrix specification, which typically defaults join_rules to "invite" (private) when not explicitly set. Defaulting to true here could bypass privacy restrictions configured via allowedNonPrivateRooms, potentially allowing invites to private rooms that should be rejected.

Consider this safer default:

 const joinRuleEvent = strippedStateEvents.find(
   (stateEvent) => stateEvent.type === 'm.room.join_rules',
 );
 const isRoomNonPrivate = joinRuleEvent
   ? joinRuleEvent.content.join_rule === 'public'
-  : true /* default, if no event */;
+  : false /* default to private/invite per Matrix spec */;
🤖 Prompt for AI Agents
In packages/federation-sdk/src/services/invite.service.ts around lines 163 to
168, the code currently treats a missing m.room.join_rules event as public
(isRoomNonPrivate = true); change this to treat a missing join_rules as private
(default to invite) by setting the default to false so that absence of the event
is handled as "invite"/private; update the ternary (or conditional) and any
accompanying comment to reflect the safer default and ensure downstream checks
(e.g., allowedNonPrivateRooms) continue to behave correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@debdutdeb what do you think about this one?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const isRoomEncrypted = strippedStateEvents.some(
(stateEvent) => stateEvent.type === 'm.room.encryption',
Expand Down Expand Up @@ -199,6 +200,13 @@ export class InviteService {
| 'm.room.encryption'
>[],
) {
// SPEC: An optional list of stripped state events to help the receiver of the invite identify the room.
// https://spec.matrix.org/v1.12/server-server-api/#put_matrixfederationv1inviteroomideventid
if (strippedStateEvents.length === 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we validate this only if we have configured restrictions? like if we don't restrict anything we won't use the stripped state anyways

throw new NotAllowedError(
'Invite has no room state, disallowing processing',
);
}
// SPEC: when a user invites another user on a different homeserver, a request to that homeserver to have the event signed and verified must be made
await this.shouldProcessInvite(strippedStateEvents);

Expand Down