Skip to content

Commit 1aa1153

Browse files
committed
Go: Add html/template as XSS queries sanitizer
1 parent fc66aac commit 1aa1153

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

go/ql/lib/semmle/go/security/Xss.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,20 @@ module SharedXss {
127127
)
128128
}
129129
}
130+
131+
/**
132+
* A `Template` from `html/template` will HTML-escape data automatically
133+
* and therefore acts as a sanitizer for XSS vulnerabilities.
134+
*/
135+
class HtmlTemplateSanitizer extends Sanitizer, DataFlow::Node {
136+
HtmlTemplateSanitizer() {
137+
exists(Method m, DataFlow::CallNode call | m = call.getCall().getTarget() |
138+
m.hasQualifiedName("html/template", "Template", "ExecuteTemplate") and
139+
call.getArgument(2) = this
140+
or
141+
m.hasQualifiedName("html/template", "Template", "Execute") and
142+
call.getArgument(1) = this
143+
)
144+
}
145+
}
130146
}

go/ql/test/query-tests/Security/CWE-079/ReflectedXssGood.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ package main
33
import (
44
"fmt"
55
"html"
6+
"html/template"
67
"net/http"
78
)
89

910
func serve1() {
11+
var template template.Template
12+
1013
http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
1114
r.ParseForm()
1215
username := r.Form.Get("username")
1316
if !isValidUsername(username) {
1417
// GOOD: a request parameter is escaped before being put into the response
1518
fmt.Fprintf(w, "%q is an unknown user", html.EscapeString(username))
19+
// GOOD: using html/template escapes values for us
20+
template.Execute(w, username)
21+
template.ExecuteTemplate(w, "test", username)
1622
} else {
1723
// TODO: do something exciting
1824
}

go/ql/test/query-tests/Security/CWE-079/StoredXssGood.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package main
22

33
import (
44
"html"
5+
"html/template"
56
"io"
67
"io/ioutil"
78
"net/http"
89
)
910

1011
func ListFiles1(w http.ResponseWriter, r *http.Request) {
12+
var template template.Template
1113
files, _ := ioutil.ReadDir(".")
1214

1315
for _, file := range files {
1416
io.WriteString(w, html.EscapeString(file.Name())+"\n")
17+
template.Execute(w, file.Name())
1518
}
1619
}

0 commit comments

Comments
 (0)