Views

Escaping And Trusted HTML

Keep template output escaped unless a value is explicitly trusted.

By Guillermo Alvarez - Published Updated

Let templates escape data

Go templates escape ordinary strings by default:

c.Set("title", `<script>alert("x")</script>`)

Rendering the value is safe:

<h1>{{.title}}</h1>

The browser receives escaped text, not executable markup.

Trust only generated HTML

Use template.HTML only when application code generated or sanitized the markup:

body, err := markdown.Convert(post.Body)
if err != nil {
    return fmt.Errorf("render post markdown: %w", err)
}

c.Set("body", template.HTML(body))

The view can then render the trusted fragment:

<article>{{.body}}</article>

Do not wrap user-submitted strings in template.HTML.

Keep trust decisions near the adapter

Put conversions in the package that knows the source:

package markdown

func Convert(source string) (string, error) {
    // Convert Markdown to HTML and apply the adapter policy here.
}

Controllers should pass trusted HTML only after the adapter has done its work.