mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Python: Expand Tornado tests and add annotations
I should probably have split this up into 2 commits, so sorry that didn't happen :|
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import python
|
||||
import experimental.meta.ConceptsTest
|
||||
//
|
||||
// class DedicatedResponseTest extends HttpServerHttpResponseTest {
|
||||
// DedicatedResponseTest() { file.getShortName() = "response_test.py" }
|
||||
// }
|
||||
//
|
||||
// class OtherResponseTest extends HttpServerHttpResponseTest {
|
||||
// OtherResponseTest() { not this instanceof DedicatedResponseTest }
|
||||
//
|
||||
// override string getARelevantTag() { result = "HttpResponse" }
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
From Tornado 6.0 Python 3.5+ is [required](https://www.tornadoweb.org/en/stable/index.html#installation)
|
||||
|
||||
https://www.tornadoweb.org/en/stable/guide/structure.html#handling-request-input
|
||||
@@ -0,0 +1,41 @@
|
||||
| taint_test.py:6 | fail | get | name |
|
||||
| taint_test.py:6 | fail | get | number |
|
||||
| taint_test.py:7 | ok | get | foo |
|
||||
| taint_test.py:11 | fail | get | self.get_argument(..) |
|
||||
| taint_test.py:12 | fail | get | self.get_arguments(..) |
|
||||
| taint_test.py:13 | fail | get | self.get_arguments(..)[0] |
|
||||
| taint_test.py:15 | fail | get | self.get_body_argument(..) |
|
||||
| taint_test.py:16 | fail | get | self.get_body_arguments(..) |
|
||||
| taint_test.py:17 | fail | get | self.get_body_arguments(..)[0] |
|
||||
| taint_test.py:19 | fail | get | self.get_query_argument(..) |
|
||||
| taint_test.py:20 | fail | get | self.get_query_arguments(..) |
|
||||
| taint_test.py:21 | fail | get | self.get_query_arguments(..)[0] |
|
||||
| taint_test.py:23 | fail | get | self.path_args |
|
||||
| taint_test.py:24 | fail | get | self.path_args[0] |
|
||||
| taint_test.py:26 | fail | get | self.path_kwargs |
|
||||
| taint_test.py:27 | fail | get | self.path_kwargs["name"] |
|
||||
| taint_test.py:34 | fail | get | request |
|
||||
| taint_test.py:36 | fail | get | request.uri |
|
||||
| taint_test.py:37 | fail | get | request.path |
|
||||
| taint_test.py:38 | fail | get | request.query |
|
||||
| taint_test.py:39 | fail | get | request.full_url() |
|
||||
| taint_test.py:41 | fail | get | request.remote_ip |
|
||||
| taint_test.py:43 | fail | get | request.body |
|
||||
| taint_test.py:45 | fail | get | request.arguments |
|
||||
| taint_test.py:46 | fail | get | request.arguments["name"] |
|
||||
| taint_test.py:47 | fail | get | request.arguments["name"][0] |
|
||||
| taint_test.py:49 | fail | get | request.query_arguments |
|
||||
| taint_test.py:50 | fail | get | request.query_arguments["name"] |
|
||||
| taint_test.py:51 | fail | get | request.query_arguments["name"][0] |
|
||||
| taint_test.py:53 | fail | get | request.body_arguments |
|
||||
| taint_test.py:54 | fail | get | request.body_arguments["name"] |
|
||||
| taint_test.py:55 | fail | get | request.body_arguments["name"][0] |
|
||||
| taint_test.py:58 | fail | get | request.headers |
|
||||
| taint_test.py:59 | fail | get | request.headers["header-name"] |
|
||||
| taint_test.py:60 | fail | get | request.headers.get_list(..) |
|
||||
| taint_test.py:61 | fail | get | request.headers.get_all() |
|
||||
| taint_test.py:62 | fail | get | ListComp |
|
||||
| taint_test.py:65 | fail | get | request.cookies |
|
||||
| taint_test.py:66 | fail | get | request.cookies["cookie-name"] |
|
||||
| taint_test.py:67 | fail | get | request.cookies["cookie-name"].key |
|
||||
| taint_test.py:68 | fail | get | request.cookies["cookie-name"].value |
|
||||
@@ -0,0 +1,6 @@
|
||||
import experimental.dataflow.tainttracking.TestTaintLib
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
|
||||
class RemoteFlowTestTaintConfiguration extends TestTaintTrackingConfiguration {
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
}
|
||||
@@ -2,26 +2,26 @@ import tornado.web
|
||||
|
||||
|
||||
class BasicHandler(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("BasicHandler " + self.get_argument("xss"))
|
||||
|
||||
def post(self):
|
||||
def post(self): # $ MISSING: requestHandler
|
||||
self.write("BasicHandler (POST)")
|
||||
|
||||
|
||||
class DeepInheritance(BasicHandler):
|
||||
def get(self):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("DeepInheritance" + self.get_argument("also_xss"))
|
||||
|
||||
|
||||
class FormHandler(tornado.web.RequestHandler):
|
||||
def post(self):
|
||||
def post(self): # $ MISSING: requestHandler
|
||||
name = self.get_body_argument("name")
|
||||
self.write(name)
|
||||
|
||||
|
||||
class RedirectHandler(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
req = self.request
|
||||
h = req.headers
|
||||
url = h["url"]
|
||||
@@ -29,7 +29,7 @@ class RedirectHandler(tornado.web.RequestHandler):
|
||||
|
||||
|
||||
class BaseReverseInheritance(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("hello from BaseReverseInheritance")
|
||||
|
||||
|
||||
@@ -38,13 +38,16 @@ class ReverseInheritance(BaseReverseInheritance):
|
||||
|
||||
|
||||
def make_app():
|
||||
return tornado.web.Application([
|
||||
(r"/basic", BasicHandler),
|
||||
(r"/deep", DeepInheritance),
|
||||
(r"/form", FormHandler),
|
||||
(r"/redirect", RedirectHandler),
|
||||
(r"/reverse-inheritance", ReverseInheritance),
|
||||
])
|
||||
return tornado.web.Application(
|
||||
[
|
||||
(r"/basic", BasicHandler), # $ MISSING: routeSetup="/basic"
|
||||
(r"/deep", DeepInheritance), # $ MISSING: routeSetup="/deep"
|
||||
(r"/form", FormHandler), # $ MISSING: routeSetup="/form"
|
||||
(r"/redirect", RedirectHandler), # $ MISSING: routeSetup="/redirect"
|
||||
(r"/reverse-inheritance", ReverseInheritance), # $ MISSING: routeSetup="/reverse-inheritance"
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --max-import-depth=1 --lang=3
|
||||
@@ -0,0 +1,35 @@
|
||||
import tornado.web
|
||||
|
||||
|
||||
class ResponseWriting(tornado.web.RequestHandler):
|
||||
def get(self, type_): # $ MISSING: requestHandler routedParameter=type_
|
||||
if type_ == "str":
|
||||
self.write("foo")
|
||||
elif type_ == "bytes":
|
||||
self.write(b"foo")
|
||||
elif type_ == "dict":
|
||||
# Content-type will be set to `application/json`
|
||||
self.write({"foo": 42})
|
||||
else:
|
||||
raise Exception("Bad type {} {}".format(type_, type(type_)))
|
||||
|
||||
|
||||
def make_app():
|
||||
return tornado.web.Application(
|
||||
[
|
||||
(r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ MISSING: routeSetup="/ResponseWriting/(str|bytes|dict)"
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import tornado.ioloop
|
||||
|
||||
app = make_app()
|
||||
app.listen(8888)
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
|
||||
# http://localhost:8888/ResponseWriting/str
|
||||
# http://localhost:8888/ResponseWriting/bytes
|
||||
# http://localhost:8888/ResponseWriting/dict
|
||||
@@ -0,0 +1,110 @@
|
||||
import tornado.web
|
||||
import tornado.routing
|
||||
|
||||
|
||||
class FooHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y
|
||||
self.write("FooHandler {} {}".format(x, y))
|
||||
|
||||
|
||||
class BarHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y
|
||||
self.write("BarHandler {} {}".format(x, y))
|
||||
|
||||
|
||||
class BazHandler(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y
|
||||
self.write("BazHandler {} {}".format(x, y))
|
||||
|
||||
|
||||
class KwArgs(tornado.web.RequestHandler):
|
||||
def get(self, *, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y
|
||||
self.write("KwArgs {} {}".format(x, y))
|
||||
|
||||
|
||||
class OnlyLocalhost(tornado.web.RequestHandler):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("OnlyLocalhost")
|
||||
|
||||
|
||||
class One(tornado.web.RequestHandler):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("One")
|
||||
|
||||
|
||||
class Two(tornado.web.RequestHandler):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("Two")
|
||||
|
||||
|
||||
class Three(tornado.web.RequestHandler):
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("Three")
|
||||
|
||||
|
||||
class AddedLater(tornado.web.RequestHandler):
|
||||
def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y
|
||||
self.write("AddedLater {} {}".format(x, y))
|
||||
|
||||
|
||||
class PossiblyNotRouted(tornado.web.RequestHandler):
|
||||
# Even if our analysis can't find a route-setup for this class, we should still
|
||||
# consider it to be a handle incoming HTTP requests
|
||||
|
||||
def get(self): # $ MISSING: requestHandler
|
||||
self.write("NotRouted")
|
||||
|
||||
|
||||
def make_app():
|
||||
# see https://www.tornadoweb.org/en/stable/routing.html for even more examples
|
||||
app = tornado.web.Application(
|
||||
[
|
||||
(r"/foo/([0-9]+)/([0-9]+)?", FooHandler), # $ MISSING: routeSetup="/foo/([0-9]+)/([0-9]+)?"
|
||||
tornado.web.URLSpec(r"/bar/([0-9]+)/([0-9]+)?", BarHandler), # $ MISSING: routeSetup="/bar/([0-9]+)/([0-9]+)?"
|
||||
# Very verbose way to write same as FooHandler
|
||||
tornado.routing.Rule(tornado.routing.PathMatches(r"/baz/([0-9]+)/([0-9]+)?"), BazHandler), # $ MISSING: routeSetup="/baz/([0-9]+)/([0-9]+)?"
|
||||
(r"/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?", KwArgs), # $ MISSING: routeSetup="/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?"
|
||||
# You can do nesting
|
||||
(r"/(one|two|three)", [
|
||||
(r"/one", One), # $ MISSING: routeSetup="/one"
|
||||
(r"/two", Two), # $ MISSING: routeSetup="/two"
|
||||
(r"/three", Three) # $ MISSING: routeSetup="/three"
|
||||
]),
|
||||
# which is _one_ recommended way to ensure known host is used
|
||||
(tornado.routing.HostMatches(r"(localhost|127\.0\.0\.1)"), [
|
||||
("/only-localhost", OnlyLocalhost) # $ MISSING: routeSetup="/only-localhost"
|
||||
]),
|
||||
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
app.add_handlers(r".*", [(r"/added-later/([0-9]+)/([0-9]+)?", AddedLater)]) # $ MISSING: routeSetup="/added-later/([0-9]+)/([0-9]+)?"
|
||||
return app
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import tornado.ioloop
|
||||
app = make_app()
|
||||
app.listen(8888)
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
|
||||
# http://localhost:8888/foo/42/
|
||||
# http://localhost:8888/foo/42/1337
|
||||
|
||||
# http://localhost:8888/bar/42/
|
||||
# http://localhost:8888/bar/42/1337
|
||||
|
||||
# http://localhost:8888/baz/42/
|
||||
# http://localhost:8888/baz/42/1337
|
||||
|
||||
# http://localhost:8888/kw-args/42/
|
||||
# http://localhost:8888/kw-args/42/1337
|
||||
|
||||
# http://localhost:8888/only-localhost
|
||||
|
||||
# http://localhost:8888/one
|
||||
# http://localhost:8888/two
|
||||
# http://localhost:8888/three
|
||||
|
||||
# http://localhost:8888/added-later
|
||||
@@ -0,0 +1,90 @@
|
||||
import tornado.web
|
||||
|
||||
|
||||
class TaintTest(tornado.web.RequestHandler):
|
||||
def get(self, name = "World!", number="0", foo="foo"): # $ MISSING: requestHandler routedParameter=name routedParameter=number
|
||||
ensure_tainted(name, number)
|
||||
ensure_not_tainted(foo)
|
||||
|
||||
ensure_tainted(
|
||||
# see https://www.tornadoweb.org/en/stable/web.html#input
|
||||
self.get_argument("name"),
|
||||
self.get_arguments("name"),
|
||||
self.get_arguments("name")[0],
|
||||
|
||||
self.get_body_argument("name"),
|
||||
self.get_body_arguments("name"),
|
||||
self.get_body_arguments("name")[0],
|
||||
|
||||
self.get_query_argument("name"),
|
||||
self.get_query_arguments("name"),
|
||||
self.get_query_arguments("name")[0],
|
||||
|
||||
self.path_args,
|
||||
self.path_args[0],
|
||||
|
||||
self.path_kwargs,
|
||||
self.path_kwargs["name"],
|
||||
)
|
||||
|
||||
request = self.request
|
||||
|
||||
ensure_tainted(
|
||||
# see https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest
|
||||
request,
|
||||
|
||||
request.uri,
|
||||
request.path,
|
||||
request.query,
|
||||
request.full_url(),
|
||||
|
||||
request.remote_ip,
|
||||
|
||||
request.body,
|
||||
|
||||
request.arguments,
|
||||
request.arguments["name"],
|
||||
request.arguments["name"][0],
|
||||
|
||||
request.query_arguments,
|
||||
request.query_arguments["name"],
|
||||
request.query_arguments["name"][0],
|
||||
|
||||
request.body_arguments,
|
||||
request.body_arguments["name"],
|
||||
request.body_arguments["name"][0],
|
||||
|
||||
# dict-like, see https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPHeaders
|
||||
request.headers,
|
||||
request.headers["header-name"],
|
||||
request.headers.get_list("header-name"),
|
||||
request.headers.get_all(),
|
||||
[(k, v) for (k, v) in request.headers.get_all()],
|
||||
|
||||
# Dict[str, http.cookies.Morsel]
|
||||
request.cookies,
|
||||
request.cookies["cookie-name"],
|
||||
request.cookies["cookie-name"].key,
|
||||
request.cookies["cookie-name"].value,
|
||||
)
|
||||
|
||||
|
||||
def make_app():
|
||||
return tornado.web.Application(
|
||||
[
|
||||
(r"/test_taint/([^/]+)/([0-9]+)", TaintTest), # $ MISSING: routeSetup="/test_taint/([^/]+)/([0-9]+)"
|
||||
],
|
||||
debug=True,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import tornado.ioloop
|
||||
|
||||
app = make_app()
|
||||
app.listen(8888)
|
||||
tornado.ioloop.IOLoop.current().start()
|
||||
|
||||
# http://localhost:8888/ResponseWriting/str
|
||||
# http://localhost:8888/ResponseWriting/bytes
|
||||
# http://localhost:8888/ResponseWriting/dict
|
||||
Reference in New Issue
Block a user