]> Untitled Git - lemmy.git/commitdiff
Forbid remote URLs for avatars/banners (fixes #1618) (#2132)
authorNutomic <me@nutomic.com>
Fri, 18 Mar 2022 15:46:58 +0000 (15:46 +0000)
committerGitHub <noreply@github.com>
Fri, 18 Mar 2022 15:46:58 +0000 (15:46 +0000)
api_tests/src/shared.ts
crates/api/src/local_user.rs
crates/api_common/src/lib.rs
crates/api_crud/src/community/create.rs
crates/api_crud/src/community/update.rs
crates/api_crud/src/site/create.rs
crates/api_crud/src/site/update.rs
crates/apub/src/objects/instance.rs
crates/apub/src/objects/mod.rs
crates/apub/src/objects/person.rs
crates/apub/src/protocol/objects/group.rs

index 8c4e08ff4f717cc60bf507ed18383e2a1696acda..da606b1fab935c53a8121655e5771c0438bd4f78 100644 (file)
@@ -427,14 +427,10 @@ export async function createCommunity(
   name_: string = randomString(5)
 ): Promise<CommunityResponse> {
   let description = 'a sample description';
-  let icon = 'https://image.flaticon.com/icons/png/512/35/35896.png';
-  let banner = 'https://image.flaticon.com/icons/png/512/35/35896.png';
   let form: CreateCommunity = {
     name: name_,
     title: name_,
     description,
-    icon,
-    banner,
     nsfw: false,
     auth: api.auth,
   };
index 01ab2ed982980f60070affc4b1edc935e27a0c74..0b2a4c3aa1bf4c05426e51dda7e7702d28bb30b6 100644 (file)
@@ -5,6 +5,7 @@ use captcha::{gen, Difficulty};
 use chrono::Duration;
 use lemmy_api_common::{
   blocking,
+  check_image_has_local_domain,
   check_registration_application,
   get_local_user_view_from_jwt,
   is_admin,
@@ -175,6 +176,9 @@ impl Perform for SaveUserSettings {
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
+    check_image_has_local_domain(&data.avatar)?;
+    check_image_has_local_domain(&data.banner)?;
+
     let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
     let banner = diesel_option_overwrite_to_url(&data.banner)?;
     let bio = diesel_option_overwrite(&data.bio);
index 59bbae0539b0aead1b277d3c335b30a1ce9e311c..a95365e9e89ec1a23d8a052e23014f6a4fc5b698 100644 (file)
@@ -40,6 +40,7 @@ use lemmy_utils::{
   LemmyError,
   Sensitive,
 };
+use url::Url;
 
 pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
 where
@@ -623,3 +624,15 @@ pub async fn remove_user_data_in_community(
 
   Ok(())
 }
+
+pub fn check_image_has_local_domain(url: &Option<String>) -> Result<(), LemmyError> {
+  if let Some(url) = url {
+    let settings = Settings::get();
+    let url = Url::parse(url)?;
+    let domain = url.domain().expect("url has domain");
+    if domain != settings.hostname {
+      return Err(LemmyError::from_message("image_not_local"));
+    }
+  }
+  Ok(())
+}
index 71e404d33599ed16e49e1d8278af6b4b6191ced6..c76fe430d68051cf605888deaa992cee384b9ae7 100644 (file)
@@ -2,6 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   blocking,
+  check_image_has_local_domain,
   community::{CommunityResponse, CreateCommunity},
   get_local_user_view_from_jwt,
   is_admin,
@@ -63,6 +64,8 @@ impl PerformCrud for CreateCommunity {
     check_slurs(&data.name, &context.settings().slur_regex())?;
     check_slurs(&data.title, &context.settings().slur_regex())?;
     check_slurs_opt(&data.description, &context.settings().slur_regex())?;
+    check_image_has_local_domain(&data.icon)?;
+    check_image_has_local_domain(&data.banner)?;
 
     if !is_valid_actor_name(&data.name, context.settings().actor_name_max_length) {
       return Err(LemmyError::from_message("invalid_community_name"));
index b7352a62408837a8f50e66198f7e20bbeed984e8..f2a0c94c217e868e270fc63e38ea7cddb2b9f445 100644 (file)
@@ -2,6 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   blocking,
+  check_image_has_local_domain,
   community::{CommunityResponse, EditCommunity, HideCommunity},
   get_local_user_view_from_jwt,
   is_admin,
@@ -37,6 +38,8 @@ impl PerformCrud for EditCommunity {
 
     check_slurs_opt(&data.title, &context.settings().slur_regex())?;
     check_slurs_opt(&data.description, &context.settings().slur_regex())?;
+    check_image_has_local_domain(&data.icon)?;
+    check_image_has_local_domain(&data.banner)?;
 
     // Verify its a mod (only mods can edit it)
     let community_id = data.community_id;
index ddb4f0a0c3b8e9f2953b9afc5a445c493d4ac215..a38f211d8fe5640fe5a0c2428367e5e6178dd49a 100644 (file)
@@ -2,6 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   blocking,
+  check_image_has_local_domain,
   get_local_user_view_from_jwt,
   is_admin,
   site::*,
@@ -49,6 +50,8 @@ impl PerformCrud for CreateSite {
 
     check_slurs(&data.name, &context.settings().slur_regex())?;
     check_slurs_opt(&data.description, &context.settings().slur_regex())?;
+    check_image_has_local_domain(&data.icon)?;
+    check_image_has_local_domain(&data.banner)?;
 
     // Make sure user is an admin
     is_admin(&local_user_view)?;
index 4e987de9d6af62769b0384659ca956c3322dcbfd..11a23f268e6331a3f8a77df1aa4614a8d3c73c5f 100644 (file)
@@ -2,6 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   blocking,
+  check_image_has_local_domain,
   get_local_user_view_from_jwt,
   is_admin,
   site::{EditSite, SiteResponse},
@@ -38,6 +39,8 @@ impl PerformCrud for EditSite {
 
     check_slurs_opt(&data.name, &context.settings().slur_regex())?;
     check_slurs_opt(&data.description, &context.settings().slur_regex())?;
+    check_image_has_local_domain(&data.icon)?;
+    check_image_has_local_domain(&data.banner)?;
 
     // Make sure user is an admin
     is_admin(&local_user_view)?;
index a07ecdc17f2eaac6f12d6101abfb56a95cd27fa1..f12696c49e2660c5b5800b8a0e88aaea80459ef4 100644 (file)
@@ -1,6 +1,6 @@
 use crate::{
   check_is_apub_id_valid,
-  objects::get_summary_from_string_or_source,
+  objects::{get_summary_from_string_or_source, verify_image_domain_matches},
   protocol::{objects::instance::Instance, ImageObject, Source},
 };
 use activitystreams_kinds::actor::ServiceType;
@@ -103,6 +103,8 @@ impl ApubObject for ApubSite {
   ) -> Result<(), LemmyError> {
     check_is_apub_id_valid(apub.id.inner(), true, &data.settings())?;
     verify_domains_match(expected_domain, apub.id.inner())?;
+    verify_image_domain_matches(expected_domain, &apub.icon)?;
+    verify_image_domain_matches(expected_domain, &apub.image)?;
 
     let slur_regex = &data.settings().slur_regex();
     check_slurs(&apub.name, slur_regex)?;
index cf66beccd4b801985f8ac8a03867d228d3609462..6acbf9ad4e7dd596fc0e5304e0aa1496591ad214 100644 (file)
@@ -1,5 +1,8 @@
-use crate::protocol::Source;
+use crate::protocol::{ImageObject, Source};
 use html2md::parse_html;
+use lemmy_apub_lib::verify::verify_domains_match;
+use lemmy_utils::LemmyError;
+use url::Url;
 
 pub mod comment;
 pub mod community;
@@ -19,6 +22,14 @@ pub(crate) fn get_summary_from_string_or_source(
   }
 }
 
+pub fn verify_image_domain_matches(a: &Url, b: &Option<ImageObject>) -> Result<(), LemmyError> {
+  if let Some(b) = b {
+    verify_domains_match(a, &b.url)
+  } else {
+    Ok(())
+  }
+}
+
 #[cfg(test)]
 pub(crate) mod tests {
   use actix::Actor;
index 8eb7fe8b7c09316afb8a09547128f33955b2f643..14e79e944b2b3cfcba6621f3ab932cf45820f627 100644 (file)
@@ -1,7 +1,11 @@
 use crate::{
   check_is_apub_id_valid,
   generate_outbox_url,
-  objects::{get_summary_from_string_or_source, instance::fetch_instance_actor_for_object},
+  objects::{
+    get_summary_from_string_or_source,
+    instance::fetch_instance_actor_for_object,
+    verify_image_domain_matches,
+  },
   protocol::{
     objects::{
       person::{Person, UserTypes},
@@ -123,6 +127,8 @@ impl ApubObject for ApubPerson {
   ) -> Result<(), LemmyError> {
     verify_domains_match(person.id.inner(), expected_domain)?;
     check_is_apub_id_valid(person.id.inner(), false, &context.settings())?;
+    verify_image_domain_matches(expected_domain, &person.icon)?;
+    verify_image_domain_matches(expected_domain, &person.image)?;
 
     let slur_regex = &context.settings().slur_regex();
     check_slurs(&person.preferred_username, slur_regex)?;
index 5b564ff88a6fd571acac639d29309a9b69a41e85..7820624d91303d97588fb8d35f3c6813182d1ead 100644 (file)
@@ -4,7 +4,11 @@ use crate::{
     community_moderators::ApubCommunityModerators,
     community_outbox::ApubCommunityOutbox,
   },
-  objects::{community::ApubCommunity, get_summary_from_string_or_source},
+  objects::{
+    community::ApubCommunity,
+    get_summary_from_string_or_source,
+    verify_image_domain_matches,
+  },
   protocol::{objects::Endpoints, ImageObject, Source},
 };
 use activitystreams_kinds::actor::GroupType;
@@ -58,6 +62,8 @@ impl Group {
   ) -> Result<(), LemmyError> {
     check_is_apub_id_valid(self.id.inner(), true, &context.settings())?;
     verify_domains_match(expected_domain, self.id.inner())?;
+    verify_image_domain_matches(expected_domain, &self.icon)?;
+    verify_image_domain_matches(expected_domain, &self.image)?;
 
     let slur_regex = &context.settings().slur_regex();
     check_slurs(&self.preferred_username, slur_regex)?;