diff --git a/Cargo.lock b/Cargo.lock index e36e618b..60e554a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2798,6 +2798,7 @@ dependencies = [ "eigen-crypto-bls", "eigen-utils", "ethers", + "mime-sniffer", "num-bigint 0.4.6", "regex", "serde", @@ -4631,6 +4632,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime-sniffer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b8b2a64cd735f1d5f17ff6701ced3cc3c54851f9448caf454cd9c923d812408" +dependencies = [ + "mime", + "url", +] + [[package]] name = "minimal-lexical" version = "0.2.1" diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 495989c2..06d7bfaf 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -14,13 +14,15 @@ ark-ff.workspace = true eigen-crypto-bls.workspace = true eigen-utils.workspace = true ethers.workspace = true -num-bigint = "0.4.4" -regex = "1" serde_json.workspace = true serde.workspace = true thiserror.workspace = true tokio.workspace = true url.workspace = true +num-bigint = "0.4.4" +regex = "1" +mime-sniffer = "0.1" + [dev-dependencies] ark-bn254.workspace = true diff --git a/crates/types/src/operator_metadata.rs b/crates/types/src/operator_metadata.rs index 99562f30..20603a25 100644 --- a/crates/types/src/operator_metadata.rs +++ b/crates/types/src/operator_metadata.rs @@ -1,4 +1,5 @@ -use alloy::transports::http::reqwest::Url; +use alloy::transports::http::reqwest::{self, Url}; +use mime_sniffer::MimeTypeSniffer; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use thiserror::Error; @@ -46,6 +47,8 @@ pub enum OperatorMetadataError { LogoUrlInvalid, #[error("Logo url has an invalid image extension")] LogoUrlInvalidImageExtension, + #[error("Logo has an unsupported mime type")] + LogoUrlInvalidMimeType, #[error("Website url is invalid")] WebsiteUrlInvalid, @@ -104,7 +107,12 @@ impl OperatorMetadata { if path.extension().map(|ext| ext != "png").unwrap_or(true) { return Err(LogoUrlInvalidImageExtension); } - // TODO: check if the server returns the content with a "image/png" mime type + let response = reqwest::get(&self.logo).await.unwrap(); + let body = response.bytes().await.unwrap(); + + if body.sniff_mime_type().map_or(true, |m| m != "image/png") { + return Err(LogoUrlInvalidMimeType); + } // website, if non-empty, must have less than 1024 characters, // not point to localhost or 127.0.0.1, and must be a valid URL that matches the regex