flawopen.com/XSS in Go/text/template vs html/template

Why does Go have both text/template and html/template?

Reference page — draft, pending review
Short answer

text/template generates plain text with no awareness of HTML — useful for config files, emails, code generation. html/template has the identical API but adds context-aware auto-escaping specifically for safely generating HTML. They're separate packages because plain-text generation shouldn't pay the cost (or unexpected behavior) of HTML escaping.

The trap this design creates

Because the two packages share an almost identical API, swapping the import line is the entire difference between safe and unsafe HTML generation — and the compiler won't catch a wrong choice, since both compile and run fine. A copy-pasted example, or a template originally written for non-HTML output later repurposed for a web response, can carry the wrong import without anyone noticing until it's exploited.

The rule

FAQ

Does html/template escape more than just angle brackets?

Yes — it tracks where in the template a value lands (HTML body, an attribute, a URL, inline JS or CSS) and applies the correct escaping for that specific context automatically, which is more sophisticated than most languages' default HTML escaping.

References