bluemonday

A fast, allowlist-based HTML sanitizer for Go that strips XSS vectors from untrusted content while preserving safe markup.

Library
Go
vv1.0.27
3,724 stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
45 /100 Fair
Development Activity 0
Maintenance 20
Community 60
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
76 /100 Good
Architecture 78
Code Quality 80
Innovation 65
Learning Curve 80

bluemonday is a Go library for sanitizing untrusted HTML fragments before they reach a browser. Instead of trying to blocklist dangerous tags and attributes, it works the opposite way: you build (or reuse) a policy describing exactly which HTML elements, attributes, and inline CSS properties are permitted, and everything else is stripped. This allowlist-first design, modeled on the OWASP Java HTML Sanitizer and HTML Purifier, closes off the constant cat-and-mouse game of trying to enumerate every possible XSS payload.

It ships two ready-made policies — StrictPolicy(), which strips all markup down to plain text, and UGCPolicy(), a broad but safe allowlist tuned for user-generated content such as blog comments or Markdown-rendered posts — plus a fluent builder API (AllowElements, AllowAttrs, AllowStyles, AllowURLSchemes) for constructing custom policies. Built policies are safe to reuse across goroutines, and the library includes dedicated handling for tricky cases like relative URLs, data URIs, and automatically adding rel="nofollow noopener noreferrer" to untrusted links.

What You Get

  • Two production-ready default policies: StrictPolicy() for plain-text-only output and UGCPolicy() for rich but safe user-generated content
  • A fluent policy-builder API to allow specific elements, attributes, and regex-matched attribute values on a per-element or global basis
  • Inline CSS style validation via a dedicated css subpackage, including value-matching handlers and enum-based allowed values
  • URL safety controls: parseable-URL enforcement, relative URL allow/deny, scheme allowlisting, and data-URI image validation
  • Automatic link hardening — rel="nofollow", rel="noreferrer", and target="_blank" + rel="noopener" handling for fully-qualified links
  • Three input/output shapes — Sanitize(string), SanitizeBytes([]byte), and SanitizeReader(io.Reader) — for different performance needs

Common Use Cases

  • Sanitizing Markdown-rendered HTML (e.g. from Blackfriday or Pandoc) before storing or serving it
  • Cleaning WYSIWYG editor output submitted by end users on comments, forums, or CMS content
  • Stripping HTML entirely from fields that should be plain text, such as titles, using StrictPolicy()
  • Building a custom allowlist for a specific rich-content feature (e.g. only allowing basic formatting tags and safe links)
  • Protecting federated/ActivityPub or CMS platforms (used in production by projects like Gitea/Forgejo) from stored XSS in remote content

Under The Hood

Architecture The library separates policy definition from the sanitization engine. policy.go defines the Policy struct as a set of allowlist maps — per-element attribute rules (elsAndAttrs), regex-matched element rules (elsMatchingAndAttrs), global attributes, per-element and global CSS style rules, and allowed URL schemes — built up through a fluent Allow* API and marked initialized so a zero-value Policy{} can’t be used unsafely. sanitize.go implements the actual sanitizer as a streaming, forward-only walk over the golang.org/x/net/html tokenizer, checking every token’s element and attributes against the policy’s maps rather than attempting to parse and repair malformed HTML. A separate css subpackage (css/handlers.go) owns inline-style validation using the douceur CSS parser, keeping style-property logic decoupled from the element/attribute logic. policies.go layers StrictPolicy() and UGCPolicy() on top of the same builder API used by consumers, so the shipped defaults are just examples of the public surface. Because every consumer path (custom policies and the two canned ones) funnels through the same elsAndAttrs/elsAndStyles maps and the same tokenizer walk in sanitize.go, that pair of files is the seam the whole library pivots on.

Tech Stack A minimal-dependency Go module (go.mod targets Go 1.19) with exactly two direct dependencies: golang.org/x/net for the html package’s tokenizer, and aymerick/douceur for CSS parsing (which pulls in gorilla/css transitively). There is no web framework, ORM, or database involved — this is a pure processing library invoked via go get and called directly from application code. CI (GitHub Actions) runs against both the pinned Go 1.19.x and the latest Go release across Ubuntu, macOS, and Windows, running go vet, staticcheck, and go test -race on every push and pull request.

