CVE-2020-26293: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: HtmlSanitizer is a .NET library for cleaning HTML fragments and documents from constructs that can lead to XSS attacks. In HtmlSanitizer before version 5.0.372, there is a possible XSS bypass if style tag is allowed. If you have explicitly allowed the `<style>` tag, an attacker could craft HTML that includes script after passing through the sanitizer. The default settings disallow the `<style>` tag so there is no risk if you have not explicitly allowed the `<style>` tag. The problem has been fixed in version 5.0.372.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2021-01-04T19:15Z
Repository: https://github.com/mganss/HtmlSanitizer
Language: C#
Files changed: src/HtmlSanitizer/HtmlSanitizer.cs, test/HtmlSanitizer.Tests/Tests.cs
Commit date: 2020-12-23 12:42:48 +0100
Commit message: Fix hex escape issue in style element

Diff: diff --git a/src/HtmlSanitizer/HtmlSanitizer.cs b/src/HtmlSanitizer/HtmlSanitizer.cs
index 9a42899..c941456 100644
--- a/src/HtmlSanitizer/HtmlSanitizer.cs
+++ b/src/HtmlSanitizer/HtmlSanitizer.cs
@@ -741,11 +741,11 @@ private void SanitizeStyleSheets(IHtmlDocument dom, string baseUrl)
                     if (!SanitizeStyleRule(rule, styleTag, baseUrl) && RemoveAtRule(styleTag, rule))
                         styleSheet.RemoveAt(i);
                     else i++;
                 }
 
-                styleTag.InnerHtml = styleSheet.ToCss();
+                styleTag.InnerHtml = styleSheet.ToCss().Replace("<", "\\3c");
             }
         }
 
         private bool SanitizeStyleRule(ICssRule rule, IElement styleTag, string baseUrl)
         {
diff --git a/test/HtmlSanitizer.Tests/Tests.cs b/test/HtmlSanitizer.Tests/Tests.cs
index e7cdd89..09bac18 100644
--- a/test/HtmlSanitizer.Tests/Tests.cs
+++ b/test/HtmlSanitizer.Tests/Tests.cs
@@ -3199,9 +3199,22 @@ public void PreParsedDocumentWithContextTest()
             var document = parser.ParseDocument(html);
             var returnedDocument = sanitizer.SanitizeDom(document, document.Body);
 
             Assert.Equal("<html><head></head><body><div>hi</div></body></html>", returnedDocument.ToHtml());
         }
+
+        [Fact]
+        public void StyleByPassTest()
+        {
+            var sanitizer = new HtmlSanitizer();
+
+            sanitizer.AllowedTags.Add("style");
+
+            var html = "aaabc<style>x[x='\\3c /style>\\3c img src onerror=alert(1)>']{}</style>";
+            var sanitized = sanitizer.Sanitize(html, "http://www.example.com");
+
+            Assert.Equal("aaabc<style>x[x=\"\\3c/style>\\3cimg src onerror=alert(1)>\"] { }</style>", sanitized);
+        }
     }
 }
 
 #pragma warning restore 1591

Vulnerable code:                 styleTag.InnerHtml = styleSheet.ToCss();
Fixed code:                 styleTag.InnerHtml = styleSheet.ToCss().Replace("<", "\\3c");

        [Fact]
        public void StyleByPassTest()
        {
            var sanitizer = new HtmlSanitizer();

            sanitizer.AllowedTags.Add("style");

            var html = "aaabc<style>x[x='\\3c /style>\\3c img src onerror=alert(1)>']{}</style>";
            var sanitized = sanitizer.Sanitize(html, "http://www.example.com");

            Assert.Equal("aaabc<style>x[x=\"\\3c/style>\\3cimg src onerror=alert(1)>\"] { }</style>", sanitized);
        }