Merge branch 'AngleSharp_0_10'

This commit is contained in:
Michael Ganss
2019-06-26 13:20:16 +02:00
10 changed files with 105 additions and 122 deletions

View File

@@ -6,10 +6,8 @@ HtmlSanitizer
[![codecov.io](https://codecov.io/github/mganss/HtmlSanitizer/coverage.svg?branch=master)](https://codecov.io/github/mganss/HtmlSanitizer?branch=master)
[![Sonarcloud Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=mganss_HtmlSanitizer&metric=alert_status)](https://sonarcloud.io/dashboard?id=mganss_HtmlSanitizer)
[![netstandard1.3](https://img.shields.io/badge/netstandard-1.3-brightgreen.svg)](https://img.shields.io/badge/netstandard-1.3-brightgreen.svg)
[![netstandard2.0](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg)](https://img.shields.io/badge/netstandard-2.0-brightgreen.svg)
[![net40](https://img.shields.io/badge/net-40-brightgreen.svg)](https://img.shields.io/badge/net-40-brightgreen.svg)
[![net45](https://img.shields.io/badge/net-45-brightgreen.svg)](https://img.shields.io/badge/net-45-brightgreen.svg)
[![net46](https://img.shields.io/badge/net-46-brightgreen.svg)](https://img.shields.io/badge/net-46-brightgreen.svg)
HtmlSanitizer is a .NET library for cleaning HTML fragments and documents from constructs that can lead to [XSS attacks](https://en.wikipedia.org/wiki/Cross-site_scripting).
It uses [AngleSharp](https://github.com/AngleSharp/AngleSharp) to parse, manipulate, and render HTML and CSS.

View File

@@ -1,4 +1,4 @@
version: 4.0.{build}
version: 5.0.{build}
skip_tags: true
image: Visual Studio 2017
environment:
@@ -18,12 +18,11 @@ test_script:
dotnet sonarscanner begin /k:"mganss_HtmlSanitizer" /v:$env:APPVEYOR_BUILD_VERSION /o:"mganss-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$env:sonar_token" /d:sonar.cs.opencover.reportsPaths="$($env:APPVEYOR_BUILD_FOLDER)\coverage.xml" /d:sonar.coverage.exclusions="**/Program.cs"
dotnet build
}
- dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput="..\..\coverage.xml" test\HtmlSanitizer.Tests\HtmlSanitizer.Tests.csproj -f netcoreapp2.0
- dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput="..\..\coverage.xml" test\HtmlSanitizer.Tests\HtmlSanitizer.Tests.csproj -f netcoreapp2.1
- ps: |
if (-not $env:APPVEYOR_PULL_REQUEST_NUMBER) {
dotnet sonarscanner end /d:sonar.login="$env:sonar_token"
}
- "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%"
- pip install codecov
- codecov -f "coverage.xml"
artifacts:

View File

@@ -1,6 +1,6 @@
using AngleSharp.Dom;
using AngleSharp.Dom.Css;
using AngleSharp.Dom.Html;
using AngleSharp.Css.Dom;
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using System;
using System.Collections.Generic;
using System.ComponentModel;

View File

@@ -1,7 +1,6 @@
using AngleSharp;
using AngleSharp.Html;
using AngleSharp.Dom;
using AngleSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -118,7 +117,7 @@ namespace Ganss.XSS
return HtmlMarkupFormatter.Instance.Processing(processing);
}
public virtual string Text(string text)
public virtual string Text(ICharacterData text)
{
return HtmlMarkupFormatter.Instance.Text(text);
}

View File

@@ -1,11 +1,9 @@
using AngleSharp;
using AngleSharp.Css.Dom;
using AngleSharp.Css.Parser;
using AngleSharp.Dom;
using AngleSharp.Dom.Css;
using AngleSharp.Dom.Html;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Parser.Css;
using AngleSharp.Parser.Html;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -462,7 +460,7 @@ namespace Ganss.XSS
public IHtmlDocument SanitizeDom(string html, string baseUrl = "")
{
var parser = HtmlParserFactory();
var dom = parser.Parse("<html><body>" + html);
var dom = parser.ParseDocument("<html><body>" + html);
DoSanitize(dom, dom.Body, baseUrl);
@@ -479,16 +477,14 @@ namespace Ganss.XSS
public string SanitizeDocument(string html, string baseUrl = "", IMarkupFormatter outputFormatter = null)
{
var parser = HtmlParserFactory();
var dom = parser.ParseDocument(html);
using (var dom = parser.Parse(html))
{
DoSanitize(dom, dom, baseUrl);
var output = dom.ToHtml(outputFormatter ?? OutputFormatter);
return output;
}
}
/// <summary>
/// Sanitizes the specified HTML document. Even if only a fragment is given, a whole document will be returned.
@@ -500,16 +496,14 @@ namespace Ganss.XSS
public string SanitizeDocument(Stream html, string baseUrl = "", IMarkupFormatter outputFormatter = null)
{
var parser = HtmlParserFactory();
var dom = parser.ParseDocument(html);
using (var dom = parser.Parse(html))
{
DoSanitize(dom, dom, baseUrl);
var output = dom.ToHtml(outputFormatter ?? OutputFormatter);
return output;
}
}
/// <summary>
/// Creeates an instance of <see cref="HtmlParser"/>.
@@ -517,13 +511,12 @@ namespace Ganss.XSS
/// <returns>An instance of <see cref="HtmlParser"/>.</returns>
private static HtmlParser CreateParser()
{
return new HtmlParser(new Configuration().WithCss(e => e.Options = new CssParserOptions
return new HtmlParser(new HtmlParserOptions(), BrowsingContext.New(new Configuration().WithCss(new CssParserOptions
{
IsIncludingUnknownDeclarations = true,
IsIncludingUnknownRules = true,
IsToleratingInvalidConstraints = true,
IsToleratingInvalidValues = true
}));
IsToleratingInvalidSelectors = true,
})));
}
/// <summary>
@@ -750,14 +743,14 @@ namespace Ganss.XSS
// filter out invalid CSS declarations
// see https://github.com/AngleSharp/AngleSharp/issues/101
if (element.GetAttribute("style") == null) return;
if (element.Style == null)
if (element.GetStyle() == null)
{
element.RemoveAttribute("style");
return;
}
element.SetAttribute("style", element.Style.ToCss());
element.SetAttribute("style", element.GetStyle().ToCss());
var styles = element.Style;
var styles = element.GetStyle();
if (styles == null || styles.Length == 0) return;
SanitizeStyleDeclaration(element, styles, baseUrl);

View File

@@ -5,11 +5,11 @@
<Copyright>Copyright 2013-$([System.DateTime]::Now.Year) Michael Ganss</Copyright>
<AssemblyTitle>HtmlSanitizer</AssemblyTitle>
<AppVeyor_Build_Version Condition="'$(APPVEYOR_BUILD_VERSION)' == ''">1.0.0</AppVeyor_Build_Version>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<AssemblyVersion>5.0.0.0</AssemblyVersion>
<FileVersion>$(AppVeyor_Build_Version).0</FileVersion>
<PackageVersion>$(AppVeyor_Build_Version)</PackageVersion>
<PackageVersion>$(AppVeyor_Build_Version)-beta</PackageVersion>
<Authors>Michael Ganss</Authors>
<TargetFrameworks>net40;net45;netstandard1.3;netstandard2.0;</TargetFrameworks>
<TargetFrameworks>net46;netstandard2.0</TargetFrameworks>
<AssemblyName>HtmlSanitizer</AssemblyName>
<AssemblyOriginatorKeyFile>HtmlSanitizer.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
@@ -20,28 +20,26 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>git://github.com/mganss/HtmlSanitizer</RepositoryUrl>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.3' ">$(PackageTargetFallback);dotnet</PackageTargetFallback>
<AppConfig Condition="'$(TargetFramework)' == 'net40'">app.net40.config</AppConfig>
<AutoUnifyAssemblyReferences Condition="'$(TargetFramework)' == 'net40'">false</AutoUnifyAssemblyReferences>
<RootNamespace>Ganss.XSS</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\HtmlSanitizer.xml</DocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AngleSharp" Version="[0.9.11]" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19324-01" PrivateAssets="All"/>
<PackageReference Include="AngleSharp" Version="[0.12.1]" />
<PackageReference Include="AngleSharp.Css" Version="[0.12.1]" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19270-01" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' or '$(TargetFramework)' == 'net45'">
<ItemGroup Condition=" '$(TargetFramework)' == 'net46'">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,7 @@
using AngleSharp;
using AngleSharp.Dom.Css;
using AngleSharp.Dom.Html;
using AngleSharp.Parser.Html;
using AngleSharp.Css.Dom;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

View File

@@ -1,15 +0,0 @@
<?xml version ="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;netcoreapp2.0;net46</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;net46</TargetFrameworks>
<AssemblyName>HtmlSanitizer.Tests</AssemblyName>
<PackageId>HtmlSanitizer.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
@@ -19,6 +19,8 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Net" />
<ProjectReference Include="..\..\src\HtmlSanitizer\HtmlSanitizer.csproj" />
</ItemGroup>
@@ -28,6 +30,12 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
<PackageReference Include="AngleSharp.Xml" Version="0.12.1" />
<PackageReference Include="coverlet.msbuild" Version="2.6.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>

View File

@@ -1,17 +1,17 @@
using AngleSharp;
using AngleSharp.Css.Dom;
using AngleSharp.Dom;
using AngleSharp.Dom.Html;
using AngleSharp.Parser.Html;
using Xunit;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;
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;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Xunit;
// Tests based on tests from http://roadkill.codeplex.com/
@@ -533,7 +533,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment);
// Assert
string expected = "<div></div>";
string expected = "<div style=\"\"></div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -1583,7 +1583,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment);
// Assert
string expected = "<div style=\"background-color: test\"></div>";
string expected = "<div></div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -1601,7 +1601,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment);
// Assert
string expected = "<div style=\"background-color: test\">Test<img src=\"http://www.example.com/test.gif\" style=\"background-image: url(&quot;http://www.example.com/bg.jpg&quot;); margin: 10px\"></div>";
string expected = "<div>Test<img src=\"http://www.example.com/test.gif\" style=\"background-image: url(&quot;http://www.example.com/bg.jpg&quot;); margin: 10px\"></div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -1670,7 +1670,7 @@ S
html = @"<div style=""background-color: red""><sCRipt>hallo</scripT></div><a href=""#"">Test</a>";
actual = sanitizer.Sanitize(html);
expected = @"<div style=""background-color: red""></div><a href=""#"">Test</a>";
expected = @"<div style=""background-color: rgba(255, 0, 0, 1)""></div><a href=""#"">Test</a>";
Assert.Equal(expected, actual, ignoreCase: true);
html = @"<IMG SRC=""jav ascript:alert('XSS');"">";
@@ -1698,9 +1698,9 @@ S
expected = "<img>";
Assert.Equal(expected, actual, ignoreCase: true);
html = "<script>alert('xss')</script><div onload=\"alert('xss')\" style=\"background-color: test\">Test<img src=\"test.gif\" style=\"background-image: url(javascript:alert('xss')); margin: 10px\"></div>";
html = "<script>alert('xss')</script><div onload=\"alert('xss')\" style=\"background-color: red\">Test<img src=\"test.gif\" style=\"background-image: url(javascript:alert('xss')); margin: 10px\"></div>";
actual = sanitizer.Sanitize(html, "http://www.example.com");
expected = @"<div style=""background-color: test"">Test<img src=""http://www.example.com/test.gif"" style=""margin: 10px""></div>";
expected = @"<div style=""background-color: rgba(255, 0, 0, 1)"">Test<img src=""http://www.example.com/test.gif"" style=""margin: 10px""></div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -1876,33 +1876,33 @@ S
{
var sanitizer = Sanitizer;
// Inline style with url() using javascript: scheme
var html = @"<DIV STYLE='background: url(javascript:alert(""foo""))'>";
var html = @"<DIV STYLE='background-image: url(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
// Inline style with url() using javascript: scheme, using control char
html = @"<DIV STYLE='background: url(&#1;javascript:alert(""foo""))'>";
html = @"<DIV STYLE='background-image: url(&#1;javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
// Inline style with url() using javascript: scheme, in quotes
html = @"<DIV STYLE='background: url(""javascript:alert(foo)"")'>";
html = @"<DIV STYLE='background-image: url(""javascript:alert(foo)"")'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
// IE expressions in CSS not allowed
html = @"<DIV STYLE='width: expression(alert(""foo""));'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='width: e/**/xpression(alert(""foo""));'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background: url(javascript:alert(""foo""));color: #fff'>";
Assert.Equal(@"<div style=""color: #fff""></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background-image: url(javascript:alert(""foo""));color: #fff'>";
Assert.Equal(@"<div style=""color: rgba(255, 255, 255, 1)""></div>", sanitizer.Sanitize(html), ignoreCase: true);
// Inline style with url() using javascript: scheme, using unicode
// escapes
html = @"<DIV STYLE='background: \75rl(javascript:alert(""foo""))'>";
html = @"<DIV STYLE='background-image: \75rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background: \000075rl(javascript:alert(""foo""))'>";
html = @"<DIV STYLE='background-image: \000075rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background: \75 rl(javascript:alert(""foo""))'>";
html = @"<DIV STYLE='background-image: \75 rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background: \000075 rl(javascript:alert(""foo""))'>";
html = @"<DIV STYLE='background-image: \000075 rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<DIV STYLE='background: \000075
html = @"<DIV STYLE='background-image: \000075
rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<div></div>", sanitizer.Sanitize(html), ignoreCase: true);
}
@@ -2031,7 +2031,7 @@ rl(javascript:alert(""foo""))'>";
{
var sanitizer = Sanitizer;
var html = @"<div style=""display:none;border-left-color:red;userDefined:1;-moz-user-selct:-moz-all"">prop</div>";
Assert.Equal(@"<div style=""display: none; border-left-color: red"">prop</div>", sanitizer.Sanitize(html), ignoreCase: true);
Assert.Equal(@"<div style=""display: none; border-left-color: rgba(255, 0, 0, 1)"">prop</div>", sanitizer.Sanitize(html), ignoreCase: true);
}
[Fact]
@@ -2089,9 +2089,9 @@ rl(javascript:alert(""foo""))'>";
public void RemovingStyleEventTest()
{
var sanitizer = new HtmlSanitizer();
sanitizer.RemovingStyle += (s, e) => e.Cancel = e.Style.Name == "test";
var html = @"<div style=""background: 0; test: xyz; bad: bad;""></div>";
Assert.Equal(@"<div style=""background: 0; test: xyz""></div>", sanitizer.Sanitize(html), ignoreCase: true);
sanitizer.RemovingStyle += (s, e) => e.Cancel = e.Style.Name == "column-count";
var html = @"<div style=""top: 1px; column-count: 3;""></div>";
Assert.Equal(@"<div style=""top: 1px; column-count: 3""></div>", sanitizer.Sanitize(html), ignoreCase: true);
}
[Fact]
@@ -2214,7 +2214,7 @@ rl(javascript:alert(""foo""))'>";
var autolinked = Regex.Replace(text.NodeValue, @"https?://[^\s]+[^\s!?.:;,]+", m => $@"<a href=""{m.Value}"">{m.Value}</a>", RegexOptions.IgnoreCase);
if (autolinked != text.NodeValue)
{
var f = new HtmlParser().Parse(autolinked);
var f = new HtmlParser().ParseDocument(autolinked);
foreach (var node in f.Body.ChildNodes)
e.ReplacementNodes.Add(node);
}
@@ -2244,14 +2244,14 @@ rl(javascript:alert(""foo""))'>";
public void DisallowCssPropertyValueTest()
{
// Arrange
var s = new HtmlSanitizer { DisallowCssPropertyValue = new Regex("^b.*") };
var s = new HtmlSanitizer { DisallowCssPropertyValue = new Regex(@"^rgba\(0.*") };
// Act
var htmlFragment = @"<div style=""color: black; background-color: white"">Test</div>";
var htmlFragment = @"<div style=""color: rgba(0, 0, 0, 1); background-color: rgba(255, 255, 255, 1)"">Test</div>";
var actual = s.Sanitize(htmlFragment);
// Assert
var expected = @"<div style=""background-color: white"">Test</div>";
var expected = @"<div style=""background-color: rgba(255, 255, 255, 1)"">Test</div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -2277,11 +2277,11 @@ rl(javascript:alert(""foo""))'>";
var s = Sanitizer;
// Act
var htmlFragment = @"<div style=""color: black; background-image: URL(x/y/bg.jpg)"">Test</div>";
var htmlFragment = @"<div style=""color: rgba(0, 0, 0, 1); background-image: URL(x/y/bg.jpg)"">Test</div>";
var actual = s.Sanitize(htmlFragment, "hallo");
// Assert
var expected = @"<div style=""color: black"">Test</div>";
var expected = @"<div style=""color: rgba(0, 0, 0, 1)"">Test</div>";
Assert.Equal(expected, actual, ignoreCase: true);
}
@@ -2427,16 +2427,19 @@ rl(javascript:alert(""foo""))'>";
{
var allowedTags = new[] { "a" };
var allowedAttributes = new[] { "style" };
var allowedStyles = new[] { "margin" };
var allowedStyles = new[] { "margin-top" };
RemoveReason? actual = null;
var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles);
var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles)
{
DisallowCssPropertyValue = new Regex(@"\d+.*")
};
s.RemovingStyle += (sender, args) =>
{
actual = args.Reason;
};
s.Sanitize("<a style=\"margin:expression(alert('xss'))\">just any content</a>");
s.Sanitize("<a style=\"margin-top:17px\">just any content</a>");
Assert.Equal(RemoveReason.NotAllowedValue, actual);
}
@@ -2465,7 +2468,7 @@ rl(javascript:alert(""foo""))'>";
{
var allowedTags = new[] { "a" };
var allowedAttributes = new[] { "style" };
var allowedStyles = new[] { "background" };
var allowedStyles = new[] { "background-image" };
RemoveReason? actual = null;
var s = new HtmlSanitizer(allowedTags: allowedTags, allowedAttributes: allowedAttributes, allowedCssProperties: allowedStyles);
@@ -2474,7 +2477,7 @@ rl(javascript:alert(""foo""))'>";
actual = args.Reason;
};
s.Sanitize("<a style=\"background:url(javascript:alert('xss'))\">just any content</a>");
var h = s.Sanitize("<a style=\"background-image:url(javascript:alert('xss'))\">just any content</a>");
Assert.Equal(RemoveReason.NotAllowedUrlValue, actual);
}
@@ -2595,11 +2598,11 @@ rl(javascript:alert(""foo""))'>";
{
var s = new HtmlSanitizer();
s.AllowedTags.Add("style");
var html = "<html><head><style>body { background-color: white; hallo-ballo: xyz }</style></head><body><div>Test</div></body></html>";
var html = "<html><head><style>body { background-color: rgba(255, 255, 255, 1); hallo-ballo: xyz }</style></head><body><div>Test</div></body></html>";
var actual = s.SanitizeDocument(html);
Assert.Equal("<html><head><style>body { background-color: white }</style></head><body><div>Test</div></body></html>", actual);
Assert.Equal("<html><head><style>body { background-color: rgba(255, 255, 255, 1) }</style></head><body><div>Test</div></body></html>", actual);
}
[Fact]
@@ -2607,17 +2610,17 @@ rl(javascript:alert(""foo""))'>";
{
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);
s.AllowedAtRules.Add(AngleSharp.Css.Dom.CssRuleType.Media);
s.AllowedAtRules.Add(AngleSharp.Css.Dom.CssRuleType.Keyframes);
s.AllowedAtRules.Add(AngleSharp.Css.Dom.CssRuleType.Keyframe);
s.AllowedAtRules.Add(AngleSharp.Css.Dom.CssRuleType.Page);
var html = @"<html><head><style>
@charset ""UTF-8"";
@import url(evil.css);
@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);
@media (min-width: 100px) {
div { color: black; }
div { color: rgba(0, 0, 0, 1); }
@font-face { font-family: test }
}
@supports (--foo: green) {
@@ -2638,17 +2641,17 @@ rl(javascript:alert(""foo""))'>";
background: yellow;
}
}
@page { size:8.5in 11in; margin: 2cm }
@page { size:8.5in 11in; margin-top: 2cm }
@font-face {
font-family: ""Bitstream Vera Serif Bold""
src: url(""https://mdn.mozillademos.org/files/2468/VeraSeBd.ttf"");
color: black;
color: rgba(0, 0, 0, 1);
}
@keyframes identifier {
0% { top: 0; }
50% { top: 30px; left: 20px; }
50% { top: 10px; }
100% { top: 0; background: url('javascript:alert(xss)') }
100% { top: 0; background-image: url('javascript:alert(xss)') }
}
@viewport {
min-width: 640px;
@@ -2670,8 +2673,8 @@ rl(javascript:alert(""foo""))'>";
Assert.Equal(@"<html><head><style>@namespace url(""http://www.w3.org/1999/xhtml"");
@namespace svg url(""http://www.w3.org/2000/svg"");
@media (min-width: 100px) { div { color: black } }
@page { margin: 2cm }
@media (min-width: 100px) { div { color: rgba(0, 0, 0, 1) } }
@page { margin-top: 2cm }
@keyframes identifier { 0% { top: 0 } 50% { top: 30px; left: 20px } 50% { top: 10px } 100% { top: 0 } }</style></head><body></body></html>".Replace("\r\n", "\n"),
actual);
}
@@ -2801,7 +2804,7 @@ zqy1QY1kkPOuMvKWvvmFIwClI2393jVVcp91eda4+J+fIYDbfJa7RY5YcNrZhTuV//9k="">
{
// https://github.com/mganss/HtmlSanitizer/issues/81
var s = new HtmlSanitizer { HtmlParserFactory = () => new HtmlParser(new Configuration()) };
var s = new HtmlSanitizer { HtmlParserFactory = () => new HtmlParser(new HtmlParserOptions(), BrowsingContext.New(new Configuration())) };
var html = @"<p style=""t"">xyz</p>";
var actual = s.Sanitize(html);
@@ -2814,7 +2817,7 @@ zqy1QY1kkPOuMvKWvvmFIwClI2393jVVcp91eda4+J+fIYDbfJa7RY5YcNrZhTuV//9k="">
{
// https://github.com/mganss/HtmlSanitizer/issues/84
var s = new HtmlSanitizer { HtmlParserFactory = () => new HtmlParser(new Configuration()) };
var s = new HtmlSanitizer { HtmlParserFactory = () => new HtmlParser(new HtmlParserOptions(), BrowsingContext.New(new Configuration())) };
var html = @"<input type=""text"" name=""my_name"" value=""<insert name>"">";
var actual = s.Sanitize(html);