Skip to content

Commit

Permalink
add better content-type checks
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Oct 27, 2023
1 parent e95aa55 commit 7325b7c
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/kitsune-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ garde = { version = "0.16.0", default-features = false, features = [
"serde",
] }
globset = "0.4.13"
headers = "0.3.9"
hex-simd = "0.8.0"
http = "0.2.9"
img-parts = "0.3.0"
Expand Down
33 changes: 25 additions & 8 deletions crates/kitsune-core/src/activitypub/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use async_recursion::async_recursion;
use autometrics::autometrics;
use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, SelectableHelper};
use diesel_async::RunQueryDsl;
use http::{header::CONTENT_TYPE, HeaderValue};
use headers::{ContentType, HeaderMapExt};
use http::HeaderValue;
use kitsune_cache::{ArcCache, CacheBackend};
use kitsune_db::{
model::{
Expand All @@ -29,6 +30,7 @@ use kitsune_type::{
ap::{actor::Actor, Object},
jsonld::RdfNode,
};
use mime::Mime;
use scoped_futures::ScopedFutureExt;
use serde::de::DeserializeOwned;
use typed_builder::TypedBuilder;
Expand Down Expand Up @@ -97,15 +99,30 @@ impl Fetcher {
T: DeserializeOwned + RdfNode,
{
let response = self.client.get(url).await?;
let content_type = response
let Some(content_type) = response
.headers()
.get(CONTENT_TYPE)
.map(HeaderValue::as_bytes);
.typed_get::<ContentType>()
.map(Mime::from)
else {
return Err(ApiError::BadRequest.into());
};

if content_type
!= Some(b"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
&& content_type != Some(b"application/activity+json")
{
let is_json_ld_activitystreams = content_type
.essence_str()
.eq_ignore_ascii_case("application/ld+json")
&& content_type
.get_param("profile")
.map_or(false, |profile_name| {
profile_name
.as_str()
.eq_ignore_ascii_case("https://www.w3.org/ns/activitystreams")
});

let is_activity_json = content_type
.essence_str()
.eq_ignore_ascii_case("application/activity+json");

if !is_json_ld_activitystreams && !is_activity_json {
return Err(ApiError::BadRequest.into());
}

Expand Down

0 comments on commit 7325b7c

Please sign in to comment.