Update to VS 2017

Use System.Uri only for resolving relative URLs (fixes #118, fixes #106, fixes #66)
This commit is contained in:
Michael Ganss
2017-04-12 16:01:42 +02:00
parent 2e70ad9160
commit 255fd58ea6
16 changed files with 179 additions and 396 deletions

View File

@@ -1,35 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{422273A8-89FB-489C-9CEE-378B39D48C45}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EEC64896-0470-41A0-BCE9-118DE051CB4C}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "HtmlSanitizer", "src\HtmlSanitizer\HtmlSanitizer.xproj", "{CCDB0C26-D683-4943-B5D8-AC07116461E5}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "HtmlSanitizer.Tests", "test\HtmlSanitizer.Tests\HtmlSanitizer.Tests.xproj", "{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CCDB0C26-D683-4943-B5D8-AC07116461E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCDB0C26-D683-4943-B5D8-AC07116461E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCDB0C26-D683-4943-B5D8-AC07116461E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCDB0C26-D683-4943-B5D8-AC07116461E5}.Release|Any CPU.Build.0 = Release|Any CPU
{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 15
VisualStudioVersion = 14.0.23107.0 VisualStudioVersion = 15.0.26403.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlSanitizer", "src\HtmlSanitizer\HtmlSanitizer.csproj", "{CCDB0C26-D683-4943-B5D8-AC07116461E5}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlSanitizer", "src\HtmlSanitizer\HtmlSanitizer.csproj", "{CCDB0C26-D683-4943-B5D8-AC07116461E5}"
EndProject EndProject

View File

@@ -1,6 +0,0 @@
{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-preview1-002702"
}
}

View File

