mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #2469 from RasmusWL/python-modernise-twisted-library
Python: modernise twisted library
This commit is contained in:
@@ -211,7 +211,7 @@ module Value {
|
||||
}
|
||||
|
||||
/** Gets the `Value` for the integer constant `i`, if it exists.
|
||||
* There will be no `Value` for most integers, but the following are
|
||||
* There will be no `Value` for most integers, but the following are
|
||||
* guaranteed to exist:
|
||||
* * From zero to 511 inclusive.
|
||||
* * All powers of 2 (up to 2**30)
|
||||
@@ -486,6 +486,11 @@ class PythonFunctionValue extends FunctionValue {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a control flow node corresponding to a return statement in this function */
|
||||
ControlFlowNode getAReturnedNode() {
|
||||
result = this.getScope().getAReturnValueFlowNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Class representing builtin functions, such as `len` or `print` */
|
||||
|
||||
@@ -9,8 +9,8 @@ import semmle.python.web.flask.General
|
||||
*/
|
||||
class FlaskRoutedResponse extends HttpResponseTaintSink {
|
||||
FlaskRoutedResponse() {
|
||||
exists(PyFunctionObject response |
|
||||
flask_routing(_, response.getFunction()) and
|
||||
exists(PythonFunctionValue response |
|
||||
flask_routing(_, response.getScope()) and
|
||||
this = response.getAReturnedNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ private import semmle.python.web.Http
|
||||
*/
|
||||
class PyramidRoutedResponse extends HttpResponseTaintSink {
|
||||
PyramidRoutedResponse() {
|
||||
exists(PyFunctionObject view |
|
||||
is_pyramid_view_function(view.getFunction()) and
|
||||
exists(PythonFunctionValue view |
|
||||
is_pyramid_view_function(view.getScope()) and
|
||||
this = view.getAReturnedNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,53 +1,35 @@
|
||||
import python
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.web.Http
|
||||
import Twisted
|
||||
|
||||
/** A twisted.web.http.Request object */
|
||||
class TwistedRequest extends TaintKind {
|
||||
|
||||
TwistedRequest() {
|
||||
this = "twisted.request.http.Request"
|
||||
}
|
||||
TwistedRequest() { this = "twisted.request.http.Request" }
|
||||
|
||||
override TaintKind getTaintOfAttribute(string name) {
|
||||
result instanceof ExternalStringSequenceDictKind and
|
||||
(
|
||||
name = "args"
|
||||
)
|
||||
name = "args"
|
||||
or
|
||||
result instanceof ExternalStringKind and
|
||||
(
|
||||
name = "uri"
|
||||
)
|
||||
name = "uri"
|
||||
}
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
(
|
||||
name = "getHeader" or
|
||||
name = "getCookie" or
|
||||
name = "getUser" or
|
||||
name = "getPassword"
|
||||
) and
|
||||
result instanceof ExternalStringKind
|
||||
(
|
||||
name = "getHeader" or
|
||||
name = "getCookie" or
|
||||
name = "getUser" or
|
||||
name = "getPassword"
|
||||
) and
|
||||
result instanceof ExternalStringKind
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class TwistedRequestSource extends TaintSource {
|
||||
TwistedRequestSource() { isTwistedRequestInstance(this) }
|
||||
|
||||
TwistedRequestSource() {
|
||||
isTwistedRequestInstance(this)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "Twisted request source"
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof TwistedRequest
|
||||
}
|
||||
override string toString() { result = "Twisted request source" }
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) { kind instanceof TwistedRequest }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import python
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.web.Http
|
||||
import semmle.python.security.strings.Basic
|
||||
@@ -8,7 +7,7 @@ import Request
|
||||
|
||||
class TwistedResponse extends TaintSink {
|
||||
TwistedResponse() {
|
||||
exists(PyFunctionObject func, string name |
|
||||
exists(PythonFunctionValue func, string name, Return ret |
|
||||
isKnownRequestHandlerMethodName(name) and
|
||||
name = func.getName() and
|
||||
func = getTwistedRequestHandlerMethod(name) and
|
||||
@@ -16,13 +15,9 @@ class TwistedResponse extends TaintSink {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) {
|
||||
kind instanceof ExternalStringKind
|
||||
}
|
||||
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
|
||||
|
||||
override string toString() {
|
||||
result = "Twisted response"
|
||||
}
|
||||
override string toString() { result = "Twisted response" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,7 +25,7 @@ class TwistedResponse extends TaintSink {
|
||||
* object, which affects the properties of the subsequent response sent to this
|
||||
* request.
|
||||
*/
|
||||
class TwistedRequestSetter extends HttpResponseTaintSink {
|
||||
class TwistedRequestSetter extends HttpResponseTaintSink {
|
||||
TwistedRequestSetter() {
|
||||
exists(CallNode call, ControlFlowNode node, string name |
|
||||
(
|
||||
@@ -44,11 +39,7 @@ class TwistedResponse extends TaintSink {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) {
|
||||
kind instanceof ExternalStringKind
|
||||
}
|
||||
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
|
||||
|
||||
override string toString() {
|
||||
result = "Twisted request setter"
|
||||
}
|
||||
}
|
||||
override string toString() { result = "Twisted request setter" }
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import python
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
|
||||
private ClassObject theTwistedHttpRequestClass() {
|
||||
result = ModuleObject::named("twisted.web.http").attr("Request")
|
||||
private ClassValue theTwistedHttpRequestClass() {
|
||||
result = Value::named("twisted.web.http.Request")
|
||||
}
|
||||
|
||||
private ClassObject theTwistedHttpResourceClass() {
|
||||
result = ModuleObject::named("twisted.web.resource").attr("Resource")
|
||||
private ClassValue theTwistedHttpResourceClass() {
|
||||
result = Value::named("twisted.web.resource.Resource")
|
||||
}
|
||||
|
||||
ClassObject aTwistedRequestHandlerClass() {
|
||||
result.getASuperType() = theTwistedHttpResourceClass()
|
||||
}
|
||||
ClassValue aTwistedRequestHandlerClass() { result.getABaseType+() = theTwistedHttpResourceClass() }
|
||||
|
||||
FunctionObject getTwistedRequestHandlerMethod(string name) {
|
||||
FunctionValue getTwistedRequestHandlerMethod(string name) {
|
||||
result = aTwistedRequestHandlerClass().declaredAttribute(name)
|
||||
}
|
||||
|
||||
@@ -24,29 +21,30 @@ predicate isKnownRequestHandlerMethodName(string name) {
|
||||
name.matches("render_%")
|
||||
}
|
||||
|
||||
/** Holds if `node` is likely to refer to an instance of the twisted
|
||||
/**
|
||||
* Holds if `node` is likely to refer to an instance of the twisted
|
||||
* `Request` class.
|
||||
*/
|
||||
predicate isTwistedRequestInstance(NameNode node) {
|
||||
node.refersTo(_, theTwistedHttpRequestClass(), _)
|
||||
node.pointsTo().getClass() = theTwistedHttpRequestClass()
|
||||
or
|
||||
/* In points-to analysis cannot infer that a given object is an instance of
|
||||
/*
|
||||
* In points-to analysis cannot infer that a given object is an instance of
|
||||
* the `twisted.web.http.Request` class, we also include any parameter
|
||||
* called `request` that appears inside a subclass of a request handler
|
||||
* class, and the appropriate arguments of known request handler methods.
|
||||
*/
|
||||
exists(Function func | func = node.getScope() |
|
||||
func.getEnclosingScope().(Class).getClassObject() = aTwistedRequestHandlerClass()
|
||||
) and
|
||||
(
|
||||
/* Any parameter called `request` */
|
||||
node.getId() = "request" and
|
||||
node.isParameter()
|
||||
or
|
||||
/* Any request parameter of a known request handler method */
|
||||
exists(FunctionObject func | node.getScope() = func.getFunction() |
|
||||
|
||||
exists(Function func |
|
||||
func = node.getScope() and
|
||||
func.getEnclosingScope() = aTwistedRequestHandlerClass().getScope()
|
||||
|
|
||||
/* Any parameter called `request` */
|
||||
node.getId() = "request" and
|
||||
node.isParameter()
|
||||
or
|
||||
/* Any request parameter of a known request handler method */
|
||||
isKnownRequestHandlerMethodName(func.getName()) and
|
||||
node.getNode() = func.getFunction().getArg(1)
|
||||
)
|
||||
node.getNode() = func.getArg(1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
| class MyRequestHandler1 | test.py:3 |
|
||||
| class MyRequestHandler2 | test.py:23 |
|
||||
| class MyRequestHandler3 | test.py:27 |
|
||||
| class MyRequestHandler4 | test.py:38 |
|
||||
| class MyRequestHandler5 | test.py:42 |
|
||||
7
python/ql/test/library-tests/web/twisted/Classes.ql
Normal file
7
python/ql/test/library-tests/web/twisted/Classes.ql
Normal file
@@ -0,0 +1,7 @@
|
||||
import python
|
||||
import semmle.python.TestUtils
|
||||
import semmle.python.web.twisted.Twisted
|
||||
|
||||
from ClassValue cls
|
||||
where cls = aTwistedRequestHandlerClass()
|
||||
select cls.toString(), remove_library_prefix(cls.getScope().getLocation())
|
||||
@@ -0,0 +1,8 @@
|
||||
| myrender | Function MyRequestHandler2.myrender | test.py:24 |
|
||||
| render | Function MyRequestHandler1.render | test.py:4 |
|
||||
| render | Function MyRequestHandler3.render | test.py:28 |
|
||||
| render | Function MyRequestHandler4.render | test.py:39 |
|
||||
| render | Function MyRequestHandler5.render | test.py:43 |
|
||||
| render_GET | Function MyRequestHandler1.render_GET | test.py:9 |
|
||||
| render_POST | Function MyRequestHandler1.render_POST | test.py:16 |
|
||||
| render_POST | Function MyRequestHandler3.render_POST | test.py:31 |
|
||||
7
python/ql/test/library-tests/web/twisted/Methods.ql
Normal file
7
python/ql/test/library-tests/web/twisted/Methods.ql
Normal file
@@ -0,0 +1,7 @@
|
||||
import python
|
||||
import semmle.python.TestUtils
|
||||
import semmle.python.web.twisted.Twisted
|
||||
|
||||
from FunctionValue func, string name
|
||||
where func = getTwistedRequestHandlerMethod(name)
|
||||
select name, func.toString(), remove_library_prefix(func.getScope().getLocation())
|
||||
8
python/ql/test/library-tests/web/twisted/Sinks.expected
Normal file
8
python/ql/test/library-tests/web/twisted/Sinks.expected
Normal file
@@ -0,0 +1,8 @@
|
||||
| test.py:7 | response | externally controlled string |
|
||||
| test.py:14 | response | externally controlled string |
|
||||
| test.py:21 | response | externally controlled string |
|
||||
| test.py:36 | do_stuff_with() | externally controlled string |
|
||||
| test.py:40 | Str | externally controlled string |
|
||||
| test.py:44 | Str | externally controlled string |
|
||||
| test.py:45 | Str | externally controlled string |
|
||||
| test.py:46 | Str | externally controlled string |
|
||||
10
python/ql/test/library-tests/web/twisted/Sinks.ql
Normal file
10
python/ql/test/library-tests/web/twisted/Sinks.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import python
|
||||
|
||||
import semmle.python.web.HttpRequest
|
||||
import semmle.python.web.HttpResponse
|
||||
import semmle.python.security.strings.Untrusted
|
||||
import semmle.python.TestUtils
|
||||
|
||||
from TaintSink sink, TaintKind kind
|
||||
where sink.sinks(kind)
|
||||
select remove_library_prefix(sink.getLocation()), sink.(ControlFlowNode).getNode().toString(), kind
|
||||
@@ -0,0 +1,8 @@
|
||||
| test.py:4 | request | twisted.request.http.Request |
|
||||
| test.py:9 | request | twisted.request.http.Request |
|
||||
| test.py:16 | request | twisted.request.http.Request |
|
||||
| test.py:24 | request | twisted.request.http.Request |
|
||||
| test.py:28 | myrequest | twisted.request.http.Request |
|
||||
| test.py:31 | postrequest | twisted.request.http.Request |
|
||||
| test.py:39 | request | twisted.request.http.Request |
|
||||
| test.py:43 | request | twisted.request.http.Request |
|
||||
11
python/ql/test/library-tests/web/twisted/Sources.ql
Normal file
11
python/ql/test/library-tests/web/twisted/Sources.ql
Normal file
@@ -0,0 +1,11 @@
|
||||
import python
|
||||
import semmle.python.TestUtils
|
||||
|
||||
import semmle.python.web.HttpRequest
|
||||
import semmle.python.web.HttpResponse
|
||||
import semmle.python.security.strings.Untrusted
|
||||
|
||||
|
||||
from TaintSource src, TaintKind kind
|
||||
where src.isSourceOf(kind)
|
||||
select remove_library_prefix(src.getLocation()), src.(ControlFlowNode).getNode().toString(), kind
|
||||
41
python/ql/test/library-tests/web/twisted/Taint.expected
Normal file
41
python/ql/test/library-tests/web/twisted/Taint.expected
Normal file
@@ -0,0 +1,41 @@
|
||||
| test.py:4 | request | twisted.request.http.Request |
|
||||
| test.py:5 | Attribute | externally controlled string |
|
||||
| test.py:5 | request | twisted.request.http.Request |
|
||||
| test.py:6 | request | twisted.request.http.Request |
|
||||
| test.py:9 | request | twisted.request.http.Request |
|
||||
| test.py:10 | request | twisted.request.http.Request |
|
||||
| test.py:11 | Attribute | externally controlled string |
|
||||
| test.py:11 | x | twisted.request.http.Request |
|
||||
| test.py:12 | request | twisted.request.http.Request |
|
||||
| test.py:13 | request | twisted.request.http.Request |
|
||||
| test.py:16 | request | twisted.request.http.Request |
|
||||
| test.py:17 | Attribute | {[externally controlled string]} |
|
||||
| test.py:17 | request | twisted.request.http.Request |
|
||||
| test.py:18 | Attribute | {[externally controlled string]} |
|
||||
| test.py:18 | Attribute() | [externally controlled string] |
|
||||
| test.py:18 | request | twisted.request.http.Request |
|
||||
| test.py:19 | Subscript | externally controlled string |
|
||||
| test.py:19 | foo | [externally controlled string] |
|
||||
| test.py:20 | quux | externally controlled string |
|
||||
| test.py:24 | request | twisted.request.http.Request |
|
||||
| test.py:25 | request | twisted.request.http.Request |
|
||||
| test.py:28 | myrequest | twisted.request.http.Request |
|
||||
| test.py:29 | myrequest | twisted.request.http.Request |
|
||||
| test.py:31 | postrequest | twisted.request.http.Request |
|
||||
| test.py:32 | Attribute() | externally controlled string |
|
||||
| test.py:32 | postrequest | twisted.request.http.Request |
|
||||
| test.py:33 | Attribute() | externally controlled string |
|
||||
| test.py:33 | postrequest | twisted.request.http.Request |
|
||||
| test.py:34 | Attribute() | externally controlled string |
|
||||
| test.py:34 | postrequest | twisted.request.http.Request |
|
||||
| test.py:35 | Attribute() | externally controlled string |
|
||||
| test.py:35 | postrequest | twisted.request.http.Request |
|
||||
| test.py:36 | w | externally controlled string |
|
||||
| test.py:36 | x | externally controlled string |
|
||||
| test.py:36 | y | externally controlled string |
|
||||
| test.py:36 | z | externally controlled string |
|
||||
| test.py:39 | request | twisted.request.http.Request |
|
||||
| test.py:40 | request | twisted.request.http.Request |
|
||||
| test.py:43 | request | twisted.request.http.Request |
|
||||
| test.py:44 | request | twisted.request.http.Request |
|
||||
| test.py:45 | request | twisted.request.http.Request |
|
||||
11
python/ql/test/library-tests/web/twisted/Taint.ql
Normal file
11
python/ql/test/library-tests/web/twisted/Taint.ql
Normal file
@@ -0,0 +1,11 @@
|
||||
import python
|
||||
import semmle.python.TestUtils
|
||||
|
||||
import semmle.python.web.HttpRequest
|
||||
import semmle.python.web.HttpResponse
|
||||
import semmle.python.security.strings.Untrusted
|
||||
|
||||
from TaintedNode node
|
||||
|
||||
select remove_library_prefix(node.getLocation()), node.getAstNode().toString(), node.getTaintKind()
|
||||
|
||||
2
python/ql/test/library-tests/web/twisted/options
Normal file
2
python/ql/test/library-tests/web/twisted/options
Normal file
@@ -0,0 +1,2 @@
|
||||
semmle-extractor-options: --max-import-depth=1 -p ../../../query-tests/Security/lib/
|
||||
optimize: true
|
||||
51
python/ql/test/library-tests/web/twisted/test.py
Normal file
51
python/ql/test/library-tests/web/twisted/test.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from twisted.web import resource
|
||||
|
||||
class MyRequestHandler1(resource.Resource):
|
||||
def render(self, request):
|
||||
foo(request.uri)
|
||||
response = do_stuff_with(request)
|
||||
return response
|
||||
|
||||
def render_GET(self, request):
|
||||
x = request
|
||||
bar(x.uri)
|
||||
do_stuff_with(request)
|
||||
response = do_stuff_with(request)
|
||||
return response
|
||||
|
||||
def render_POST(self, request):
|
||||
baz(request.args)
|
||||
foo = request.args.get("baz")
|
||||
quux = foo[5]
|
||||
response = do_stuff_with(quux)
|
||||
return response
|
||||
|
||||
class MyRequestHandler2(resource.Resource):
|
||||
def myrender(self, request):
|
||||
do_stuff_with(request)
|
||||
|
||||
class MyRequestHandler3(resource.Resource):
|
||||
def render(self, myrequest):
|
||||
do_stuff_with(myrequest)
|
||||
|
||||
def render_POST(self, postrequest):
|
||||
x = postrequest.getHeader("someheader")
|
||||
y = postrequest.getCookie("somecookie")
|
||||
z = postrequest.getUser()
|
||||
w = postrequest.getPassword()
|
||||
return do_stuff_with(x,y,z,w)
|
||||
|
||||
class MyRequestHandler4(resource.Resource):
|
||||
def render(self, request):
|
||||
request.write("Foobar")
|
||||
|
||||
class MyRequestHandler5(resource.Resource):
|
||||
def render(self, request):
|
||||
request.setHeader("foo", "bar")
|
||||
request.addCookie("key", "value")
|
||||
return "This is my response."
|
||||
|
||||
class NotATwistedRequestHandler(object):
|
||||
def render(self, request):
|
||||
return do_stuff_with(request)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
class Request(object):
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
class Resource(object):
|
||||
pass
|
||||
Reference in New Issue
Block a user