From b2bead67ac8bc45de9a612578f295e5b7fc6c2b5 Mon Sep 17 00:00:00 2001 From: timedout Date: Sun, 21 Dec 2025 08:41:56 +0000 Subject: [PATCH] fix: Apply additional validation to invites --- src/api/server/invite.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/api/server/invite.rs b/src/api/server/invite.rs index ef2c8541..dac66a99 100644 --- a/src/api/server/invite.rs +++ b/src/api/server/invite.rs @@ -10,6 +10,7 @@ use conduwuit::{ use ruma::{ CanonicalJsonValue, OwnedUserId, UserId, api::{client::error::ErrorKind, federation::membership::create_invite}, + events::room::member::{MembershipState, RoomMemberEventContent}, serde::JsonObject, }; @@ -60,6 +61,36 @@ pub(crate) async fn create_invite_route( let mut signed_event = utils::to_canonical_object(&body.event) .map_err(|_| err!(Request(InvalidParam("Invite event is invalid."))))?; + // Ensure this is a membership event + if signed_event + .get("type") + .expect("event must have a type") + .as_str() + .expect("type must be a string") + != "m.room.member" + { + return Err!(Request(BadJson( + "Not allowed to send non-membership event to invite endpoint." + ))); + } + + let content: RoomMemberEventContent = serde_json::from_value( + signed_event + .get("content") + .ok_or_else(|| err!(Request(BadJson("Event missing content property"))))? + .clone() + .into(), + ) + .map_err(|e| err!(Request(BadJson(warn!("Event content is empty or invalid: {e}")))))?; + + // Ensure this is an invite membership event + if content.membership != MembershipState::Invite { + return Err!(Request(BadJson( + "Not allowed to send a non-invite membership event to invite endpoint." + ))); + } + + // Ensure the target user belongs to this server let recipient_user: OwnedUserId = signed_event .get("state_key") .try_into()