bluemonday HTML Sanitizer

repository·main·Indexed 25 days ago

https://github.com/microcosm-cc/bluemonday

A fast, highly configurable HTML sanitizer implemented in Go designed to protect against XSS attacks. It sanitizes untrusted user-generated content against an allowlist of approved HTML elements and attributes. It provides pre-configured policies like UGCPolicy() and StrictPolicy(), as well as tools for building custom policies, configuring inline CSS sanitization, and managing safe URL schemes. The package also includes CLI utilities for sanitizing HTML emails and general user-generated content.

Tokens
4K
Snippets
7
Records
32
Agent score
85%

What's inside bluemonday

  1. Sanitize HTML using default policies

    main

    bluemonday provides pre-configured policies for common use cases. You can use bluemonday.UGCPolicy() for user-generated content (allowing safe formatting like links and images) or bluemonday.StrictPolicy() to strip all HTML elements and attributes entirely.

    Important: Policy creation/editing is not thread-safe. Create your policy once and reuse it. However, once created, the policy instance is safe to use for sanitization across multiple goroutines.

    package main
    
    import (
    	"fmt"
    
    	"github.com/microcosm-cc/bluemonday"
    )
    
    func main() {
    	// Create the policy once
    	p := bluemonday.UGCPolicy()
    
    	// Use the policy to sanitize input (safe for multiple goroutines)
    	html := p.Sanitize(
    		`<a onblur="alert(secret)" href="http://www.google.com">Google</a>`,
    	)
    
    	// Output: <a href="http://www.google.com" rel="nofollow">Google</a>
    	fmt.Println(html)
    }
  2. Configure inline CSS sanitization

    main

    Instead of using a single complex regex for the style attribute, use bluemonday's specialized style policy methods. First, allow the style attribute on specific elements, then use AllowStyles to define permitted properties and their allowed values.

    Available methods for style validation:

    • .Matching(regex): Validates the property value against a regular expression.
    • .MatchingEnum(values...): Restricts the property to a specific set of allowed values.
    • .MatchingHandler(func(string) bool): Uses a custom function to validate the property value (the input string is lowercased and unicode-normalized).
  3. Use policy building helpers

    main

    Use these convenience methods to quickly permit common HTML structures:

    • AllowStandardAttributes(): Permits dir, id, lang, and title globally.
    • AllowImages(): Permits the img element and its standard attributes.
    • AllowLists(): Permits ordered, unordered, and definition lists.
    • AllowTables(): Permits HTML tables and all applicable elements/non-styling attributes.
    p.AllowStandardAttributes()
    p.AllowImages()
    p.AllowLists()
    p.AllowTables()
  4. Create and build a custom HTML sanitization policy

    main

    To create a new policy, use bluemonday.NewPolicy(). You can build a policy by specifying allowed elements and attributes. It is highly recommended to use regular expressions with .Matching() for attributes to prevent XSS. You can also extend existing policies like bluemonday.UGCPolicy().

    To sanitize HTML, call .Sanitize(htmlIn) on your policy instance.

    p := bluemonday.NewPolicy()
    p.AllowElements("b", "strong")
    p.AllowAttrs("title").Matching(regexp.MustCompile(`[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&]*`)).Globally()
    
    htmlOut := p.Sanitize(htmlIn)
  5. Configure safe URL and link behavior

    main

    Links are a major attack vector. Use the following options to secure them:

    • RequireParseableURLs(true): Ensures URLs are parseable by Go's net/url package.
    • AllowRelativeURLs(true): Permits local and scheme-relative URLs (e.g., href="localpage.html"). Requires RequireParseableURLs to be enabled first.
    • AllowURLSchemes(schemes...): Specifies permitted protocols (e.g., http, https, mailto).
    • RequireNoFollowOnLinks(true): Forces rel="nofollow" on valid links.
    • RequireNoReferrerOnLinks(true): Forces rel="noreferrer" on valid links.
    • AddTargetBlankToFullyQualifiedLinks(true): Adds target="_blank" to links with a host name.
    • AllowDataURIImages(): Enables GIF, JPEG, PNG, and WEBP images via data URIs (use with caution).
    • AllowStandardURLs(): A convenience method that applies several URL safety rules.
    p.RequireParseableURLs(true)
    p.AllowRelativeURLs(true)
    p.AllowURLSchemes("mailto", "http", "https")
    p.RequireNoFollowOnLinks(true)
    p.AddTargetBlankToFullyQualifiedLinks(true)
    
    // Note: You must still allow the elements/attributes for these rules to apply
    p.AllowAttrs("href").OnElements("a", "area")
  6. Initialize a new Policy

    main
    Use bluemonday.NewPolicy() to create a blank policy. This is the recommended way to start building a policy because it initializes the internal maps required for configuration. A blank policy starts with nothing allowed or permitted.
  7. Sanitize HTML emails via CLI

    main

    The sanitise_html_email utility is a CLI tool designed to sanitize HTML content specifically formatted for emails. It uses a customized bluemonday.UGCPolicy() as a base, extending it to preserve structural elements (like <html>, <head>, and <body>) and styling (like <style> tags and style attributes) that are often necessary for email rendering but typically stripped by stricter policies.

    Key features of this specific policy:

    • Preserves core structure: html, head, body, title.
    • Preserves styling: Allows style attributes globally and <style> tags with type="text/css".
    • Supports legacy HTML: Allows elements like font, main, nav, header, footer, kbd, and legend.
    • Handles email-specific attributes: Allows bgcolor and color (matching hex or web-safe color names) on basefont, font, and hr; allows border, cellpadding, and cellspacing on img and table.
    • Security/UX enhancements: Automatically adds rel="nofollow" to links and target="_blank" to fully qualified links.
    • Image support: Allows images embedded via data-URIs.

    Usage: This utility reads dirty HTML from stdin and writes the sanitized HTML to stdout. It is designed to be used in Unix pipelines.

  8. Build a custom HTML sanitization policy

    main

    You can define a custom allowlist of elements and attributes using bluemonday.NewPolicy(). This allows you to control exactly which tags and attributes are permitted and even enforce URL schemes.

    package main
    
    import (
    	"fmt"
    
    	"github.com/microcosm-cc/bluemonday"
    )
    
    func main() {
    	p := bluemonday.NewPolicy()
    
    	// Require URLs to be parseable by net/url.Parse and either: mailto:, http:// or https://
    	p.AllowStandardURLs()
    
    	// Only allow <p> and <a href=""> tags
    	p.AllowAttrs("href").OnElements("a")
    	p.AllowElements("p")
    
    	html := p.Sanitize(
    		`<a onblur="alert(secret)" href="http://www.google.com">Google</a>`,
    	)
    
    	// Output: <a href="http://www.google.com">Google</a>
    	fmt.Println(html)
    }
  9. Sanitize different data types with Policy.Sanitize

    main

    The policy object provides three methods for sanitization depending on your input type:

    • p.Sanitize(string) string: For standard string inputs.
    • p.SanitizeBytes([]byte) []byte: For byte slice inputs.
    • p.SanitizeReader(io.Reader) bytes.Buffer: For streaming inputs via an io.Reader. This is the most performant option for large inputs as it avoids unnecessary casting.
  10. Reference: Default bluemonday policies

    main

    bluemonday ships with two primary default policies:

    1. bluemonday.StrictPolicy(): Strips all HTML elements and attributes. Use this when no HTML is expected (e.g., blog post titles).
    2. bluemonday.UGCPolicy(): Allows a broad selection of safe HTML elements and attributes for user-generated content (e.g., blog post bodies). It does not allow iframes, object, embed, styles, or script tags.