Skip to main content

    XSS prevention for Go net/http

    This is a cross-site scripting (XSS) prevention cheat sheet by Semgrep, Inc. It contains code patterns of potential XSS in an application. Instead of scrutinizing code for exploitable vulnerabilities, the recommendations in this cheat sheet pave a safe road for developers that mitigate the possibility of XSS in your code. By following these recommendations, you can be reasonably sure your code is free of XSS.

    Mitigation summary

    The Go template engine in html/template does automatic and contextual autoescaping, which mitigates many common XSS mistakes. Some aspects of the engine are confusingly named; therefore, proper use of the library should be enforced using code scanners. You may also consider using a stricter alternative, such as safehtml.

    Check your project using Semgrep

    The following command runs an optimized set of rules for your project:

    semgrep --config p/default

    1. Server code: Unescaped content

    1.A. Using the text/template package

    text/template does not perform any HTML escaping.

    Example:

    import "text/template"

    References

    Mitigation

    Ban text/template. Alternatively, use html/template, or a stricter alternative such as safehtml.

    Semgrep rule

    go.lang.security.audit.xss.import-text-template.import-text-template

    1.B. Escaped types: template.HTML

    template.HTML is a special type which instructs the template engine not to escape the content.

    Example:

    content := template.HTML("<div>" + user.name + "</div>")

    References

    Mitigation

    Ban template.HTML. Alternatively, if necessary, review each case carefully and exempt with # nosemgrep.

    Semgrep rule

    go.lang.security.audit.xss.template-html-does-not-escape.unsafe-template-type

    1.C. Escaped types: template.HTMLAttr

    template.HTMLAttr is a special type which instructs the template engine not to escape the content.

    Example:

    content := template.HTMLAttr("class=" + user.role)

    References

    Mitigation

    Ban template.HTMLAttr. Alternatively, prefer template.HTML, only if necessary.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    1.D. Escaped types: template.CSS

    template.CSS is a special type which instructs the template engine not to escape the content in CSS contexts.

    Example:

    content := template.CSS("body { color: black; }")

    References

    Mitigation

    Ban template.CSS. Alternatively, if necessary, review each case carefully and exempt with # nosemgrep.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    1.E. Escaped types: template.JS

    The template.JS is a special type which instructs the template engine not to escape the content in JavaScript contexts, such as between script tags.

    Example:

    content := template.JS("var name = " + user.name)

    References

    Mitigation

    Ban template.JS. Alternatively, place JavaScript code in files separate from HTML and serve them using the src attribute.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    1.F. Escaped types: template.JSStr

    The template.JSStr is a special type which instructs the template engine not to escape the content when in JavaScript contexts and in a string.

    Example:

    content := template.JSStr("Error by: " + user.name)

    References

    Mitigation

    Ban template.JSStr. Alternatively, place JavaScript code in files separate from HTML and serve them using the src attribute.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    1.G. Escaped types: template.Srcset

    template.Srcset is a special type which instructs the template engine not to escape the content.

    Example:

    content := template.Srcset("https://" + user.stylepageurl)

    References

    Mitigation

    Ban template.Srcset. Alternatively, prefer template.HTML, only if necessary.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    1.H. Escaped types: template.URL

    The template.URL is a special type which instructs the template engine not to escape the content.

    Example:

    content := template.URL("https://" + user.stylepageurl)

    References

    Mitigation

    Ban template.URL. Alternatively, if necessary, review each case carefully and exempt with # nosem.

    Semgrep rule

    go.template.security.insecure-types.go-insecure-templates

    2. Server code: Bypassing the template engine

    2.A. Writing directly to the response object: fmt.Fprintf()

    Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

    Example:

    fmt.Fprintf(w, "<div>" + user.name + "</div>")

    References

    Mitigation

    Ban using fmt.Printf with the HTTP response writer. Alternatively, use html/template to render data to users.

    Semgrep rule

    go.lang.security.audit.xss.no-fprintf-to-responsewriter.no-fprintf-to-responsewriter

    2.C. Writing directly to the response object: io.WriteString()

    Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

    Example:

    io.WriteString(w, "<div>" + user.name + "</div>")

    References

    Mitigation

    Ban using io.WriteString with the HTTP response writer. Alternatively, use html/template to render data to users.

    Semgrep rule

    go.lang.security.audit.xss.no-io-writestring-to-responsewriter.no-io-writestring-to-responsewriter

    2.C. Writing directly to the response object: w.Write() method

    Writing directly to the response object bypasses the template engine which means content will not be autoescaped. This could introduce a XSS vulnerability.

    Example:

    writer.Write([]byte("<div>" + user.name + "</div>"))

    References

    Mitigation

    Ban using the Write method of the HTTP response writer. Alternatively, use html/template to render data to users.

    Semgrep rule

    go.lang.security.audit.xss.no-direct-write-to-responsewriter.no-direct-write-to-responsewriter

    Not finding what you need in this doc? Ask questions in our Community Slack group, or see Support for other ways to get help.