diff --git a/moli-renderer-v8/src/network_host/image.rs b/moli-renderer-v8/src/network_host/image.rs index f2c328c1fe..516f557900 100644 --- a/moli-renderer-v8/src/network_host/image.rs +++ b/moli-renderer-v8/src/network_host/image.rs @@ -448,9 +448,6 @@ fn image_response_descriptor_from_bytes( moli_web_mime::MimeSniffingContext::Image, body, ); - if !moli_web_mime::is_image_mime_essence(&computed_mime_type) { - return None; - } if moli_web_mime::is_svg_image_mime_essence(&computed_mime_type) { let metadata = moli_image::probe_svg_image(body).ok()?; return crate::native_bridge::ImageResponseDescriptor::svg(metadata); @@ -489,18 +486,29 @@ mod tests { for (mime, bytes) in [ ("image/png", png.as_slice()), ("image/svg+xml", svg.as_slice()), + ("application/xml", png.as_slice()), + ("text/xml", png.as_slice()), + ("application/blah+xml", png.as_slice()), ] { let encoded = manager.from_frozen_bytes(bytes.to_vec()); - for status in [200, 206, 301, 302, 400, 404, 410, 500, 503] { - let response = crate::protocol_types::NavigationResponse::from_text_body( - url::Url::parse("https://images.test/image").unwrap(), - status, - vec![("Content-Type".to_owned(), mime.as_bytes().to_vec())], - String::new(), - ); - let descriptor = image_response_descriptor_from_parkable(&response, &encoded) - .unwrap_or_else(|| panic!("{mime} image rejected at HTTP {status}")); - assert_eq!((descriptor.width, descriptor.height), (2, 1)); + for nosniff in [false, true] { + let mut headers = vec![("Content-Type".to_owned(), mime.as_bytes().to_vec())]; + if nosniff { + headers.push(("X-Content-Type-Options".to_owned(), b"nosniff".to_vec())); + } + for status in [200, 206, 301, 302, 400, 404, 410, 500, 503] { + let response = crate::protocol_types::NavigationResponse::from_text_body( + url::Url::parse("https://images.test/image").unwrap(), + status, + headers.clone(), + String::new(), + ); + let descriptor = image_response_descriptor_from_parkable(&response, &encoded) + .unwrap_or_else(|| { + panic!("{mime} image rejected at HTTP {status}, nosniff={nosniff}") + }); + assert_eq!((descriptor.width, descriptor.height), (2, 1)); + } } } } @@ -508,12 +516,26 @@ mod tests { #[test] fn image_response_rejects_empty_and_invalid_data_at_any_http_status() { let manager = moli_parkable_image::ParkableImageManager::default(); + let png = + moli_image::encode_png(&moli_image::RgbaImage::try_new(2, 1, vec![255; 8]).unwrap()) + .unwrap() + .bytes; + let svg = br#""#; for (mime, bytes) in [ ("image/png", b"".as_slice()), ("image/png", b"\x89PNG\r\n\x1a\n".as_slice()), ("image/png", b"not an image".as_slice()), ("image/svg+xml", b"Not Found".as_slice()), ("text/html", b"Not Found".as_slice()), + ("application/xml", b"\x89PNG\r\n\x1a\n".as_slice()), + ( + "application/xml", + b"".as_slice(), + ), + ("application/blah+xml", b"Not Found".as_slice()), + ("image/svg+xml", png.as_slice()), + ("application/xml", svg.as_slice()), + ("application/blah+xml", svg.as_slice()), ] { let encoded = manager.from_frozen_bytes(bytes.to_vec()); for status in [200, 404, 500] {