diff --git a/dev/tests/integration/testsuite/Magento/Csp/CspUtilTest.php b/dev/tests/integration/testsuite/Magento/Csp/CspUtilTest.php index 93d019f572e63..d961332ee6950 100644 --- a/dev/tests/integration/testsuite/Magento/Csp/CspUtilTest.php +++ b/dev/tests/integration/testsuite/Magento/Csp/CspUtilTest.php @@ -30,7 +30,7 @@ public function testPhtmlHelper(): void $content = $this->getResponse()->getContent(); $this->assertStringContainsString( - '', + '', $content ); $this->assertStringContainsString("", $content); diff --git a/dev/tests/integration/testsuite/Magento/Csp/Helper/InlineUtilTest.php b/dev/tests/integration/testsuite/Magento/Csp/Helper/InlineUtilTest.php index 0f31f0beccda9..d272b398cd876 100644 --- a/dev/tests/integration/testsuite/Magento/Csp/Helper/InlineUtilTest.php +++ b/dev/tests/integration/testsuite/Magento/Csp/Helper/InlineUtilTest.php @@ -96,7 +96,7 @@ public function getTags(): array 'script', ['src' => 'http://magento.com/static/some-script.js'], null, - '', + '', [new FetchPolicy('script-src', false, ['http://magento.com'])] ], 'inline-script' => [ @@ -209,7 +209,7 @@ public function getTags(): array 'iframe', ['src' => 'http://magento.com/some-page'], null, - '', + '', [new FetchPolicy('frame-src', false, ['http://magento.com'])] ], 'remote-track' => [ @@ -230,21 +230,21 @@ public function getTags(): array 'video', ['src' => 'https://magento.com/static/video.mp4'], null, - '', + '', [new FetchPolicy('media-src', false, ['https://magento.com'])] ], 'remote-audio' => [ 'audio', ['src' => 'https://magento.com/static/audio.mp3'], null, - '', + '', [new FetchPolicy('media-src', false, ['https://magento.com'])] ], 'remote-object' => [ 'object', ['data' => 'http://magento.com/static/flash.swf'], null, - '', + '', [new FetchPolicy('object-src', false, ['http://magento.com'])] ], 'remote-embed' => [ @@ -259,7 +259,7 @@ public function getTags(): array ['code' => 'SomeApplet.class', 'archive' => 'https://magento.com/applet/my-applet.jar'], null, '', + . 'archive="https://magento.com/applet/my-applet.jar">', [new FetchPolicy('object-src', false, ['https://magento.com'])] ] ]; @@ -294,7 +294,7 @@ public function testSecureHtmlRenderer(): void $eventListener = $this->secureHtmlRenderer->renderEventListener('onclick', 'alert()'); $this->assertEquals( - '', + '', $scriptTag ); $this->assertEquals( diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/Helper/SecureHtmlRendererTemplateTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/Helper/SecureHtmlRendererTemplateTest.php index 0d2b85b4ae20d..2999bc06b2f36 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/Helper/SecureHtmlRendererTemplateTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/Helper/SecureHtmlRendererTemplateTest.php @@ -33,7 +33,7 @@ public function testTemplateUsage(): void $content ); $this->assertStringContainsString( - '', + '', $content ); $this->assertStringContainsString( diff --git a/lib/internal/Magento/Framework/View/Helper/SecureHtmlRender/HtmlRenderer.php b/lib/internal/Magento/Framework/View/Helper/SecureHtmlRender/HtmlRenderer.php index d8705b63cd0a9..466728e0ec784 100644 --- a/lib/internal/Magento/Framework/View/Helper/SecureHtmlRender/HtmlRenderer.php +++ b/lib/internal/Magento/Framework/View/Helper/SecureHtmlRender/HtmlRenderer.php @@ -13,6 +13,31 @@ */ class HtmlRenderer { + + /** + * List of void elements which require a self-closing tag and don't allow content + * + * @var array + */ + private const VOID_ELEMENTS_MAP = [ + 'area' => true, + 'base' => true, + 'br' => true, + 'col' => true, + 'command' => true, + 'embed' => true, + 'hr' => true, + 'img' => true, + 'input' => true, + 'keygen' => true, + 'link' => true, + 'meta' => true, + 'param' => true, + 'source' => true, + 'track' => true, + 'wbr' => true, + ]; + /** * @var Escaper */ @@ -49,10 +74,10 @@ public function renderTag(TagData $tagData): string } $html = '<' .$tagData->getTag() .$attributesHtml; - if ($content) { - $html .= '>' .$content .'' .$tagData->getTag() .'>'; - } else { + if (isset(self::VOID_ELEMENTS_MAP[$tagData->getTag()])) { $html .= '/>'; + } else { + $html .= '>' .$content .'' .$tagData->getTag() .'>'; } return $html; diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Helper/SecureHtmlRenderer/HtmlRendererTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Helper/SecureHtmlRenderer/HtmlRendererTest.php new file mode 100644 index 0000000000000..44b6f66c4380a --- /dev/null +++ b/lib/internal/Magento/Framework/View/Test/Unit/Helper/SecureHtmlRenderer/HtmlRendererTest.php @@ -0,0 +1,60 @@ +escaperMock = $this->createMock(Escaper::class); + } + + /** + * @covers \Magento\Framework\View\Helper\SecureHtmlRender\HtmlRenderer::renderTag + */ + public function testRenderTag() + { + $helper = new HtmlRenderer($this->escaperMock); + + /** Test void element to have closing tag */ + $tag = new TagData('hr', [], null, true); + $this->assertEquals( + "