diff --git a/ql/src/semmle/go/Concepts.qll b/ql/src/semmle/go/Concepts.qll index e17b5f3889a..81cd1b1ff72 100644 --- a/ql/src/semmle/go/Concepts.qll +++ b/ql/src/semmle/go/Concepts.qll @@ -366,8 +366,8 @@ module HTTP { * extend `HTTP::ResponseWriter` instead. */ abstract class Range extends Variable { - /** Gets a data-flow node that represents this response writer. */ - DataFlow::Node getANode() { result = this.getARead().getASuccessor*() } + /** Gets a data-flow node that is a use of this response writer. */ + abstract DataFlow::Node getANode(); } } @@ -391,7 +391,7 @@ module HTTP { /** Gets a redirect that is sent in this HTTP response. */ Redirect getARedirect() { result.getResponseWriter() = this } - /** Gets a data-flow node that represents this response writer. */ + /** Gets a data-flow node that is a use of this response writer. */ DataFlow::Node getANode() { result = self.getANode() } } diff --git a/ql/src/semmle/go/frameworks/HTTP.qll b/ql/src/semmle/go/frameworks/HTTP.qll index 44e0cd23533..a159d75db7b 100644 --- a/ql/src/semmle/go/frameworks/HTTP.qll +++ b/ql/src/semmle/go/frameworks/HTTP.qll @@ -54,13 +54,21 @@ private module StdlibHttp { } } + /** The declaration of a variable which either is or has a field that implements the http.ResponseWriter type */ private class StdlibResponseWriter extends HTTP::ResponseWriter::Range { - StdlibResponseWriter() { this.getType().implements("net/http", "ResponseWriter") } + SsaWithFields v; + + StdlibResponseWriter() { + this = v.getBaseVariable().getSourceVariable() and + exists(Type t | t.implements("net/http", "ResponseWriter") | v.getType() = t) + } + + override DataFlow::Node getANode() { result = v.similar().getAUse().getASuccessor*() } /** Gets a header object that corresponds to this HTTP response. */ DataFlow::MethodCallNode getAHeaderObject() { - result.getTarget().hasQualifiedName("net/http", _, "Header") and - this.getARead() = result.getReceiver() + result.getTarget().getName() = "Header" and + this.getANode() = result.getReceiver() } } diff --git a/ql/src/semmle/go/frameworks/Macaron.qll b/ql/src/semmle/go/frameworks/Macaron.qll index 134e7a390bb..a38b2b20da0 100644 --- a/ql/src/semmle/go/frameworks/Macaron.qll +++ b/ql/src/semmle/go/frameworks/Macaron.qll @@ -6,11 +6,16 @@ import go private module Macaron { private class Context extends HTTP::ResponseWriter::Range { + SsaWithFields v; + Context() { + this = v.getBaseVariable().getSourceVariable() and exists(Method m | m.hasQualifiedName("gopkg.in/macaron.v1", "Context", "Redirect") | - m = this.getType().getMethod("Redirect") + v.getType().getMethod("Redirect") = m ) } + + override DataFlow::Node getANode() { result = v.similar().getAUse().getASuccessor*() } } private class RedirectCall extends HTTP::Redirect::Range, DataFlow::MethodCallNode { @@ -20,6 +25,6 @@ private module Macaron { override DataFlow::Node getUrl() { result = this.getArgument(0) } - override HTTP::ResponseWriter getResponseWriter() { result.getARead() = this.getReceiver() } + override HTTP::ResponseWriter getResponseWriter() { result.getANode() = this.getReceiver() } } } diff --git a/ql/src/semmle/go/security/ReflectedXssCustomizations.qll b/ql/src/semmle/go/security/ReflectedXssCustomizations.qll index 65c660f2112..b6b3757c060 100644 --- a/ql/src/semmle/go/security/ReflectedXssCustomizations.qll +++ b/ql/src/semmle/go/security/ReflectedXssCustomizations.qll @@ -59,7 +59,7 @@ module ReflectedXss { not htmlTypeSpecified(body) and ( exists(HTTP::HeaderWrite hw | hw = body.getResponseWriter().getAHeaderWrite() | - hw.definesHeader("content-type", _) + hw.getName().getStringValue().toLowerCase() = "content-type" ) or exists(DataFlow::CallNode call | call.getTarget().hasQualifiedName("fmt", "Fprintf") |