using AngleSharp.Dom; using AngleSharp.Dom.Html; using AngleSharp.Parser.Html; using Xunit; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using AngleSharp; using AngleSharp.Dom.Css; using System.Threading; using System.Reflection; // Tests based on tests from http://roadkill.codeplex.com/ // To create unit tests in this class reference is taken from // https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.232_-_Attribute_Escape_Before_Inserting_Untrusted_Data_into_HTML_Common_Attributes // and http://ha.ckers.org/xss.html // disable XML comments warnings #pragma warning disable 1591 namespace Ganss.XSS.Tests { public class HtmlSanitizerFixture { public HtmlSanitizer Sanitizer { get; set; } = new HtmlSanitizer(); } /// /// Tests for . /// public class HtmlSanitizerTests: IClassFixture { public HtmlSanitizer Sanitizer { get; set; } public HtmlSanitizerTests(HtmlSanitizerFixture fixture) { Sanitizer = fixture.Sanitizer; } /// /// A test for Xss locator /// [Fact] public void XSSLocatorTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "=&{()}\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = @"=&{()}"">"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector /// Example /// [Fact] public void ImageXSS1Test() { // Arrange var sanitizer = Sanitizer; // Action string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector without quotes and semicolon. /// Example /// [Fact] public void ImageXSS2Test() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image xss vector with case insensitive. /// Example /// [Fact] public void ImageCaseInsensitiveXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Html entities /// Example /// [Fact] public void ImageHtmlEntitiesXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with grave accent /// Example /// [Fact] public void ImageGraveAccentXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with malformed /// Example /// [Fact] public void ImageMalformedXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "\">"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with ImageFromCharCode /// Example /// [Fact] public void ImageFromCharCodeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with UTF-8 Unicode /// Example /// [Fact] public void ImageUTF8UnicodeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Long UTF-8 Unicode /// Example /// [Fact] public void ImageLongUTF8UnicodeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Hex encoding without semicolon /// Example /// [Fact] public void ImageHexEncodeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with embedded tab /// Example /// [Fact] public void ImageEmbeddedTabXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with embedded encoded tab /// Example /// [Fact] public void ImageEmbeddedEncodedTabXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with embedded new line /// Example /// [Fact] public void ImageEmbeddedNewLineXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with embedded carriage return /// Example /// [Fact] public void ImageEmbeddedCarriageReturnXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Multiline using ASCII carriage return /// Example /// [Fact] public void ImageMultilineInjectedXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = @" "; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "\n"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Null breaks up Javascript directive /// Example /// [Fact] public void ImageNullBreaksUpXSSTest1() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Null breaks up cross site scripting vector /// Example /// [Fact] public void ImageNullBreaksUpXSSTest2() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "alert(\"XSS\")"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with spaces and Meta characters /// Example /// [Fact] public void ImageSpaceAndMetaCharXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with half open html /// Example /// [Fact] public void ImageHalfOpenHtmlXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = " /// A test for Image Xss vector with double open angle bracket /// Example /// [Fact] public void ImageDoubleOpenAngleBracketXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = " /// A test for Dic Xss vector with Javascript escaping /// Example /// [Fact] public void DivJavascriptEscapingXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with input image /// Example /// [Fact] public void ImageInputXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Dynsrc /// Example /// [Fact] public void ImageDynsrcXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image Xss vector with Lowsrc /// Example /// [Fact] public void ImageLowsrcXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Xss vector with BGSound /// Example /// [Fact] public void BGSoundXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for BR with Javascript Include /// Example /// [Fact] public void BRJavascriptIncludeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for P with url in style /// Example /// [Fact] public void PWithUrlInStyleXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "

"; string actual = sanitizer.Sanitize(htmlFragment); // Assert // intentionally keep it failing to get notice when reviewing unit tests so can disucss string expected = "

