OWASP.AntiSamy 1.0.2

Advisory: https://github.com/advisories/GHSA-8x6f-956f-q43w Severity: moderate
There is a newer version of this package available.
See the version list below for details.
dotnet add package OWASP.AntiSamy --version 1.0.2                
NuGet\Install-Package OWASP.AntiSamy -Version 1.0.2                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OWASP.AntiSamy" Version="1.0.2" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add OWASP.AntiSamy --version 1.0.2                
#r "nuget: OWASP.AntiSamy, 1.0.2"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install OWASP.AntiSamy as a Cake Addin
#addin nuget:?package=OWASP.AntiSamy&version=1.0.2

// Install OWASP.AntiSamy as a Cake Tool
#tool nuget:?package=OWASP.AntiSamy&version=1.0.2                


Codacy Badge Actions Status CodeQL

A library for performing fast, configurable cleansing of HTML coming from untrusted sources. Refactored from an old project in .NET Framework 2.0.

Another way of saying that could be: It's an API that helps you make sure that clients don't supply malicious cargo code in the HTML they supply for their profile, comments, etc., that get persisted on the server. The term "malicious code" in regard to web applications usually mean "JavaScript." Mostly, Cascading Stylesheets are only considered malicious when they invoke JavaScript. However, there are many situations where "normal" HTML and CSS can be used in a malicious manner.

This project will be trying to be in sync with the original Java version, its repository can be found here.

How to use

1. Import the dependency

Ways to import the project:

  1. Import the NuGet package.
  2. Build and reference the OWASP.AntiSamy DLL in your project.

2. Choosing a base policy file

Chances are that your site's use case for AntiSamy is at least roughly comparable to one of the predefined policy files. They each represent a "typical" scenario for allowing users to provide HTML (and possibly CSS) formatting information. In the repository you will find different policy files:

  1. antisamy-slashdot.xml
  2. antisamy-ebay.xml
  3. antisamy-myspace.xml
  4. antisamy-anythinggoes.xml

For more information about each policy, see the README file in the repository.

3. Tailoring the policy file

You may want to deploy OWASP AntiSamy .NET in a default configuration, but it's equally likely that a site may want to have strict, business-driven rules for what users can allow. The discussion that decides the tailoring should also consider attack surface - which grows in relative proportion to the policy file.

When installing from the NuGet package, policy examples are included in your project but not copied to the output folder by default. If you decide to use one you can, for example in Visual Studio, select the chosen XML policy file and specify in its properties to be copied if newer or always. The example files are removed along with the package in case it's deleted.

You may also want to enable/modify some "directives", which are basically advanced user options. Supported directives are the following:

  • maxInputSize (int): Maximum input size for the HTML to read.
  • nofollowAnchors (bool): Determines if adds the attribute rel="nofollow" on <a> tags.
  • validateParamAsEmbed (bool): Determines if validates the <param> tag as <embed> tag.
  • preserveSpace (bool): Determines if HTML output gets trimmed.
  • preserveComments (bool): Determines if comments are removed from the HTML.
  • entityEncodeIntlChars (bool): Determines if HTML output gets encoded regarding special characters, like accents.
  • useXHTML (bool): Determines if parser uses XHTML, explicitly used for CDATA handling when scanning CSS.
  • onUnknownTag (string): Determines the action for a detected unknown tag. Today, the only value taken into account is "encode". Default action is "remove".

More directives are supported on the Java-based project. For more detailed information on directive declaration and general policy format, inspect the example policies. Note: Every input policy will be validated by AntiSamy against the only defined schema.

4. Calling the OWASP AntiSamy .NET API

Using OWASP AntiSamy .NET is easy. Here is an example of invoking AntiSamy with a policy file:

using OWASP.AntiSamy.Html;

Policy policy = Policy.GetInstance(POLICY_FILE_LOCATION);

var antiSamy = new AntiSamy();
CleanResults results = antiSamy.Scan(dirtyInput, policy);

MyUser.StoreHtmlProfile(results.GetCleanHTML()); // Some custom function

There are a few ways to create a Policy object. The GetInstance() method can take any of the following:

  • A string filename.
  • A FileInfo object.
  • A Stream object.
  • Policy files can also be referenced by filename by passing a second argument to the AntiSamy.Scan() method as the following examples show:
var antiSamy = new AntiSamy();
CleanResults results = antiSamy.Scan(dirtyInput, policyFilePath);

5. Analyzing CleanResults

The CleanResults object provides a lot of useful stuff.

  • GetCleanHTML() - the clean, safe HTML output.
  • GetErrorMessages() - a list of String error messages. -- if this returns empty that does not mean there were no attacks!
  • GetNumberOfErrors() - the error message count in case the list itself is not needed. -- if this returns 0 that does not mean there were no attacks!
  • GetScanTime() - returns the scan time in seconds.
  • GetStartOfScan() and GetEndOfScan() - return the each DateTime object in case it is needed.

Important note: There has been much confusion about the GetErrorMessages() method. The GetErrorMessages() method does not subtly answer the question "is this safe input?" in the affirmative if it returns an empty list. You must always use the sanitized input and there is no way to be sure the input passed in had no attacks.

The serialization and deserialization process that is critical to the effectiveness of the sanitizer is purposefully lossy and will filter out attacks via several attack vectors. Unfortunately, one of the tradeoffs of this strategy is that we don't always know in retrospect that an attack was seen. Thus, the GetErrorMessages() API is there to help users understand their well-intentioned input meet the requirements of the system, not help a developer detect if an attack was present.

Contributing to OWASP AntiSamy .NET

Found an issue?

If you have found a bug, then create an issue in the OWASP AntiSamy .NET repository: https://github.com/spassarop/antisamy-dotnet/issues.

Found a vulnerability?

If you have found a vulnerability in OWASP AntiSamy .NET, first search the issues list (see above) to see if it has already been reported. If it has not, then please contact Sebastián Passaro (sebastian.passaro at owasp.org) directly. Please do not report vulnerabilities via GitHub issues as we wish to keep our users secure while a patch is implemented and deployed. If you wish to be acknowledged for finding the vulnerability, then please follow this process.

More detail is available in the file: SECURITY.md.

How to build

You can build and test from source pretty easily:

git clone https://github.com/spassarop/antisamy-dotnet.git
cd antisamy-dotnet
dotnet build OWASP.AntiSamy.sln

To build without tests:

dotnet build OWASP.AntiSamy/OWASP.AntiSamy.csproj

Also, you always can just build the project/solution from Visual Studio.

How to test

To run the tests:

dotnet test OWASP.AntiSamy.sln
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net46 is compatible.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.1 20,705 12/22/2023
1.2.0 7,260 12/21/2023
1.1.1 80,962 6/1/2022
1.1.0 5,868 2/2/2022
1.0.3 33,178 9/19/2021
1.0.2 44,464 1/13/2021