diff --git a/CHANGELOG.md b/CHANGELOG.md index a85a1952b..2e8a1b674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - Auto accept contact requests if `Config::Bot` is set for a client #3567 - Don't prepend the subject to chat messages in mailinglists - fix `set_core_version.py` script to also update version in `deltachat-jsonrpc/typescript/package.json` #3585 +- Reject webxcd-updates from contacts who are not group members #3568 ## 1.93.0 diff --git a/src/webxdc.rs b/src/webxdc.rs index 2f2cbc73c..d812bf501 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -489,6 +489,12 @@ impl Context { bail!("receive_status_update: status message has no parent.") }; + if from_id != ContactId::SELF + && !chat::is_contact_in_chat(self, instance.chat_id, from_id).await? + { + bail!("receive_status_update: status sender not chat member.") + } + let updates: StatusUpdates = serde_json::from_str(json)?; for update_item in updates.updates { self.create_status_update_record( @@ -741,8 +747,8 @@ impl Message { #[cfg(test)] mod tests { use crate::chat::{ - add_contact_to_chat, create_broadcast_list, create_group_chat, forward_msgs, resend_msgs, - send_msg, send_text_msg, ChatId, ProtectionStatus, + add_contact_to_chat, create_broadcast_list, create_group_chat, forward_msgs, + remove_contact_from_chat, resend_msgs, send_msg, send_text_msg, ChatId, ProtectionStatus, }; use crate::chatlist::Chatlist; use crate::config::Config; @@ -2317,4 +2323,58 @@ sth_for_the = "future""# Ok(()) } + + async fn helper_send_receive_status_update( + bob: &TestContext, + alice: &TestContext, + bob_instance: &Message, + alice_instance: &Message, + ) -> Result { + bob.send_webxdc_status_update( + bob_instance.id, + r#"{"payload":7,"info": "i","summary":"s"}"#, + "", + ) + .await?; + bob.flush_status_updates().await?; + let msg = bob.pop_sent_msg().await; + alice.recv_msg(&msg).await; + alice + .get_webxdc_status_updates(alice_instance.id, StatusUpdateSerial(0)) + .await + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_webxdc_reject_updates_from_non_groupmembers() -> Result<()> { + let alice = TestContext::new_alice().await; + let bob = TestContext::new_bob().await; + let contact_bob = Contact::create(&alice, "Bob", "bob@example.net").await?; + let chat_id = create_group_chat(&alice, ProtectionStatus::Unprotected, "Group").await?; + add_contact_to_chat(&alice, chat_id, contact_bob).await?; + let instance = send_webxdc_instance(&alice, chat_id).await?; + bob.recv_msg(&alice.pop_sent_msg().await).await; + let bob_instance = bob.get_last_msg().await; + Chat::load_from_db(&bob, bob_instance.chat_id) + .await? + .id + .accept(&bob) + .await?; + + let status = + helper_send_receive_status_update(&bob, &alice, &bob_instance, &instance).await?; + assert_eq!( + status, + r#"[{"payload":7,"info":"i","summary":"s","serial":1,"max_serial":1}]"# + ); + + remove_contact_from_chat(&alice, chat_id, contact_bob).await?; + let status = + helper_send_receive_status_update(&bob, &alice, &bob_instance, &instance).await?; + + assert_eq!( + status, + r#"[{"payload":7,"info":"i","summary":"s","serial":1,"max_serial":1}]"# + ); + Ok(()) + } }