From 33da7dcd9680c0e84da3fdc13557ba57b9ab018c Mon Sep 17 00:00:00 2001 From: Lambda Date: Fri, 4 Apr 2025 17:47:02 +0000 Subject: [PATCH] Check account data type match before storing to DB --- src/database/key_value/account_data.rs | 51 ++++++++++++++++++-------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/database/key_value/account_data.rs b/src/database/key_value/account_data.rs index 49231a2b..101986f8 100644 --- a/src/database/key_value/account_data.rs +++ b/src/database/key_value/account_data.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use ruma::{api::client::error::ErrorKind, RoomId, UserId}; use serde::Deserialize; use serde_json::value::RawValue; +use tracing::error; use crate::{ database::KeyValueDatabase, service, services, utils, Error, Result, @@ -16,16 +17,6 @@ impl service::account_data::Data for KeyValueDatabase { event_type: &str, data: &RawValue, ) -> Result<()> { - // Allowed because we just use this type to validate the schema, and - // don't read the fields. - #[allow(dead_code)] - #[derive(Deserialize)] - struct ExtractEventFields<'a> { - #[serde(rename = "type")] - event_type: &'a str, - content: &'a RawValue, - } - let mut prefix = room_id .map(ToString::to_string) .unwrap_or_default() @@ -44,11 +35,41 @@ impl service::account_data::Data for KeyValueDatabase { let mut key = prefix; key.extend_from_slice(event_type.as_bytes()); - if serde_json::from_str::>(data.get()).is_err() { - return Err(Error::BadRequest( - ErrorKind::InvalidParam, - "Account data doesn't have all required fields.", - )); + { + #[derive(Deserialize)] + struct ExtractEventFields<'a> { + #[serde(rename = "type")] + event_type: &'a str, + // Allowed because we just use this type to validate the schema + // and event type, and don't extract the content. + #[allow(dead_code)] + content: &'a RawValue, + } + + let Ok(ExtractEventFields { + event_type: serialised_event_type, + .. + }) = serde_json::from_str(data.get()) + else { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Account data doesn't have all required fields.", + )); + }; + + if serialised_event_type != event_type { + error!( + %user_id, + ?room_id, + event_type, + serialised_event_type, + "Mismatch between discrete and serialised account data event type" + ); + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Account data event type mismatch.", + )); + } } self.roomuserdataid_accountdata