Skip to content

Commit ba054bd

Browse files
Manually specify subclasses for redirect models
1 parent 7df8b1b commit ba054bd

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

python/ql/lib/semmle/python/frameworks/Pyramid.qll

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,9 @@ module Pyramid {
183183
override string getMimetypeDefault() { result = "text/html" }
184184
}
185185

186-
/** Gets a reference to the class `pyramid.response.Response` or a subclass. */
187-
API::Node subclassRef() {
188-
result = API::moduleImport("pyramid").getMember("response").getMember("Response") or
189-
result = ModelOutput::getATypeNode("pyramid.response.Response~Subclass").getASubclass*()
186+
/** Gets a reference to the class `pyramid.response.Response`. */
187+
API::Node classRef() {
188+
result = API::moduleImport("pyramid").getMember("response").getMember("Response")
190189
}
191190

192191
/**
@@ -215,7 +214,7 @@ module Pyramid {
215214

216215
/** An instantiation of the class `pyramid.response.Response` or a subclass. */
217216
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
218-
ClassInstantiation() { this = subclassRef().getACall() }
217+
ClassInstantiation() { this = classRef().getACall() }
219218

220219
override DataFlow::Node getBody() { result = [this.getArg(0), this.getArgByName("body")] }
221220

@@ -277,20 +276,20 @@ module Pyramid {
277276

278277
/** Provides models for pyramid http redirects. */
279278
module Redirect {
280-
/** Gets a reference to a subclass of `pyramid.httpexceptions._HTTPMove`, which each each exception class representing an HTTP redirect response is a subclass of. */
281-
API::Node subclassRef() {
279+
/** Gets a reference to a class that represents an HTTP redirect response.. */
280+
API::Node classRef() {
282281
result =
283282
API::moduleImport("pyramid")
284283
.getMember("httpexceptions")
285-
.getMember("_HTTPMove")
286-
.getASubclass*() or
287-
result =
288-
ModelOutput::getATypeNode("pyramid.httpexceptions._HTTPMove~Subclass").getASubclass*()
284+
.getMember([
285+
"HTTPMultipleChoices", "HTTPMovedPermanently", "HTTPFound", "HTTPSeeOther",
286+
"HTTPUseProxy", "HTTPTemporaryRedirect", "HTTPPermanentRedirect"
287+
])
289288
}
290289

291290
/** Gets a call to a pyramid HTTP exception class that represents an HTTP redirect response. */
292291
class PyramidRedirect extends Http::Server::HttpRedirectResponse::Range, DataFlow::CallCfgNode {
293-
PyramidRedirect() { this = subclassRef().getACall() }
292+
PyramidRedirect() { this = classRef().getACall() }
294293

295294
override DataFlow::Node getRedirectLocation() {
296295
result = [this.getArg(0), this.getArgByName("location")]

python/ql/test/library-tests/frameworks/pyramid/pyramid_test.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pyramid.view import view_config
22
from pyramid.config import Configurator
33
from pyramid.response import Response
4+
from pyramid.httpexceptions import HTTPMultipleChoices, HTTPMovedPermanently, HTTPFound, HTTPSeeOther, HTTPUseProxy, HTTPTemporaryRedirect, HTTPPermanentRedirect
45
from wsgiref.simple_server import make_server
56

67
def ignore(*args, **kwargs): pass
@@ -45,6 +46,8 @@ def test1(request): # $ requestHandler
4546

4647
request.text, # $ tainted
4748

49+
request.matchdict, # $ tainted
50+
4851
request.path, # $ tainted
4952
request.path_info, # $ tainted
5053
request.path_info_peek(), # $ tainted
@@ -87,12 +90,23 @@ def test3(ctx, req): # $ requestHandler
8790
resp.set_cookie(value="there", name="hi") # $ CookieWrite CookieName="hi" CookieValue="there"
8891
return "Ok" # $ HttpResponse responseBody="Ok" mimetype=text/html
8992

93+
@view_config(route_name="test4", renderer="string") # $ routeSetup
94+
def test4(request): # $ requestHandler
95+
a = HTTPMultipleChoices("redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
96+
b = HTTPMovedPermanently(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
97+
c = HTTPFound(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
98+
d = HTTPSeeOther(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
99+
e = HTTPUseProxy(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
100+
f = HTTPTemporaryRedirect(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
101+
g = HTTPPermanentRedirect(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
102+
raise a
103+
90104
if __name__ == "__main__":
91105
with Configurator() as config:
92-
for i in range(1,4):
106+
for i in range(1,5):
93107
config.add_route(f"test{i}", f"/test{i}")
94108
config.add_view(test2, route_name="test2") # $ routeSetup
95109
config.scan()
96-
server = make_server('127.0.0.1', 8000, config.make_wsgi_app())
110+
server = make_server('127.0.0.1', 8080, config.make_wsgi_app())
97111
print("serving")
98112
server.serve_forever()

0 commit comments

Comments
 (0)