@@ -684,7 +684,7 @@ namespace Ganss.XSS
if (urls.Count > 0) if (urls.Count > 0)
{ {
if (urls.Cast<Match>().Any(m => GetSafeUri(m.Groups[2].Value) == null || SanitizeUrl(m.Groups[2].Value, baseUrl) == null)) if (urls.Cast<Match>().Any(m => SanitizeUrl(m.Groups[2].Value, baseUrl) == null))
removeStyles.Add(new Tuple<ICssProperty, RemoveReason>(style, RemoveReason.NotAllowedUrlValue)); removeStyles.Add(new Tuple<ICssProperty, RemoveReason>(style, RemoveReason.NotAllowedUrlValue));
else else
{ {
@@ -732,29 +732,24 @@ namespace Ganss.XSS
return r; return r;
} }
private static readonly Regex SchemeRegex = new Regex(@"^\s*([^\/#]*?)(?:\:|&#0*58|&#x0*3a)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
/// <summary> /// <summary>
/// Tries to create a safe <see cref="Uri"/> object from a string. /// Tries to create a safe <see cref="Iri"/> object from a string.
/// </summary> /// </summary>
/// <param name="url">The URL.</param> /// <param name="url">The URL.</param>
/// <returns>The <see cref="Uri"/> object or null if no safe <see cref="Uri"/> can be created.</returns> /// <returns>The <see cref="Iri"/> object or null if no safe <see cref="Iri"/> can be created.</returns>
protected Uri GetSafeUri(string url) protected Iri GetSafeIri(string url)
{ {
Uri uri; var schemeMatch = SchemeRegex.Match(url);
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri)
|| !uri.IsAbsoluteUri && !IsWellFormedRelativeUri(uri)
|| uri.IsAbsoluteUri && !AllowedSchemes.Contains(uri.Scheme, StringComparer.OrdinalIgnoreCase))
return null;
return uri; if (schemeMatch.Success)
} {
var scheme = schemeMatch.Groups[1].Value;
return AllowedSchemes.Contains(scheme, StringComparer.OrdinalIgnoreCase) ? new Iri { Value = url, Scheme = scheme } : null;
}
private static readonly Uri _exampleUri = new Uri("http://www.example.com/"); return new Iri { Value = url };
private static bool IsWellFormedRelativeUri(Uri uri)
{
if (uri.IsAbsoluteUri) return false;
Uri absoluteUri;
return Uri.TryCreate(_exampleUri, uri, out absoluteUri) && !uri.OriginalString.Contains(":");
} }
/// <summary> /// <summary>
@@ -765,27 +760,28 @@ namespace Ganss.XSS
/// <returns>The sanitized URL or null if no safe URL can be created.</returns> /// <returns>The sanitized URL or null if no safe URL can be created.</returns>
protected string SanitizeUrl(string url, string baseUrl) protected string SanitizeUrl(string url, string baseUrl)
{ {
var uri = GetSafeUri(url); var iri = GetSafeIri(url);
if (uri == null) return null; if (iri == null) return null;
if (!uri.IsAbsoluteUri && !string.IsNullOrEmpty(baseUrl)) if (!iri.IsAbsolute && !string.IsNullOrEmpty(baseUrl))
{ {
// resolve relative uri // resolve relative uri
Uri baseUri; if (Uri.TryCreate(baseUrl, UriKind.Absolute, out Uri baseUri))
if (Uri.TryCreate(baseUrl, UriKind.Absolute, out baseUri)) {
uri = new Uri(baseUri, uri.ToString()); try
{
return new Uri(baseUri, iri.Value).AbsoluteUri;
}
catch (UriFormatException)
{
return null;
}
}
else return null; else return null;
} }
try return iri.Value;
{
return uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
}
catch (UriFormatException)
{
return null;
}
} }
/// <summary> /// <summary>

View File

@@ -1,82 +1,54 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration> <Description>Cleans HTML from constructs that can be used for cross site scripting (XSS)</Description>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Copyright>Copyright 2013-2016 Michael Ganss</Copyright>
<ProjectGuid>{CCDB0C26-D683-4943-B5D8-AC07116461E5}</ProjectGuid> <AssemblyTitle>HtmlSanitizer</AssemblyTitle>
<OutputType>Library</OutputType> <VersionPrefix>1.0.0-VERSION</VersionPrefix>
<AppDesignerFolder>Properties</AppDesignerFolder> <Authors>Michael Ganss</Authors>
<RootNamespace>Ganss.XSS</RootNamespace> <TargetFrameworks>net40;net45;netstandard1.3</TargetFrameworks>
<AssemblyName>HtmlSanitizer</AssemblyName> <AssemblyName>HtmlSanitizer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<IntermediateOutputPath>obj\Debug\net45\</IntermediateOutputPath>
<OutputPath>bin\Debug\net45\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>false</RunCodeAnalysis>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>bin\Debug\net45\HtmlSanitizer.XML</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<IntermediateOutputPath>obj\Release\net45\</IntermediateOutputPath>
<OutputPath>bin\Release\net45\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\net45\HtmlSanitizer.XML</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>HtmlSanitizer.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>HtmlSanitizer.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>HtmlSanitizer</PackageId>
<PackageTags>xss;anti;antixss;html;security</PackageTags>
<PackageProjectUrl>https://github.com/mganss/HtmlSanitizer</PackageProjectUrl>
<PackageLicenseUrl>https://raw.github.com/mganss/HtmlSanitizer/master/LICENSE.md</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>git://github.com/mganss/HtmlSanitizer</RepositoryUrl>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.3' ">$(PackageTargetFallback);dotnet</PackageTargetFallback>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<AppConfig Condition="'$(TargetFramework)' == 'net40'">app.net40.config</AppConfig>
<AutoUnifyAssemblyReferences Condition="'$(TargetFramework)' == 'net40'">false</AutoUnifyAssemblyReferences>
<RootNamespace>Ganss.XSS</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AngleSharp" Version="[0.9.9]" />
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="EventArgs.cs" /> <ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Compile Include="HtmlFormatter.cs" /> <Reference Include="System.Globalization" />
<Compile Include="HtmlSanitizer.cs" /> <Reference Include="System.IO" />
<Compile Include="IHtmlSanitizer.cs" /> <Reference Include="System.Runtime" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Reference Include="System" />
<Compile Include="RemoveReason.cs" /> <Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="HtmlSanitizer.snk" /> <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);NETSTANDARD</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
<Reference Include="System.ComponentModel" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. </Project>
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,11 +0,0 @@
{
"dependencies": {
"AngleSharp": "[0.9.9]"
},
"frameworks": {
"net45": {}
},
"runtimes": {
"win": {}
}
}

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>ccdb0c26-d683-4943-b5d8-ac07116461e5</ProjectGuid>
<RootNamespace>Ganss.XSS</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

