Cross-site scripting via HTML template escaping bypass — CodeQL query help documentation
CodeQL docs
Cross-site scripting via HTML template escaping bypass
ID: go/html-template-escaping-bypass-xss
Kind: path-problem
Security severity: 7.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-079
- external/cwe/cwe-116
Query suites:
- go-code-scanning.qls
- go-security-extended.qls
- go-security-and-quality.qls
Click to see the query in the CodeQL repository
In Go, the html/template package has a few special types (HTML, HTMLAttr, JS, JSStr, CSS, Srcset, and URL) that allow values to be rendered as-is in the template, avoiding the escaping that all the other strings go through.
Using them on user-provided values allows for a cross-site scripting vulnerability.
Recommendation
Make sure to never use those types on untrusted content.
Example
In the first example you can see the special types and how they are used in a template:
package main
import (
"html/template"
"net/http"
)
func bad(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.Form.Get("username")
tmpl, _ := template.New("test").Parse(`<b>Hi {{.}}</b>`)
tmpl.Execute(w, template.HTML(username))
}
To avoid XSS, all user input should be a normal string type.
package main
import (
"html/template"
"net/http"
)
func good(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.Form.Get("username")
tmpl, _ := template.New("test").Parse(`<b>Hi {{.}}</b>`)
tmpl.Execute(w, username)
}