diff --git a/homeassistant/components/image/__init__.py b/homeassistant/components/image/__init__.py index 7060e62011c..8daea2cdd46 100644 --- a/homeassistant/components/image/__init__.py +++ b/homeassistant/components/image/__init__.py @@ -62,9 +62,9 @@ class ImageContentTypeError(HomeAssistantError): """Error with the content type while loading an image.""" -def valid_image_content_type(content_type: str) -> str: +def valid_image_content_type(content_type: str | None) -> str: """Validate the assigned content type is one of an image.""" - if content_type.split("/", 1)[0] != "image": + if content_type is None or content_type.split("/", 1)[0] != "image": raise ImageContentTypeError return content_type @@ -174,9 +174,10 @@ class ImageEntity(Entity): url, timeout=GET_IMAGE_TIMEOUT, follow_redirects=True ) response.raise_for_status() + content_type = response.headers.get("content-type") return Image( content=response.content, - content_type=response.headers["content-type"], + content_type=valid_image_content_type(content_type), ) except httpx.TimeoutException: _LOGGER.error("%s: Timeout getting image from %s", self.entity_id, url) @@ -189,6 +190,14 @@ class ImageEntity(Entity): err, ) return None + except ImageContentTypeError: + _LOGGER.error( + "%s: Image from %s has invalid content type: %s", + self.entity_id, + url, + content_type, + ) + return None async def async_image(self) -> bytes | None: """Return bytes of image.""" diff --git a/tests/components/image/test_init.py b/tests/components/image/test_init.py index 0573484a534..0950d6f42e5 100644 --- a/tests/components/image/test_init.py +++ b/tests/components/image/test_init.py @@ -256,3 +256,34 @@ async def test_fetch_image_url_exception( resp = await client.get("/api/image_proxy/image.test") assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR + + +@respx.mock +@pytest.mark.parametrize( + "content_type", + [ + None, + "text/plain", + ], +) +async def test_fetch_image_url_wrong_content_type( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + content_type: str | None, +) -> None: + """Test fetching an image with an authenticated client.""" + respx.get("https://example.com/myimage.jpg").respond( + status_code=HTTPStatus.OK, content_type=content_type, content=b"Test" + ) + + mock_integration(hass, MockModule(domain="test")) + mock_platform(hass, "test.image", MockImagePlatform([MockURLImageEntity(hass)])) + assert await async_setup_component( + hass, image.DOMAIN, {"image": {"platform": "test"}} + ) + await hass.async_block_till_done() + + client = await hass_client() + + resp = await client.get("/api/image_proxy/image.test") + assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR