Skip to main content

Server-side HTML sanitization

The LgHtmlSanitizer service (namespace Lagoon.Server.Services) sanitizes HTML content using an allowlist: it removes scripts, event handlers (onclick, onerror…), dangerous URLs (javascript:…), and forms before the content is displayed to other users. It relies on the HtmlSanitizer library.

Lagoon registers it as a singleton in all server applications and uses it for the terms of use. Inject it into your services or controllers to sanitize any other HTML content entered by a user, for example with an LgHtmlEditor.

Usage​

ArticleController.cs
public class ArticleController : LgControllerBase
{
private readonly LgHtmlSanitizer _htmlSanitizer;

public ArticleController(LgHtmlSanitizer htmlSanitizer)
{
_htmlSanitizer = htmlSanitizer;
}

[HttpPost]
public async Task<IActionResult> SaveAsync(ArticleDto article)
{
try
{
// Sanitize the HTML entered in the LgHtmlEditor before storing it
article.Content = _htmlSanitizer.Sanitize(article.Content);
// ...
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
}
MethodUsage
Sanitize(string html)HTML fragment, for example the content produced by an LgHtmlEditor.
SanitizeDocument(string html)Full HTML document (html, head, body), for example a file exported from a word processor.

Both methods return null or an empty string as-is and can be called concurrently.

Applied rules​

Lagoon starts from HtmlSanitizer's default allowlist (formatting tags, lists, tables, links, images, style attribute limited to a list of CSS properties), then:

  • removes forms (form, input, button, select, textarea…) and their attributes (action, method…): a form could collect data and send it to an external URL;
  • allows the class attribute and the mailto: URL scheme in addition to http: and https:;
  • preserves embedded data:image/... images in the src attribute of img tags (images pasted into the editor);
  • for SanitizeDocument only, preserves style elements (whose content is itself sanitized) and @page, @media, and @font-face rules, so that a document exported from a word processor keeps its layout. Other head elements (meta, title, link, script…) are removed.

iframe elements (videos inserted with the editor, for example) are removed.

Configuration​

Options are read from the Lagoon:HtmlSanitizer section of appsettings.json:

{
"Lagoon": {
"HtmlSanitizer": {
"AllowDataImages": true
}
}
}
OptionDescription
AllowDataImagesPreserves embedded data:image/... images in img tags. Defaults to true.

To modify the allowlist, extend the options in OnConfigureServices. The ConfigureSanitizer callback receives the underlying HtmlSanitizer object, after Lagoon's rules have been applied, and a boolean that is true for a full document:

Main.cs
protected override void OnConfigureServices(IServiceCollection services)
{
services.Configure<LgHtmlSanitizerOptions>(options =>
{
options.ConfigureSanitizer = (sanitizer, document) =>
{
// Keep the videos inserted with the HTML editor
sanitizer.AllowedTags.Add("iframe");
};
});
}
warning

Each tag, attribute, CSS property, or URL scheme added widens the attack surface. Only allow iframe if your CSP policy restricts frame sources (the frame-src directive, see Content Security Policy).