Skip to content

Commit ab29319

Browse files
committed
Merge branch 'advisory-fix-1'
2 parents 0b8b5d1 + 93cbca7 commit ab29319

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

src/HtmlSanitizer/HtmlSanitizer.cs

+14
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ private void RemoveComments(INode context)
453453
{
454454
foreach (var comment in GetAllNodes(context).OfType<IComment>().ToList())
455455
{
456+
var escapedText = comment.TextContent.Replace("<", "&lt;").Replace(">", "&gt;");
457+
if (escapedText != comment.TextContent)
458+
comment.TextContent = escapedText;
459+
456460
var e = new RemovingCommentEventArgs(comment);
457461
OnRemovingComment(e);
458462

@@ -463,6 +467,16 @@ private void RemoveComments(INode context)
463467

464468
private void DoSanitize(IHtmlDocument dom, IParentNode context, string baseUrl = "")
465469
{
470+
// always encode text in raw data content
471+
foreach (var tag in context.QuerySelectorAll("*").Where(t => t.Flags.HasFlag(NodeFlags.LiteralText) && !string.IsNullOrWhiteSpace(t.InnerHtml)))
472+
{
473+
var escapedHtml = tag.InnerHtml.Replace("<", "&lt;").Replace(">", "&gt;");
474+
if (escapedHtml != tag.InnerHtml)
475+
tag.InnerHtml = escapedHtml;
476+
if (tag.InnerHtml != escapedHtml) // setting InnerHtml does not work for noscript
477+
tag.SetInnerText(escapedHtml);
478+
}
479+
466480
// remove disallowed tags
467481
foreach (var tag in context.QuerySelectorAll("*").Where(t => !IsAllowedTag(t)).ToList())
468482
{

test/HtmlSanitizer.Tests/Tests.cs

+56-1
Original file line numberDiff line numberDiff line change
@@ -3248,7 +3248,7 @@ public void StyleByPassTest()
32483248
var sanitized = sanitizer.Sanitize(html, "http://www.example.com");
32493249

32503250
// Assert
3251-
Assert.Equal("aaabc<style>x[x=\"\\3c/style>\\3cimg src onerror=alert(1)>\"] { }</style>", sanitized);
3251+
Assert.Equal("aaabc<style>x[x=\"\\3c/style&gt;\\3cimg src onerror=alert(1)&gt;\"] { }</style>", sanitized);
32523252
}
32533253

32543254
[Fact]
@@ -3497,4 +3497,59 @@ public void Number469Test()
34973497
var sanitized = sanitizer.Sanitize(html);
34983498
Assert.Equal(@"<div style=""height: 0; background-image: url(&quot;https://example.com/1.jpg&quot;), url(&quot;https://example.com/2.jpg&quot;), url(&quot;https://example.com/3.jpg&quot;); display: none""></div>", sanitized);
34993499
}
3500+
3501+
[Fact]
3502+
public void BypassTest()
3503+
{
3504+
var sanitizer = new HtmlSanitizer();
3505+
sanitizer.AllowedTags.Add("svg");
3506+
sanitizer.AllowedTags.Add("title");
3507+
sanitizer.AllowedTags.Add("xmp");
3508+
var bypass = @"<svg></p><title><xmp></title><img src=x onerror=alert(1)></xmp></title>";
3509+
var sanitized = sanitizer.Sanitize(bypass, "https://www.example.com");
3510+
var expected = @"<svg><p></p><title><xmp>&lt;/title&gt;&lt;img src=x onerror=alert(1)&gt;</xmp></title></svg>";
3511+
Assert.Equal(expected, sanitized);
3512+
}
3513+
3514+
[Fact]
3515+
public void Bypass2Test()
3516+
{
3517+
var sanitizer = new HtmlSanitizer();
3518+
sanitizer.AllowedTags.Add("form");
3519+
sanitizer.AllowedTags.Add("math");
3520+
sanitizer.AllowedTags.Add("mtext");
3521+
sanitizer.AllowedTags.Add("mglyph");
3522+
sanitizer.AllowedTags.Add("xmp");
3523+
var bypass = @"<form><math><mtext></form><form><mglyph><xmp></math><img src onerror=alert(1)>";
3524+
var sanitized = sanitizer.Sanitize(bypass, "https://www.example.com");
3525+
var expected = @"<form><math><mtext><form><mglyph><xmp>&lt;/math&gt;&lt;img src onerror=alert(1)&gt;</xmp></mglyph></form></mtext></math></form>";
3526+
Assert.Equal(expected, sanitized);
3527+
}
3528+
3529+
[Fact]
3530+
public void Bypass3Test()
3531+
{
3532+
var sanitizer = new HtmlSanitizer();
3533+
sanitizer.AllowedTags.Add("svg");
3534+
sanitizer.AllowedTags.Add("title");
3535+
sanitizer.AllowedTags.Add("noscript");
3536+
var bypass = @"<svg></p><title><noscript></title><img src=x onerror=alert(1)></noscript></title>";
3537+
var sanitized = sanitizer.Sanitize(bypass, "https://www.example.com");
3538+
var expected = "<svg><p></p><title><noscript>&lt;/title&gt;&lt;img src=x onerror=alert(1)&gt;</noscript></title></svg>";
3539+
Assert.Equal(expected, sanitized);
3540+
}
3541+
3542+
[Fact]
3543+
public void Bypass4Test()
3544+
{
3545+
var sanitizer = new HtmlSanitizer();
3546+
sanitizer.AllowedTags.Add("svg");
3547+
sanitizer.AllowedTags.Add("p");
3548+
sanitizer.AllowedTags.Add("style");
3549+
sanitizer.RemovingComment += (s, e) => e.Cancel = true;
3550+
var bypass = @"<svg></p><style><!--</style><img src=x onerror=alert(1)>-->";
3551+
var sanitized = sanitizer.Sanitize(bypass, "https://www.example.com");
3552+
var expected = "<svg><p></p><style><!--&lt;/style&gt;&lt;img src=x onerror=alert(1)&gt;--></style></svg>";
3553+
Assert.Equal(expected, sanitized);
3554+
}
35003555
}

0 commit comments

Comments
 (0)