"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image with vbscript /// Example /// [Fact] public void ImageWithVBScriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image with Mocha /// Example /// [Fact] public void ImageWithMochaXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image with Livescript /// Example /// [Fact] public void ImageWithLivescriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Iframe /// Example /// [Fact] public void IframeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Frame /// Example /// [Fact] public void FrameXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Table /// Example /// [Fact] public void TableXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for TD /// Example /// [Fact] public void TDXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div Background Image /// Example /// [Fact] public void DivBackgroundImageXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div Background Image with unicoded XSS /// Example /// [Fact] public void DivBackgroundImageWithUnicodedXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = @"
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div Background Image with extra characters /// Example /// [Fact] public void DivBackgroundImageWithExtraCharactersXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for DIV expression /// Example /// [Fact] public void DivExpressionXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Image with break up expression /// Example /// [Fact] public void ImageStyleExpressionXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with break up expression /// Example /// [Fact] public void AnchorTagStyleExpressionXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "exp/*"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "exp/*"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for BaseTag /// Example /// [Fact] public void BaseTagXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for EMBEDTag /// Example /// [Fact] public void EmbedTagXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for EMBEDSVG /// Example /// [Fact] public void EmbedSVGXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for XML namespace /// Example /// [Fact] public void XmlNamespaceXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for XML with CData /// Example /// [Fact] public void XmlWithCDataXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "]]>"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for XML with Comment obfuscation /// [Fact] public void XmlWithCommentObfuscationXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "<IMG SRC=\"javascript:alert('XSS')\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for XML with Embedded script /// Example /// [Fact] public void XmlWithEmbeddedScriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Html + Time /// Example /// [Fact] public void HtmlPlusTimeXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = ""; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with javascript link location /// Example /// [Fact] public void AnchorTagJavascriptLinkLocationXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with no filter evasion /// Example /// [Fact] public void DivNoFilterEvasionXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and no filter evasion /// Example /// [Fact] public void DivStyleExpressionNoFilterEvasionXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with non alpha non digit xss /// Example /// [Fact] public void AnchorTagNonAlphaNonDigitXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "\">XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with non alpha non digit xss /// Example /// [Fact] public void DivNonAlphaNonDigitXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and non alpha non digit xss /// Example /// [Fact] public void DivStyleExpressionNonAlphaNonDigitXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
)\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with non alpha non digit part 3 xss /// Example /// [Fact] public void DivNonAlphaNonDigit3XSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and non alpha non digit part 3 xss /// Example /// [Fact] public void DivStyleExpressionNonAlphaNonDigit3XSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
)\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with Extraneous open brackets xss /// Example /// [Fact] public void AnchorTagExtraneousOpenBracketsXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "alert(\"XSS\");//<\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "\">XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with Extraneous open brackets xss /// Example /// [Fact] public void DivExtraneousOpenBracketsXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
alert(\"XSS\");//<\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and Extraneous open brackets xss /// Example /// [Fact] public void DivStyleExpressionExtraneousOpenBracketsXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
alert(\"XSS\");//<)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
)\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with No closing script tags xss /// Example /// [Fact] public void DivNoClosingScriptTagsXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and No closing script tags xss /// Example /// [Fact] public void DivStyleExpressionNoClosingScriptTagsXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with Protocol resolution in script tags xss /// Example /// [Fact] public void AnchorTagProtocolResolutionScriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with Protocol resolution in script tags xss /// Example /// [Fact] public void DivProtocolResolutionScriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and Protocol resolution in script tags xss /// Example /// [Fact] public void DivStyleExpressionProtocolResolutionScriptXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with no single quotes or double quotes or semicolons xss /// Example /// [Fact] public void AnchorTagNoQuotesXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "a=/XSS/alert(a.source)\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with no single quotes or double quotes or semicolons xss /// Example /// [Fact] public void DivNoQuotesXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
a=/XSS/alert(a.source)\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with style expression and no single quotes or double quotes or semicolons xss /// Example /// [Fact] public void DivStyleExpressionNoQuotesXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
a=/XSS/alert(a.source))\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with US-ASCII encoding xss /// Example /// [Fact] public void AnchorTagUSASCIIEncodingXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with Downlevel-Hidden block xss /// [Fact] public void AnchorTagDownlevelHiddenBlockXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "XSS"; try { Assert.Equal(expected, actual, ignoreCase: true); } catch (Exception) { //in .net 3.5 there is a bug with URI, and so this test would otherwise fail on .net 3.5 in Appveyor / nunit: //http://help.appveyor.com/discussions/problems/1625-nunit-not-picking-up-net-framework-version //http://stackoverflow.com/questions/27019061/forcing-nunit-console-runner-to-use-clr-4-5 string expectedNet35 = @"XSS"; Assert.Equal(expectedNet35, actual, ignoreCase: true); } } /// /// A test for Div with Downlevel-Hidden block xss /// [Fact] public void DivDownlevelHiddenBlockXSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = @"
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for AnchorTag with Html Quotes Encapsulation 1 xss /// Example /// [Fact] public void AnchorTagHtmlQuotesEncapsulation1XSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "\" SRC=\"http://ha.ckers.org/xss.js\">\">XSS"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "\" SRC=\"http://ha.ckers.org/xss.js\">\">XSS"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for Div with Html Quotes Encapsulation 1 xss /// Example /// [Fact] public void DivHtmlQuotesEncapsulation1XSSTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
\" SRC=\"http://ha.ckers.org/xss.js\">\">"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
\" SRC=\"http://ha.ckers.org/xss.js\">\">
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// A test for various legal fragments /// [Fact] public void LegalTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// More tests for legal fragments. /// [Fact] public void MoreLegalTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
Test
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Misc tests. /// [Fact] public void MiscTest() { var sanitizer = Sanitizer; var html = @""; var actual = sanitizer.Sanitize(html); var expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @"
"; actual = sanitizer.Sanitize(html); expected = @"
"; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @"
"; actual = sanitizer.Sanitize(html); expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = "\""; actual = sanitizer.Sanitize(html); expected = "\""; Assert.Equal(expected, actual, ignoreCase: true); html = "\""; actual = sanitizer.Sanitize(html); expected = "\""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @"
Test"; actual = sanitizer.Sanitize(html); expected = @"
Test"; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = @""; actual = sanitizer.Sanitize(html); expected = ""; Assert.Equal(expected, actual, ignoreCase: true); html = "
Test
"; actual = sanitizer.Sanitize(html, "http://www.example.com"); expected = @"
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Tests disallowed tags. /// [Fact] public void DisallowedTagTest() { var sanitizer = Sanitizer; var html = @"Hallo"; var actual = sanitizer.Sanitize(html); var expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Tests disallowed HTML attributes. /// [Fact] public void DisallowedAttributeTest() { var sanitizer = Sanitizer; var html = @"
Test
"; var actual = sanitizer.Sanitize(html); var expected = @"
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Tests sanitization of attributes that contain a URL. /// [Fact] public void UrlAttributeTest() { var sanitizer = Sanitizer; var html = @"test"; var actual = sanitizer.Sanitize(html); var expected = @"test"; Assert.Equal(expected, actual, ignoreCase: true); html = @"test"; actual = sanitizer.Sanitize(html); expected = @"test"; Assert.Equal(expected, actual, ignoreCase: true); html = @"test"; actual = sanitizer.Sanitize(html, @"http://www.example.com"); expected = @"test"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Tests disallowed css properties. /// [Fact] public void DisallowedStyleTest() { var sanitizer = Sanitizer; var html = @"
test
"; var actual = sanitizer.Sanitize(html); var expected = @"
test
"; Assert.Equal(expected, actual, ignoreCase: true); } /// /// Tests sanitization of URLs that are contained in CSS property values. /// [Fact] public void UrlStyleTest() { var sanitizer = Sanitizer; var html = @"
"; var actual = sanitizer.Sanitize(html); var expected = @"
"; Assert.Equal(expected, actual, ignoreCase: true); html = @"
"; actual = sanitizer.Sanitize(html, @"http://www.example.com"); expected = @"
"; Assert.Equal(expected, actual, ignoreCase: true); } // test below from http://genshi.edgewall.org/ [Fact] public void SanitizeUnchangedTest() { var sanitizer = Sanitizer; var html = @"fo
o
"; Assert.Equal(@"fo
o
", sanitizer.Sanitize(html), ignoreCase: true); html = @"foo"; Assert.Equal(html, sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeEscapeTextTest() { var sanitizer = Sanitizer; var html = @"fo&"; Assert.Equal(@"fo&", sanitizer.Sanitize(html), ignoreCase: true); html = @"<foo>"; Assert.Equal(@"<foo>", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeEntityrefTextTest() { var sanitizer = Sanitizer; var html = @"foö"; Assert.Equal(@"foö", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeEscapeAttrTest() { var sanitizer = Sanitizer; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeCloseEmptyTagTest() { var sanitizer = Sanitizer; var html = @"fo
o
"; Assert.Equal(@"fo
o
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeInvalidEntityTest() { var sanitizer = Sanitizer; var html = @"&junk;"; Assert.Equal(@"&junk;", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveScriptElemTest() { var sanitizer = Sanitizer; var html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveOnclickAttrTest() { var sanitizer = Sanitizer; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveCommentsTest() { var sanitizer = Sanitizer; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveStyleScriptsTest() { var sanitizer = Sanitizer; // Inline style with url() using javascript: scheme var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); // Inline style with url() using javascript: scheme, using control char html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); // Inline style with url() using javascript: scheme, in quotes html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); // IE expressions in CSS not allowed html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); // Inline style with url() using javascript: scheme, using unicode // escapes html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveStylePhishingTest() { var sanitizer = Sanitizer; // The position property is not allowed var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); // Normal margins get passed through html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeRemoveSrcJavascriptTest() { var sanitizer = Sanitizer; var html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Case-insensitive protocol matching html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Grave accents (not parsed) // Protocol encoded using UTF-8 numeric entities html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Protocol encoded using UTF-8 numeric entities without a semicolon // (which is allowed because the max number of digits is used) html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Protocol encoded using UTF-8 numeric hex entities without a semicolon // (which is allowed because the max number of digits is used) html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Embedded tab character in protocol html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); // Embedded tab character in protocol, but encoded this time html = @""; Assert.Equal(@"", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeExpressionTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void CapitalExpressionTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeUrlWithJavascriptTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeCapitalUrlWithJavascriptTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeUnicodeEscapesTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeBackslashWithoutHexTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeUnsafePropsTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeCssHackTest() { var sanitizer = Sanitizer; var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizePropertyNameTest() { var sanitizer = Sanitizer; var html = @"
prop
"; Assert.Equal(@"
prop
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeUnicodeExpressionTest() { var sanitizer = Sanitizer; // Fullwidth small letters var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); // Fullwidth capital letters html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); // IPA extensions html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeUnicodeUrlTest() { var sanitizer = Sanitizer; // IPA extensions var html = @"
XSS
"; Assert.Equal(@"
XSS
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void RemovingTagEventTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingTag += (s, e) => e.Cancel = e.Tag.NodeName == "BLINK"; var html = @"
Test
"; Assert.Equal(@"
Test
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void RemovingAttributeEventTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingAttribute += (s, e) => e.Cancel = e.Attribute.Name == "onclick"; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void RemovingAttributeEventTagTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingAttribute += (s, e) => Assert.IsAssignableFrom(e.Tag); var html = @"
"; sanitizer.Sanitize(html); } [Fact] public void RemovingStyleEventTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingStyle += (s, e) => e.Cancel = e.Style.Name == "test"; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void RemovingStyleEventTagTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingStyle += (s, e) => Assert.IsAssignableFrom(e.Tag); var html = @"
"; sanitizer.Sanitize(html); } [Fact] public void ProtocolRelativeTest() { var sanitizer = Sanitizer; var html = @"Test"; Assert.Equal(@"Test", sanitizer.Sanitize(html), ignoreCase: true); Assert.Equal(@"Test", sanitizer.Sanitize(html, baseUrl: @"https://www.xyz.com/123"), ignoreCase: true); } [Fact] public void JavaScriptIncludeAndAngleBracketsTest() { // Arrange var sanitizer = Sanitizer; // Act string htmlFragment = "
"; string actual = sanitizer.Sanitize(htmlFragment); // Assert string expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void AllowDataAttributesTest() { var sanitizer = new HtmlSanitizer() { AllowDataAttributes = true }; var html = @"
"; Assert.Equal(html, sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void AllowDataAttributesCaseTest() { var sanitizer = new HtmlSanitizer() { AllowDataAttributes = true }; var html = @"
"; Assert.Equal(html, sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void AllowDataAttributesOffTest() { var sanitizer = new HtmlSanitizer() { AllowDataAttributes = false }; var html = @"
"; Assert.Equal(@"
", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void SanitizeNonClosedTagTest() { var sanitizer = Sanitizer; var html = @"
Hallo

Bold
Ballo"; Assert.Equal(@"

Hallo

Bold
Ballo

", sanitizer.Sanitize(html), ignoreCase: true); } [Fact] public void PostProcessTest() { var sanitizer = new HtmlSanitizer(); sanitizer.PostProcessNode += (s, e) => { if (e.Node is IHtmlElement el) { el.ClassList.Add("test"); var b = e.Document.CreateElement("b"); b.TextContent = "Test"; el.AppendChild(b); } }; var html = @"
Hallo
"; var sanitized = sanitizer.Sanitize(html); Assert.Equal(@"
HalloTest
", sanitized, ignoreCase: true); } [Fact] public void AutoLinkTest() { var sanitizer = new HtmlSanitizer(); sanitizer.PostProcessNode += (s, e) => { if (e.Node is IText text) { var autolinked = Regex.Replace(text.NodeValue, @"https?://[^\s]+[^\s!?.:;,]+", m => $@"{m.Value}", RegexOptions.IgnoreCase); if (autolinked != text.NodeValue) { var f = new HtmlParser().Parse(autolinked); foreach (var node in f.Body.ChildNodes) e.ReplacementNodes.Add(node); } } }; var html = @"
Click here: http://example.com/.
"; Assert.Equal(@"
Click here: http://example.com/.
", sanitizer.Sanitize(html), ignoreCase: true); Assert.Equal(@"Check out https://www.google.com.", sanitizer.Sanitize("Check out https://www.google.com."), ignoreCase: true); } [Fact] public void RussianTextTest() { // Arrange var s = Sanitizer; // Act var htmlFragment = "Тест"; var actual = s.Sanitize(htmlFragment, ""); // Assert var expected = htmlFragment; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void DisallowCssPropertyValueTest() { // Arrange var s = new HtmlSanitizer { DisallowCssPropertyValue = new Regex("^b.*") }; // Act var htmlFragment = @"
Test
"; var actual = s.Sanitize(htmlFragment); // Assert var expected = @"
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void CssKeyTest() { // Arrange var s = Sanitizer; // Act var htmlFragment = @"
Test
"; var actual = s.Sanitize(htmlFragment); // Assert var expected = @"
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void InvalidBaseUrlTest() { // Arrange var s = Sanitizer; // Act var htmlFragment = @"
Test
"; var actual = s.Sanitize(htmlFragment, "hallo"); // Assert var expected = @"
Test
"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void XhtmlTest() { // Arrange var s = Sanitizer; // Act var htmlFragment = @"

"; var actual = s.Sanitize(htmlFragment, "", AngleSharp.Xml.XmlMarkupFormatter.Instance); // Assert var expected = @"

"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void MultipleRecipientsTest() { // https://github.com/mganss/HtmlSanitizer/issues/41 // Arrange var s = new HtmlSanitizer(); s.AllowedSchemes.Add("mailto"); // Act var htmlFragment = @"Bang Bang"; var actual = s.Sanitize(htmlFragment); // Assert var expected = htmlFragment; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void QuotedBackgroundImageTest() { // https://github.com/mganss/HtmlSanitizer/issues/44 // Arrange var s = Sanitizer; // Act var htmlFragment = "
"; var actual = s.Sanitize(htmlFragment); // Assert var expected = "
"; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void QuotedBackgroundImageFromIE9() { // Arrange var s = Sanitizer; // Act var htmlFragment = ""; var actual = s.Sanitize(htmlFragment); // Assert var expected = ""; Assert.Equal(expected, actual, ignoreCase: true); } [Fact] public void RemoveEventForNotAllowedTag() { var allowedTags = new[] {"a"}; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags); s.RemovingTag += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedTag, actual); } [Fact] public void RemoveEventForNotAllowedAttribute() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] {"id"}; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes); s.RemovingAttribute += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedAttribute, actual); } [Fact] public void RemoveEventForNotAllowedStyle() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] { "style" }; var allowedStyles = new[] { "margin" }; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles); s.RemovingStyle += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedStyle, actual); } [Fact] public void RemoveEventForNotAllowedValueAtAttribute() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] { "id" }; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes); s.RemovingAttribute += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedValue, actual); } [Fact] public void RemoveEventForNotAllowedValueAtStyle() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] { "style" }; var allowedStyles = new[] { "margin" }; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles); s.RemovingStyle += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedValue, actual); } [Fact] public void RemoveEventForNotAllowedUrlAtUriAttribute() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] { "href" }; var uriAttributes = new[] { "href" }; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, uriAttributes: uriAttributes); s.RemovingAttribute += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedUrlValue, actual); } [Fact] public void RemoveEventForNotAllowedUrlAtStyle() { var allowedTags = new[] { "a" }; var allowedAttributes = new[] { "style" }; var allowedStyles = new[] { "background" }; RemoveReason? actual = null; var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles); s.RemovingStyle += (sender, args) => { actual = args.Reason; }; s.Sanitize("just any content"); Assert.Equal(RemoveReason.NotAllowedUrlValue, actual); } [Fact] public void RemoveEventForNotAllowedTag_ScriptTag() { RemoveReason? actual = null; var s = new HtmlSanitizer(); s.RemovingTag += (sender, args) => { actual = args.Reason; }; s.Sanitize(""); Assert.Equal(RemoveReason.NotAllowedTag, actual); } [Fact] public void RemoveEventForNotAllowedTag_StyleTag() { RemoveReason? actual = null; var s = new HtmlSanitizer(); s.RemovingTag += (sender, args) => { actual = args.Reason; }; s.Sanitize(""); Assert.Equal(RemoveReason.NotAllowedTag, actual); } [Fact] public void RemoveEventForNotAllowedTag_ScriptTagAndSpan() { RemoveReason? actual = null; var s = new HtmlSanitizer(); s.RemovingTag += (sender, args) => { actual = args.Reason; }; s.Sanitize("Hi"); Assert.Equal(RemoveReason.NotAllowedTag, actual); } [Fact] public void DocumentTest() { var s = new HtmlSanitizer(); s.AllowedTags.Add("title"); var html = "Test
Test
"; var actual = s.SanitizeDocument(html); Assert.Equal(html, actual); } [Fact] public void DocumentFromFragmentTest() { var s = Sanitizer; var html = "
Test
"; var actual = s.SanitizeDocument(html); Assert.Equal("
Test
", actual); } [Fact] public void FragmentFromDocumentTest() { var s = Sanitizer; var html = "Test
Test
"; var actual = s.Sanitize(html); Assert.Equal("
Test
", actual); } [Fact] public void StyleTagTest() { var s = new HtmlSanitizer(); s.AllowedTags.Add("style"); var html = "
Test
"; var actual = s.SanitizeDocument(html); Assert.Equal("
Test
", actual); } [Fact] public void StyleAtTest() { var s = new HtmlSanitizer(); s.AllowedTags.Add("style"); s.AllowedAtRules.Add(AngleSharp.Dom.Css.CssRuleType.Media); s.AllowedAtRules.Add(AngleSharp.Dom.Css.CssRuleType.Keyframes); s.AllowedAtRules.Add(AngleSharp.Dom.Css.CssRuleType.Keyframe); s.AllowedAtRules.Add(AngleSharp.Dom.Css.CssRuleType.Page); var html = @""; var actual = s.SanitizeDocument(html); Assert.Equal(@"".Replace("\r\n", "\n"), actual); } [Fact] public void DataTest() { // https://github.com/mganss/HtmlSanitizer/issues/66 var sanitizer = new HtmlSanitizer() { AllowDataAttributes = true }; sanitizer.AllowedSchemes.Add("data"); var html = @"

".Replace("\r\n", "\n"); var actual = sanitizer.Sanitize(html); Assert.Equal(html, actual); } [Fact] public void UriHashTest() { var s = Sanitizer; var html = @"test"; var actual = s.Sanitize(html); Assert.Equal(html, actual); } [Fact] public void FragmentTest() { var s = Sanitizer; var html = @"

Test

"; var actual = s.Sanitize(html); Assert.Equal("

Test

", actual); } [Fact] public void OpenTagFragmentTest() { // https://github.com/mganss/HtmlSanitizer/issues/75 var s = Sanitizer; var html = "

abc Test4

"; var actual = sanitizer.Sanitize(html); Assert.Equal("Test1 Test2 Test3 Test4", actual); } [Fact] public void KeepChildNodesTest() { var sanitizer = new HtmlSanitizer { KeepChildNodes = true }; sanitizer.AllowedTags.Remove("div"); var html = @"Test1
Test2 Test4
"; var actual = sanitizer.Sanitize(html); Assert.Equal("Test1 Test2 Test3 Test4", actual); } [Fact] public void NormalizeTest() { var sanitizer = new HtmlSanitizer(); sanitizer.PostProcessNode += (s, e) => { Assert.Equal(1, e.Document.Body.ChildNodes.Count()); var text = e.Node as IText; Assert.NotNull(text); Assert.Equal("Test1Test2", text.NodeValue); }; var html = @"Test1Test2"; var actual = sanitizer.Sanitize(html); Assert.Equal("Test1Test2", actual); } [Fact] public void RemovingCommentTest() { var sanitizer = new HtmlSanitizer(); sanitizer.RemovingComment += (s, e) => e.Cancel = e.Comment.TextContent.Contains("good comment"); var html = @""; var actual = sanitizer.Sanitize(html); Assert.Equal("", actual); } [Fact] public void TrailingSlashTest() { var sanitizer = new HtmlSanitizer(); sanitizer.AllowedSchemes.Add("resources"); var html = ""; var actual = sanitizer.Sanitize(html); Assert.Equal(html, actual, ignoreCase: true); } [Fact] public void FileUrlTest() { var sanitizer = new HtmlSanitizer(); sanitizer.AllowedSchemes.Add("file"); var html = @"test"; var actual = sanitizer.Sanitize(html); Assert.Equal(html, actual); } } } #pragma warning restore 1591