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
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);
}
}
}
| Method | Usage |
|---|---|
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
classattribute and themailto:URL scheme in addition tohttp:andhttps:; - preserves embedded
data:image/...images in thesrcattribute ofimgtags (images pasted into the editor); - for
SanitizeDocumentonly, preservesstyleelements (whose content is itself sanitized) and@page,@media, and@font-facerules, so that a document exported from a word processor keeps its layout. Otherheadelements (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
}
}
}
| Option | Description |
|---|---|
AllowDataImages | Preserves 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:
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");
};
});
}
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).