Skip to content
Merged
Show file tree
Hide file tree
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
5 changes: 3 additions & 2 deletions packages/federation-sdk/src/services/room.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,13 +784,14 @@ export class RoomService {

// if local room, add the user to the room if allowed.
// if remote room, run through the join process
async joinUser(roomId: RoomID, userId: UserID) {
async joinUser(invite: PersistentEventBase, userId: UserID) {
const configService = this.configService;
const stateService = this.stateService;
const federationService = this.federationService;
const roomId = invite.roomId;

// where the room is hosted at
const residentServer = extractDomainFromId(roomId);
const residentServer = extractDomainFromId(invite.sender);
Comment on lines +787 to +794
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate invite parameter and userId matching.

The method accepts an invite parameter but doesn't validate that it's a proper invite event. Consider adding validation to ensure:

  1. invite.type === 'm.room.member'
  2. invite.content.membership === 'invite'
  3. userId === invite.stateKey (to ensure we're joining the correct user)

Without these checks, the method could process invalid invites or join the wrong user.

Apply this diff to add validation at the beginning of the method:

 async joinUser(invite: PersistentEventBase, userId: UserID) {
+	// Validate that the invite is a proper invite event
+	if (invite.type !== 'm.room.member') {
+		throw new HttpException(
+			'Invalid invite: expected m.room.member event',
+			HttpStatus.BAD_REQUEST,
+		);
+	}
+	
+	if (invite.content.membership !== 'invite') {
+		throw new HttpException(
+			'Invalid invite: expected membership to be invite',
+			HttpStatus.BAD_REQUEST,
+		);
+	}
+	
+	if (invite.stateKey !== userId) {
+		throw new HttpException(
+			'Invalid invite: userId does not match invite state_key',
+			HttpStatus.BAD_REQUEST,
+		);
+	}
+
 	const configService = this.configService;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async joinUser(invite: PersistentEventBase, userId: UserID) {
const configService = this.configService;
const stateService = this.stateService;
const federationService = this.federationService;
const roomId = invite.roomId;
// where the room is hosted at
const residentServer = extractDomainFromId(roomId);
const residentServer = extractDomainFromId(invite.sender);
async joinUser(invite: PersistentEventBase, userId: UserID) {
// Validate that the invite is a proper invite event
if (invite.type !== 'm.room.member') {
throw new HttpException(
'Invalid invite: expected m.room.member event',
HttpStatus.BAD_REQUEST,
);
}
if (invite.content.membership !== 'invite') {
throw new HttpException(
'Invalid invite: expected membership to be invite',
HttpStatus.BAD_REQUEST,
);
}
if (invite.stateKey !== userId) {
throw new HttpException(
'Invalid invite: userId does not match invite state_key',
HttpStatus.BAD_REQUEST,
);
}
const configService = this.configService;
const stateService = this.stateService;
const federationService = this.federationService;
const roomId = invite.roomId;
// where the room is hosted at
const residentServer = extractDomainFromId(invite.sender);
🤖 Prompt for AI Agents
In packages/federation-sdk/src/services/room.service.ts around lines 787 to 794,
the joinUser method does not validate the invite parameter or ensure the target
user matches the invite; add checks to verify invite.type === 'm.room.member',
invite.content?.membership === 'invite', and that the provided userId equals
invite.stateKey. If any check fails, throw or return an early error (e.g., throw
new Error or return a rejected promise) with a clear message indicating which
validation failed; perform these validations before extracting residentServer or
proceeding with any join logic.


// our own room, we can validate the join event by ourselves
// once done, emit the event to all participating servers
Expand Down
27 changes: 0 additions & 27 deletions packages/homeserver/src/controllers/internal/room.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,33 +168,6 @@ export const internalRoomPlugin = (app: Elysia) => {
},
},
)
.put(
'/internal/rooms/:roomId/join/:userId',
async ({ params }) => {
const { roomId, userId } = params;

const eventId = await roomService.joinUser(
roomId as RoomID,
userId as UserID,
);

return {
eventId,
};
},
{
// params: InternalJoinRoomParamsDto,
// response: {
// 200: InternalRoomEventResponseDto,
// 400: ErrorResponseDto,
// },
detail: {
tags: ['Internal'],
summary: 'Join a room',
description: 'Join a room',
},
},
)
.get(
'/internal/rooms/:roomId/state',
async ({ params, query }) => {
Expand Down