From 904210f3168a9ec6f499351b8415c90f02d0c08c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 04:37:39 +0000 Subject: [PATCH] fix(security): sanitize user inputs rendered as HTML Sanitizes filenames in file, video, and audio media types as well as display_name and user_id in invited room previews before passing them to the html rendering engine to prevent XSS vulnerabilities. Co-authored-by: kevinaboos <1139460+kevinaboos@users.noreply.github.com> --- src/home/room_screen.rs | 6 +++--- src/home/rooms_list_entry.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index dc42a462..0b163415 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -3784,7 +3784,7 @@ fn populate_file_message_content( file_content: &FileMessageEventContent, ) -> bool { // Display the file name, human-readable size, caption, and a button to download it. - let filename = file_content.filename(); + let filename = htmlize::escape_text(file_content.filename()); let size = file_content .info .as_ref() @@ -3814,7 +3814,7 @@ fn populate_audio_message_content( audio: &AudioMessageEventContent, ) -> bool { // Display the file name, human-readable size, caption, and a button to download it. - let filename = audio.filename(); + let filename = htmlize::escape_text(audio.filename()); let (duration, mime, size) = audio .info .as_ref() @@ -3855,7 +3855,7 @@ fn populate_video_message_content( video: &VideoMessageEventContent, ) -> bool { // Display the file name, human-readable size, caption, and a button to download it. - let filename = video.filename(); + let filename = htmlize::escape_text(video.filename()); let (duration, mime, size, dimensions) = video .info .as_ref() diff --git a/src/home/rooms_list_entry.rs b/src/home/rooms_list_entry.rs index 093c1680..dbe78fd3 100644 --- a/src/home/rooms_list_entry.rs +++ b/src/home/rooms_list_entry.rs @@ -348,8 +348,8 @@ impl RoomsListEntryContent { // Hide the timestamp field, and use the latest message field to show the inviter. self.view.label(ids!(timestamp)).set_text(cx, ""); let inviter_string = match &room_info.inviter_info { - Some(InviterInfo { user_id, display_name: Some(dn), .. }) => format!("Invited by {dn} ({user_id})"), - Some(InviterInfo { user_id, .. }) => format!("Invited by {user_id}"), + Some(InviterInfo { user_id, display_name: Some(dn), .. }) => format!("Invited by {} ({})", htmlize::escape_text(dn), htmlize::escape_text(user_id.as_str())), + Some(InviterInfo { user_id, .. }) => format!("Invited by {}", htmlize::escape_text(user_id.as_str())), None => String::from("You were invited"), }; self.view.html_or_plaintext(ids!(latest_message)).show_html(cx, &inviter_string);