From 700fbe472d4a8385b96f870256bfc00f9a15f809 Mon Sep 17 00:00:00 2001 From: Ginger Date: Tue, 11 Aug 2026 16:35:24 -0400 Subject: [PATCH] fix: SEC26 Reviewed-By: timedout Reviewed-By: Ginger --- changelog.d/SEC26.bugfix.md | 1 + src/api/server/event_auth.rs | 24 ++++++++++-------------- src/api/server/state.rs | 13 ++++++++++++- src/api/server/state_ids.rs | 13 ++++++++++++- 4 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 changelog.d/SEC26.bugfix.md diff --git a/changelog.d/SEC26.bugfix.md b/changelog.d/SEC26.bugfix.md new file mode 100644 index 000000000..5bde5ccdc --- /dev/null +++ b/changelog.d/SEC26.bugfix.md @@ -0,0 +1 @@ +Fixed a vulnerability that enabled the server to leak certain events over federation. Contributed by @eleboucher. diff --git a/src/api/server/event_auth.rs b/src/api/server/event_auth.rs index fd24cefd1..5cd49b834 100644 --- a/src/api/server/event_auth.rs +++ b/src/api/server/event_auth.rs @@ -1,9 +1,9 @@ use std::{borrow::Borrow, iter::once}; use axum::extract::State; -use conduwuit::{Err, Error, Result, err, info, utils::stream::ReadyExt}; +use conduwuit::{Err, Event, Result, info, utils::stream::ReadyExt}; use futures::StreamExt; -use ruma::{RoomId, api::federation::authorization::get_event_authorization}; +use ruma::api::federation::authorization::get_event_authorization; use super::AccessCheck; use crate::Ruma; @@ -48,25 +48,21 @@ pub(crate) async fn get_event_authorization_route( return Err!(Request(NotFound("This server is not participating in that room."))); } - let event = services + // The event must be in the room we just authorised access to + if !services .rooms .timeline - .get_pdu_json(&body.event_id) + .get_pdu(&body.event_id) .await - .map_err(|_| err!(Request(NotFound("Event not found."))))?; - - let room_id_str = event - .get("room_id") - .and_then(|val| val.as_str()) - .ok_or_else(|| Error::bad_database("Invalid event in database."))?; - - let room_id = <&RoomId>::try_from(room_id_str) - .map_err(|_| Error::bad_database("Invalid room_id in event in database."))?; + .is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id) + { + return Err!(Request(NotFound("Event not found."))); + } let auth_chain = services .rooms .auth_chain - .event_ids_iter(room_id, once(body.event_id.borrow())) + .event_ids_iter(&body.room_id, once(body.event_id.borrow())) .ready_filter_map(Result::ok) .filter_map(|id| async move { services.rooms.timeline.get_pdu_json(&id).await.ok() }) .then(|pdu| services.sending.convert_to_outgoing_federation_event(pdu)) diff --git a/src/api/server/state.rs b/src/api/server/state.rs index 90aa4253e..e2ba6a289 100644 --- a/src/api/server/state.rs +++ b/src/api/server/state.rs @@ -1,7 +1,7 @@ use std::{borrow::Borrow, iter::once}; use axum::extract::State; -use conduwuit::{Err, Result, at, err, info, utils::IterStream}; +use conduwuit::{Err, Event, Result, at, err, info, utils::IterStream}; use futures::{FutureExt, StreamExt, TryStreamExt}; use ruma::{OwnedEventId, api::federation::event::get_room_state}; @@ -24,6 +24,17 @@ pub(crate) async fn get_room_state_route( .assert() .await?; + // The event must be in the room we just authorised access to + if !services + .rooms + .timeline + .get_pdu(&body.event_id) + .await + .is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id) + { + return Err!(Request(NotFound("Event not found."))); + } + if services .rooms .pdu_metadata diff --git a/src/api/server/state_ids.rs b/src/api/server/state_ids.rs index 81fadb167..19b5cf609 100644 --- a/src/api/server/state_ids.rs +++ b/src/api/server/state_ids.rs @@ -1,7 +1,7 @@ use std::{borrow::Borrow, iter::once}; use axum::extract::State; -use conduwuit::{Err, Result, at, err, info}; +use conduwuit::{Err, Event, Result, at, err, info}; use futures::{StreamExt, TryStreamExt}; use ruma::{OwnedEventId, api::federation::event::get_room_state_ids}; @@ -25,6 +25,17 @@ pub(crate) async fn get_room_state_ids_route( .assert() .await?; + // The event must be in the room we just authorised access to + if !services + .rooms + .timeline + .get_pdu(&body.event_id) + .await + .is_ok_and(|pdu| pdu.room_id_or_hash() == body.room_id) + { + return Err!(Request(NotFound("Event not found."))); + } + if services .rooms .pdu_metadata