14
src/HtmlSanitizer/Iri.cs Normal file
View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ganss.XSS
{
public class Iri
{
public string Value { get; set; }
public bool IsAbsolute => !string.IsNullOrEmpty(Scheme);
public string Scheme { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
<?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,54 +0,0 @@
{
"version": "1.0.0-VERSION",
"title": "HtmlSanitizer",
"description": "Cleans HTML from constructs that can be used for cross site scripting (XSS)",
"authors": [ "Michael Ganss" ],
"copyright": "Copyright 2013-2016 Michael Ganss",
"packOptions": {
"projectUrl": "https://github.com/mganss/HtmlSanitizer",
"tags": [ "xss", "anti", "antixss", "html", "security" ],
"licenseUrl": "https://raw.github.com/mganss/HtmlSanitizer/master/LICENSE.md",
"repository": {
"type": "git",
"url": "git://github.com/mganss/HtmlSanitizer"
}
},
"buildOptions": {
"keyFile": "HtmlSanitizer.snk"
},
"dependencies": {
"AngleSharp": "[0.9.9]"
},
"frameworks": {
"net40": {
"frameworkAssemblies": {
}
},
"net45": {
"frameworkAssemblies": {
"System.Globalization": { "type": "build" },
"System.IO": { "type": "build" },
"System.Runtime": { "type": "build" }
}
},
"netstandard1.3": {
"imports": "dotnet",
"buildOptions": {
"define": [
"NETSTANDARD"
]
},
"dependencies": {
"System.Collections": "4.0.11",
"System.ComponentModel": "4.0.1",
"System.Diagnostics.Debug": "4.0.11",
"System.Globalization": "4.0.11",
"System.Linq": "4.1.0",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Text.RegularExpressions": "4.1.0",
"System.Threading": "4.0.11"
}
}
}
}

View File

@@ -1,93 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFrameworks>netcoreapp1.0;net452</TargetFrameworks>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55D772A0-8D8C-4CF7-A876-E6DAB8ED42C0}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Ganss.XSS.Tests</RootNamespace>
<AssemblyName>HtmlSanitizer.Tests</AssemblyName> <AssemblyName>HtmlSanitizer.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> <PackageId>HtmlSanitizer.Tests</PackageId>
<FileAlignment>512</FileAlignment> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dnxcore50;portable-net45+win8</PackageTargetFallback>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">1.0.4</RuntimeFrameworkVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<IsCodedUITest>False</IsCodedUITest> <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<TestProjectType>UnitTest</TestProjectType> <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<TargetFrameworkProfile /> <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<NuGetPackageImportStamp> <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<IntermediateOutputPath>obj\Debug\net451\</IntermediateOutputPath>
<OutputPath>bin\Debug\net451</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<IntermediateOutputPath>obj\Release\net451\</IntermediateOutputPath>
<OutputPath>bin\Release\net451</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\HtmlSanitizer\HtmlSanitizer.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="xunit.runner.console" Version="2.2.0" />
<PackageReference Include="xunit" Version="2.2.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Net" /> <Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise />
</Choose>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
<Compile Include="Tests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\HtmlSanitizer\HtmlSanitizer.csproj"> </Project>
<Project>{ccdb0c26-d683-4943-b5d8-ac07116461e5}</Project>
<Name>HtmlSanitizer</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,12 +0,0 @@
{
"dependencies": {
"xunit": "2.1.0",
"xunit.runner.visualstudio": "2.1.0"
},
"frameworks": {
"net451": { }
},
"runtimes": {
"win": { }
}
}

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>55d772a0-8d8c-4cf7-a876-e6dab8ed42c0</ProjectGuid>
<RootNamespace>Ganss.XSS.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -2,7 +2,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("HtmlSanitizer.Tests")] [assembly: AssemblyTitle("HtmlSanitizer.Tests")]
@@ -14,8 +14,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
@@ -25,11 +25,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
// Major Version // Major Version
// Minor Version // Minor Version
// Build Number // Build Number
// Revision // Revision
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")]

View File

@@ -1150,7 +1150,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3CSCRIPT/XSS%20SRC="">""&gt;XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;SCRIPT/XSS SRC=\">\"&gt;XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1250,7 +1250,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3C%3CSCRIPT%3Ealert("">""&gt;XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;&lt;SCRIPT&gt;alert(\">\"&gt;XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1349,7 +1349,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3CSCRIPT%20SRC=//ha.ckers.org/.j%3E"">XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;SCRIPT SRC=//ha.ckers.org/.j&gt;\">XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1409,7 +1409,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3CSCRIPT%3Ea=/XSS/alert(a.source)%3C/SCRIPT%3E"">XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;SCRIPT&gt;a=/XSS/alert(a.source)&lt;/SCRIPT&gt;\">XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1469,7 +1469,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%C2%BCscript%C2%BEalert(%C2%A2XSS%C2%A2)%C2%BC/script%C2%BE"">XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=¼script¾alert(¢XSS¢)¼/script¾\">XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1488,7 +1488,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3C!--[if%20gte%20IE%204]%3E%3CSCRIPT%3Ealert('XSS');%3C/SCRIPT%3E%3C![endif]--%3E"">XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;!--[if gte IE 4]&gt;&lt;SCRIPT&gt;alert('XSS');&lt;/SCRIPT&gt;&lt;![endif]--&gt;\">XSS</a>";
try try
{ {
@@ -1542,7 +1542,7 @@ S
string actual = sanitizer.Sanitize(htmlFragment); string actual = sanitizer.Sanitize(htmlFragment);
// Assert // Assert
string expected = @"<a href=""http://www.codeplex.com/?url=%3CSCRIPT%20a="">"" SRC=""http://ha.ckers.org/xss.js""&gt;""&gt;XSS</a>"; string expected = "<a href=\"http://www.codeplex.com?url=&lt;SCRIPT a=\">\" SRC=\"http://ha.ckers.org/xss.js\"&gt;\"&gt;XSS</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -1744,7 +1744,7 @@ S
html = @"<a href=""http:xxx"">test</a>"; html = @"<a href=""http:xxx"">test</a>";
actual = sanitizer.Sanitize(html); actual = sanitizer.Sanitize(html);
expected = @"<a>test</a>"; expected = @"<a href=""http:xxx"">test</a>";
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
html = @"<a href=""folder/file.jpg"">test</a>"; html = @"<a href=""folder/file.jpg"">test</a>";
@@ -1796,7 +1796,7 @@ S
Assert.Equal(@"<a href=""#"">fo<br>o</a>", sanitizer.Sanitize(html), ignoreCase: true); Assert.Equal(@"<a href=""#"">fo<br>o</a>", sanitizer.Sanitize(html), ignoreCase: true);
html = @"<a href=""#with:colon"">foo</a>"; html = @"<a href=""#with:colon"">foo</a>";
Assert.Equal(@"<a>foo</a>", sanitizer.Sanitize(html), ignoreCase: true); Assert.Equal(html, sanitizer.Sanitize(html), ignoreCase: true);
} }
[Fact] [Fact]
@@ -2291,7 +2291,7 @@ rl(javascript:alert(""foo""))'>";
var actual = s.Sanitize(htmlFragment); var actual = s.Sanitize(htmlFragment);
// Assert // Assert
var expected = @"<a>Bang Bang</a>"; var expected = htmlFragment;
Assert.Equal(expected, actual, ignoreCase: true); Assert.Equal(expected, actual, ignoreCase: true);
} }
@@ -2623,7 +2623,6 @@ rl(javascript:alert(""foo""))'>";
var sanitizer = new HtmlSanitizer(); var sanitizer = new HtmlSanitizer();
sanitizer.AllowDataAttributes = true; sanitizer.AllowDataAttributes = true;
sanitizer.AllowedSchemes.Add("data"); sanitizer.AllowedSchemes.Add("data");
sanitizer.RemovingAttribute += (s, e) => e.Cancel = e.Reason == RemoveReason.NotAllowedUrlValue && e.Attribute.Value.Length >= 0xfff0 && e.Attribute.Value.StartsWith("data:", StringComparison.OrdinalIgnoreCase);
var html = @" <p> var html = @" <p>
<img src=""data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAFvAeoDASIAAhEBAxEB/8QAHgAAAAcBAQEBAAAAAAAAAAAAAgMEBQYHCAEJAAr/xABrEAABAwMCAwQGBQQHEA0JBwUBAgMEAAURBiEHEjEIE0FRCRQiYXGBFTJCkaEjM7HBFhdSYnXR0iQ1NzhDY3J2gpKis7TU4fAYGSU0VnSEhZSVsrXCJicoNkZTZnOjREVUV4Ok8VVkZZOW/8QAHAEAAQUBAQEAAAAAAAAAAAAABAECAwUGAAcI/8QAOhEAAQQBBAADBQYFAwQDAAAAAQACAxEEBRIhMRNBUQYUImFxIzIzNIGRFSRCocEHUrE10eHwFkPx/9oADAMBAAIRAxEAPwCsOwKgjhLKXyKx9NPjPcjH5tv7f6v4q2HaSAEn34rIfYBCVcIZWA3kXqQT7auf8214dMfj0rXMJB5UFJ99eg6T/wBPZ+q8+1gVqDz9FMLYsnpUpgrWEDIO25qJWhwEdOlSmG7gAJzvQWX2psY8J7hvpKMg7e+liHfZ26im+OAU9cY8KVt486qZGgqxj6S5K87k184okkjxopC84GK6tWUKHT30KGU5EB3HCbLmvmSoKwAn3+NQe4pBeJT0zUynILqVJK8eJNRWe2hJwjfNW2JwhJk1Hf5UFQPKTR6kZxQe5Uds1at55QDuklaAWr6uaOdjnuiQnrSlEUpGMDJo9TQDeD51KH0oCwO7UXlW3vle0jPz60mFlTn2B8RUuLDRweXpQkMtg55QanGU7pRe7hRL6ASGQQklWab5FsUhRSp <img src=""data:image/jpeg;base64,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
@@ -2921,6 +2920,32 @@ zqy1QY1kkPOuMvKWvvmFIwClI2393jVVcp91eda4+J+fIYDbfJa7RY5YcNrZhTuV//9k="">
Assert.Equal("<!-- good comment -->", actual); Assert.Equal("<!-- good comment -->", actual);
} }
[Fact]
public void TrailingSlashTest()
{
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedSchemes.Add("resources");
var html = "<IMG src=\"resources://ais_w20_h20_33ba129c.png\">";
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 = @"<a href=""file:///C:/exampleㄓ.txt"">test</a>";
var actual = sanitizer.Sanitize(html);
Assert.Equal(html, actual);
}
} }
} }

View File

@@ -1,31 +0,0 @@
{
"version": "1.0.0-*",
"testRunner": "xunit",
"dependencies": {
"HtmlSanitizer": {
"target": "project"
},
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"System.Reflection": "4.1.0"
},
"imports": [
"dnxcore50",
"portable-net45+win8"
]
},
"net451": {
"dependencies": {
"xunit.runner.visualstudio": "2.1.0"
}
}
}
}