diff --git a/src/Render/MediaRenderer.php b/src/Render/MediaRenderer.php
index 855b859..0e0071d 100644
--- a/src/Render/MediaRenderer.php
+++ b/src/Render/MediaRenderer.php
@@ -179,7 +179,7 @@ protected function getMedia(MediaInterface|string|null $media): ?MediaInterface
protected function htmlAttributes(array $attributes): string
{
array_walk($attributes, function (&$value, $attribute) {
- $value = "$attribute=\"$value\"";
+ $value = sprintf('%s="%s"', $attribute, htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'));
});
return implode(' ', $attributes);
diff --git a/tests/Unit/Render/MediaRendererTest.php b/tests/Unit/Render/MediaRendererTest.php
index e3e3793..0eb39fa 100644
--- a/tests/Unit/Render/MediaRendererTest.php
+++ b/tests/Unit/Render/MediaRendererTest.php
@@ -68,6 +68,11 @@ public function testRenderImages()
$expectedXlImg = '
';
$this->assertEquals($expectedXlImg, $renderer->renderImage($media, 'xl', ['class' => 'img-fluid']));
+ $media->setDescription('A "quoted" image & ');
+ $expectedXlImg = '
';
+ $this->assertEquals($expectedXlImg, $renderer->renderImage($media, 'xl', ['class' => 'img-fluid']));
+ $media->setDescription(null);
+
$versionL = new MediaVersion('l', $media);
$versionL->setUrl('https://example.com/image.l.jpeg');
$versionL->setWidth(800);