diff --git a/src/Aspire.Dashboard/Model/Markdown/HighlightedCodeBlockRenderer.cs b/src/Aspire.Dashboard/Model/Markdown/HighlightedCodeBlockRenderer.cs index 548a0297551..854ac878090 100644 --- a/src/Aspire.Dashboard/Model/Markdown/HighlightedCodeBlockRenderer.cs +++ b/src/Aspire.Dashboard/Model/Markdown/HighlightedCodeBlockRenderer.cs @@ -95,7 +95,7 @@ protected override void Write(HtmlRenderer renderer, CodeBlock obj) renderer.Writer.Write(@"
"); renderer.Writer.Write(@"
"); - renderer.Writer.Write(title); + renderer.WriteEscape(title); renderer.Writer.Write("
"); renderer.Writer.Write(@"
"); diff --git a/tests/Aspire.Dashboard.Tests/Markdown/MarkdownProcessorTests.cs b/tests/Aspire.Dashboard.Tests/Markdown/MarkdownProcessorTests.cs index 23c74bb0413..09ad0d54e67 100644 --- a/tests/Aspire.Dashboard.Tests/Markdown/MarkdownProcessorTests.cs +++ b/tests/Aspire.Dashboard.Tests/Markdown/MarkdownProcessorTests.cs @@ -168,6 +168,27 @@ public void ToHtml_FencedCodeBlock_CopyButtonHasLocalizedAccessibleName() Assert.Equal("aria-label=\"Localized:GridValueCopyToClipboard\"", copyButton.Groups["accessibleName"].Value); } + [Fact] + public void ToHtml_FencedCodeBlockLanguageWithHtml_HtmlEncoded() + { + // Arrange + var processor = CreateMarkdownProcessor(); + + var markdown = + """ + ```
+ In code block. + ``` + """; + + // Act + var html = processor.ToHtml(markdown, inCompleteDocument: true); + + // Assert + var title = Regex.Match(html, "
(.*?)
").Groups[1].Value; + Assert.Equal("</div><svg/onload=alert(1)>", title); + } + [Fact] public void ToHtml_ContainsHtml_HtmlIgnored() {