Go html/template: Why Auto-Escaping Is Your Friend
When you write {{.Title}} in a Go html/template, Go does not print the string — it prints a context-aware, escaped version. That automatic escaping is one of the best security features in the language, and it is exactly where hand-rolled template concatenation goes wrong.
What auto-escaping does for you
Go's template engine knows the context of every value:
- Inside
{{.Title}}in body text, it HTML-escapes (&,<,>, quotes). - Inside
href="{{.URL}}", it escapes URL-hostile characters. - Inside
onclick="...", it escapes for a JavaScript context.
The result: if user content contains <script>alert(1)</script>, it renders as harmless text instead of executing. You do not need a sanitizer for template output — the escaping is structural.
The mistake it prevents
The classic bug is building HTML by string concatenation:
html := "<div>" + userInput + "</div>"
One <script> in userInput and you have an XSS hole. With html/template, that same value is escaped automatically. This is why "just concatenate strings" is not a template.
Where it gets in the way — and what to do
- You want raw HTML. Use
template.HTMLdeliberately, and only for trusted content. The site's markdown renderer sanitizes with a whitelist first, then hands the result to the template as trusted HTML. - You want to inject a known-safe snippet. Same answer — wrap it explicitly. The moment you reach for
template.HTML, you are telling Go "I take responsibility for this being safe."
The rule I follow
Default to auto-escaping. Escape by construction, sanitize at the boundary, and never concatenate HTML strings. Go's template engine gives you the safe default for free — the only skill is not disabling it casually.
Comments (0)
No comments yet.