Code Quality Test coverage is extensive and specific: sanitize_test.go alone contains around 48 test functions covering individual XSS vectors, malformed markup, and edge cases in URL/CSS handling, backed by further tests in policy_test.go, policies_test.go, and helpers_test.go, plus runnable example_test.go files that double as documentation. CI enforces go vet, staticcheck, and the race detector on every change across multiple OSes and Go versions, giving strong confidence against regressions and data races in concurrent policy use. Errors are handled by explicit return values rather than panics — Sanitize() documents that malformed input degrades to an empty string rather than surfacing an error, a deliberate simplicity trade-off for a security-focused API. Naming and structure follow idiomatic Go conventions throughout, with doc comments on every exported type and method.

What Makes It Unique Most hand-rolled HTML sanitizers try to blocklist dangerous tags and attributes, which is fragile against novel XSS vectors. bluemonday instead defaults to fail-closed: nothing is permitted unless the policy explicitly allows it, an approach it inherited from the OWASP Java HTML Sanitizer and HTML Purifier projects. Beyond the core allowlist mechanism, it goes deep on link and URL safety specifically — parseable-URL enforcement, relative-URL control, data-URI image validation with mimetype checks, and automatic rel="noopener" injection for target="_blank" links — details that simpler sanitizers commonly miss. This depth, combined with its concurrency-safe policy objects, has made it the de facto standard HTML sanitizer in the Go ecosystem, used in production by projects such as Gitea and Forgejo.

Used by 13 apps in this directory

Vue
43%
MIT

Alexandrie

Collaboration · Knowledge Management · Note Taking

2,797

The open-source, offline-first Notion, Obsidian & Confluence alternative with multi-tenant teams, OIDC/SSO, and one-command Docker deployment.

View details
85
Repo Health
73
Technical
74
Dependency
Built with
Vue 43%
TypeScript 41%
Go 13%
Updated 2 weeks ago
Go
61%
Apache 2.0

Apache Answer

Community

15,688

Open-source Q&A platform for communities, help centers, and knowledge bases with AI assistant and plugin extensibility

View details
89
Repo Health
78
Technical
68
Dependency
Built with
Go 61%
TypeScript 36%
Updated yesterday
Go
75%
AGPL 3.0

Coder

Code Editors · Developer Tools · Devops

16,920

Self-hosted cloud development environments and AI coding agents — defined in Terraform, connected via WireGuard, automatically shut down when idle.

View details
91
Repo Health
90
Technical
65
Dependency
Built with
Go 75%
TypeScript 23%
Updated today
Go
66%
AGPL 3.0

Fider

Customer Support · Product Management

4,571

Open-source feedback portal where customers submit, vote on, and track feature requests so product teams build what actually matters.

View details
89
Repo Health
85
Technical
71
Dependency
Built with
Go 66%
TypeScript 28%
Updated yesterday
Go
83%
MIT

Gitea

Developer Tools · Devops · Project Management

58,399

Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.

View details
93
Repo Health
79
Technical
64
Dependency
Built with
Go 83%
Updated yesterday
Go
68%
MIT

Gogs

Developer Tools

47,862

The painless self-hosted Git service that runs on anything from a Raspberry Pi to a $5 cloud droplet, delivering GitHub-like workflows as a single Go binary.

View details
84
Repo Health
79
Technical
71
Dependency
Built with
Go 68%
Go Template 16%
Updated 4 weeks ago
TypeScript
52%
Other

Mattermost

Collaboration · Devops · Team Chat

39,306

Open core, self-hosted team collaboration with chat, AI agents, voice calling, and deep DevOps integrations — all under your control.

View details
96
Repo Health
87
Technical
65
Dependency
Built with
TypeScript 52%
Go 40%
Updated yesterday
Go
82%
GPL 3.0

Navidrome

File Storage · Music Audio

24,068

Run your own personal Spotify — stream your entire music collection from any device, anywhere, forever.

View details
91
Repo Health
81
Technical
69
Dependency
Built with
Go 82%
JavaScript 15%
Updated yesterday
Go
74%
Other

Notifuse

Marketing

2,240

Open-source, self-hosted alternative to Mailchimp, Brevo, and Klaviyo — send newsletters and transactional emails without per-email pricing or vendor lock-in.

View details
81
Repo Health
80
Technical
65
Dependency
Built with
Go 74%
TypeScript 23%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers