Documentation
¶
Overview ¶
Package sanitizehtml sanitizes untrusted HTML by removing disallowed tags and attributes, mirroring a practical subset of the npm "sanitize-html" library. It is intended for the common case of accepting rich text from a user (comments, profile bios, CMS fields) and rendering it back into a page without opening the door to cross-site scripting or layout-breaking markup.
Sanitization is driven by an allowlist rather than a blocklist, which is the safe default: only tags that appear in Options.AllowedTags survive, and on those surviving tags only the attributes named in Options.AllowedAttributes are kept. Everything else is discarded. Because the policy enumerates what is permitted instead of what is forbidden, a novel or misspelled tag is stripped automatically rather than slipping through. DefaultOptions returns a policy equivalent to the sanitize-html defaults, allowing common formatting tags plus href/name/target on <a> and the usual source attributes on <img>.
The implementation tokenizes the input with the standard library only; no third-party HTML parser is used. The tokenizer scans the string once and emits a flat stream of text, start-tag, and end-tag tokens. HTML comments (<!-- ... -->) and declarations such as <!DOCTYPE html> are dropped during scanning, and a stray '<' that does not begin a valid tag is treated as literal text. Start tags are parsed into a tag name plus a list of attribute name/value pairs, with entity references in attribute values unescaped so that they can be re-escaped consistently on output.
Disallowed tags are stripped in a way that preserves the reader's content: the tag's angle-bracket markup is removed but the text between the opening and closing tags is emitted verbatim, so "<foo>hello</foo>" becomes "hello". The two exceptions are <script> and <style>, whose entire raw contents are consumed and discarded rather than surfaced as text, preventing script source or CSS from leaking into the output. On surviving start tags each attribute is checked against AllowedAttributes (honoring the "*" key that applies to every tag), disallowed attributes are dropped, and the retained attribute values are re-escaped with html.EscapeString before serialization.
Parity with the Node library is deliberately partial. This port covers the tag and attribute allowlist model, text-preserving tag removal, and the script/style content stripping that most callers rely on. It does not implement the richer sanitize-html features such as per-attribute value filtering, URL scheme validation, CSS style parsing, allowed classes, transformTags, or exclusiveFilter callbacks. Tag and attribute names are compared case-insensitively (lower-cased), matching the way browsers treat HTML, and output tag names are normalized to lower case.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Sanitize ¶
Sanitize returns htmlStr with disallowed tags and attributes removed according to opts. Text content of disallowed tags is kept; the contents of <script> and <style> elements are removed entirely.
Example ¶
ExampleSanitize demonstrates cleaning an untrusted HTML fragment with the library defaults returned by DefaultOptions. The <p> and <b> tags are on the default allowlist, so they survive unchanged and keep their text. The <script> element is not on the allowlist, and because script contents are always discarded its "alert(1)" payload is removed entirely rather than being surfaced as text. The result is therefore safe to render back into a page, and the transformation is deterministic so an Output block can assert it.
package main
import (
"fmt"
"github.com/malcolmston/express/sanitizehtml"
)
func main() {
input := `<p>Hello <script>alert(1)</script><b>world</b></p>`
fmt.Println(sanitizehtml.Sanitize(input, sanitizehtml.DefaultOptions()))
}
Output: <p>Hello <b>world</b></p>
Example (Attributes) ¶
ExampleSanitize_attributes shows how the attribute allowlist filters individual attributes on an otherwise-allowed tag. The <a> tag is permitted by the defaults, and so is its href attribute, so both are kept. The onclick attribute is not in the permitted set for <a>, so it is dropped, which is the primary mechanism that blocks inline event-handler scripting. Retained attribute values are re-escaped on output, keeping the serialization consistent and safe.
package main
import (
"fmt"
"github.com/malcolmston/express/sanitizehtml"
)
func main() {
input := `<a href="/home" onclick="steal()">link</a>`
fmt.Println(sanitizehtml.Sanitize(input, sanitizehtml.DefaultOptions()))
}
Output: <a href="/home">link</a>
Example (CustomPolicy) ¶
ExampleSanitize_customPolicy demonstrates a restrictive custom policy that allows only the <em> tag and no attributes at all. The <em> tag is kept, but the <span> tag is not on the allowlist and is stripped while its inner text "keep" is preserved. This illustrates the text-preserving removal of disallowed tags: markup disappears but the reader's words remain. Building Options directly gives full control over the tag and attribute policy.
package main
import (
"fmt"
"github.com/malcolmston/express/sanitizehtml"
)
func main() {
opts := sanitizehtml.Options{AllowedTags: []string{"em"}}
input := `<span>keep</span> <em>this</em>`
fmt.Println(sanitizehtml.Sanitize(input, opts))
}
Output: keep <em>this</em>
Types ¶
type Options ¶
type Options struct {
// AllowedTags is the set of tag names permitted in the output. A single
// entry of "*" permits every tag. Tags not listed are stripped while their
// text content is preserved.
AllowedTags []string
// AllowedAttributes maps a tag name to the attribute names permitted on
// that tag. The special key "*" applies to all tags. Attributes not
// permitted are removed from otherwise-allowed tags.
AllowedAttributes map[string][]string
}
Options controls how Sanitize filters HTML.
func DefaultOptions ¶
func DefaultOptions() Options
DefaultOptions returns Options mirroring the sanitize-html defaults: a set of common formatting tags is allowed, href/name/target are permitted on <a>, and image source attributes are permitted on <img>.