diff --git a/src/Twig/Runtime/MarkdownExtension.php b/src/Twig/Runtime/MarkdownExtension.php index c73e8eea49..3187796f13 100644 --- a/src/Twig/Runtime/MarkdownExtension.php +++ b/src/Twig/Runtime/MarkdownExtension.php @@ -61,7 +61,7 @@ public function commentContent(?string $content, bool $fullLength = false): stri } if ($this->isMarkdownEnabled()) { - $content = $this->markdown->toHtml($content, false); + $content = $this->markdown->toHtml($content); } elseif ($fullLength) { $content = '

' . nl2br($content) . '

'; } @@ -112,7 +112,7 @@ public function timesheetContent(?string $content): string } if ($this->isMarkdownEnabled()) { - return $this->markdown->toHtml($content, false); + return $this->markdown->toHtml($content); } return nl2br($content); @@ -126,6 +126,6 @@ public function timesheetContent(?string $content): string */ public function markdownToHtml(string $content): string { - return $this->markdown->toHtml($content, false); + return $this->markdown->toHtml($content); } } diff --git a/src/Utils/Markdown.php b/src/Utils/Markdown.php index 0988e7c9df..5f21a100aa 100644 --- a/src/Utils/Markdown.php +++ b/src/Utils/Markdown.php @@ -33,7 +33,12 @@ public function __construct() */ public function toHtml(string $text, bool $safe = true): string { - $this->parser->setSafeMode($safe); + if ($safe !== true) { + @trigger_error('Only safe mode is supported in Markdown since 1.16.3 to prevent XSS attacks. Parameter $safe will be removed with 2.0', E_USER_DEPRECATED); + } + + $this->parser->setSafeMode(true); + $this->parser->setMarkupEscaped(true); return $this->parser->text($text); } diff --git a/tests/Twig/Runtime/MarkdownExtensionTest.php b/tests/Twig/Runtime/MarkdownExtensionTest.php index 56fbaf828e..4418f3e9f4 100644 --- a/tests/Twig/Runtime/MarkdownExtensionTest.php +++ b/tests/Twig/Runtime/MarkdownExtensionTest.php @@ -27,6 +27,10 @@ public function testMarkdownToHtml() $sut = new MarkdownExtension(new Markdown(), $config); $this->assertEquals('

test

', $sut->markdownToHtml('*test*')); $this->assertEquals('

# foobar

', $sut->markdownToHtml('# foobar')); + $this->assertEquals( + '

XSS

', + $sut->markdownToHtml('[XSS](javascript:alert(`XSS`))') + ); } public function testTimesheetContent() @@ -47,6 +51,10 @@ public function testTimesheetContent() "\n

foo bar

", $sut->timesheetContent("- test\n- foo\n\nfoo __bar__") ); + $this->assertEquals( + '

XSS

', + $sut->timesheetContent('[XSS](javascript:alert(`XSS`))') + ); } public function testCommentContent() @@ -76,6 +84,10 @@ public function testCommentContent() "\n

foo bar

", $sut->commentContent("- test\n- foo\n\nfoo __bar__") ); + $this->assertEquals( + '

XSS

', + $sut->commentContent('[XSS](javascript:alert(`XSS`))') + ); } public function testCommentOneLiner() diff --git a/tests/Utils/MarkdownTest.php b/tests/Utils/MarkdownTest.php index 5871a5b995..b021bf8b98 100644 --- a/tests/Utils/MarkdownTest.php +++ b/tests/Utils/MarkdownTest.php @@ -81,6 +81,24 @@ public function testDuplicateIds() ## test ### test # test +EOT; + $this->assertEquals($html, $sut->toHtml($markdown)); + } + + public function testLinksAreSanitized() + { + $sut = new Markdown(); + + $html = <<<'EOT' +

XSS
+XSS
+XSS

+EOT; + + $markdown = <<assertEquals($html, $sut->toHtml($markdown)); }