Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d60221b

Browse files
committed
Python: Model return from flask handler as HTTP response
When dealing with ``` resp = make_response(...) return resp ``` ideally we don't want to mark the return as a creation of a HTTP response. I'll deal with this in a second commit, to show off how annoying it looks in the tests right now :D
1 parent 44ba346 commit d60221b

5 files changed

Lines changed: 75 additions & 12 deletions

File tree

python/ql/src/experimental/semmle/python/frameworks/Flask.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,4 +479,19 @@ private module FlaskModel {
479479

480480
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
481481
}
482+
483+
private class FlaskRouteHandlerReturn extends HTTP::Server::HttpResponse::Range, DataFlow::CfgNode {
484+
FlaskRouteHandlerReturn() {
485+
exists(Function routeHandler |
486+
routeHandler = any(FlaskRouteSetup rs).getARouteHandler() and
487+
node = routeHandler.getAReturnValueFlowNode()
488+
)
489+
}
490+
491+
override DataFlow::Node getBody() { result = this }
492+
493+
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
494+
495+
override string getMimetypeDefault() { result = "text/html" }
496+
}
482497
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
2+
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
3+
| response_test.py:19:12:19:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
4+
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
5+
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
6+
| response_test.py:25:12:25:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
7+
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
8+
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
9+
| response_test.py:35:12:35:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
10+
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
11+
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
12+
| response_test.py:43:12:43:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
13+
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
14+
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
15+
| response_test.py:51:12:51:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
16+
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: HttpResponse= |
17+
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: mimetype=text/html |
18+
| response_test.py:58:12:58:19 | ControlFlowNode for response | Unexpected result: responseBody=response |
19+
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
20+
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
21+
| response_test.py:70:12:70:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
22+
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
23+
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
24+
| response_test.py:77:12:77:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
25+
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
26+
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
27+
| response_test.py:87:12:87:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
28+
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
29+
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
30+
| response_test.py:93:12:93:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
31+
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
32+
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
33+
| response_test.py:100:12:100:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
34+
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
35+
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
36+
| response_test.py:107:12:107:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
37+
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
38+
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
39+
| response_test.py:115:12:115:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
40+
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
41+
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
42+
| response_test.py:123:12:123:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
43+
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
44+
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
45+
| response_test.py:131:12:131:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |
46+
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: HttpResponse= |
47+
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: mimetype=text/html |
48+
| response_test.py:139:12:139:15 | ControlFlowNode for resp | Unexpected result: responseBody=resp |

python/ql/test/experimental/library-tests/frameworks/flask/old_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
@app.route("/") # $routeSetup="/"
77
def hello_world(): # $routeHandler
8-
return "Hello World!"
8+
return "Hello World!" # $HttpResponse
99

1010
from flask.views import MethodView
1111

@@ -26,14 +26,14 @@ def get(self, user_id): # $f-:routeHandler
2626

2727
@app.route("/dangerous") # $routeSetup="/dangerous"
2828
def dangerous(): # $routeHandler
29-
return request.args.get('payload')
29+
return request.args.get('payload') # $HttpResponse
3030

3131
@app.route("/dangerous-with-cfg-split") # $routeSetup="/dangerous-with-cfg-split"
3232
def dangerous2(): # $routeHandler
3333
x = request.form['param0']
3434
if request.method == "POST":
35-
return request.form['param1']
36-
return None
35+
return request.form['param1'] # $HttpResponse
36+
return None # $f+:HttpResponse
3737

3838
@app.route("/unsafe") # $routeSetup="/unsafe"
3939
def unsafe(): # $routeHandler

python/ql/test/experimental/library-tests/frameworks/flask/response_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
@app.route("/html1") # $routeSetup="/html1"
99
def html1(): # $routeHandler
10-
return "<h1>hello</h1>" # $f-:HttpResponse $f-:mimetype=text/html $f-:responseBody="<h1>hello</h1>"
10+
return "<h1>hello</h1>" # $HttpResponse $mimetype=text/html $responseBody="<h1>hello</h1>"
1111

1212

1313
@app.route("/html2") # $routeSetup="/html2"

python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def debug(foo, bar): # $routeHandler $routedParameter=foo $routedParameter=bar
200200

201201
print("request.pragma {!r}".format(request.pragma))
202202

203-
return 'ok'
203+
return 'ok' # $HttpResponse
204204

205205
@app.route("/stream", methods=['POST']) # $routeSetup="/stream"
206206
def stream(): # $routeHandler
@@ -210,7 +210,7 @@ def stream(): # $routeHandler
210210
# just works :)
211211
print(s.read())
212212

213-
return 'ok'
213+
return 'ok' # $HttpResponse
214214

215215
@app.route("/input_stream", methods=['POST']) # $routeSetup="/input_stream"
216216
def input_stream(): # $routeHandler
@@ -221,14 +221,14 @@ def input_stream(): # $routeHandler
221221
# be handled manually
222222
print(s.read())
223223

224-
return 'ok'
224+
return 'ok' # $HttpResponse
225225

226226
@app.route("/form", methods=['POST']) # $routeSetup="/form"
227227
def form(): # $routeHandler
228228
print(request.path)
229229
print("request.form", request.form)
230230

231-
return 'ok'
231+
return 'ok' # $HttpResponse
232232

233233
@app.route("/cache_control", methods=['POST']) # $routeSetup="/cache_control"
234234
def cache_control(): # $routeHandler
@@ -237,22 +237,22 @@ def cache_control(): # $routeHandler
237237
print("request.cache_control.max_stale", request.cache_control.max_stale, type(request.cache_control.max_stale))
238238
print("request.cache_control.min_fresh", request.cache_control.min_fresh, type(request.cache_control.min_fresh))
239239

240-
return 'ok'
240+
return 'ok' # $HttpResponse
241241

242242
@app.route("/file_upload", methods=['POST']) # $routeSetup="/file_upload"
243243
def file_upload(): # $routeHandler
244244
print(request.path)
245245
for k,v in request.files.items():
246246
print(k, v, v.name, v.filename, v.stream)
247247

248-
return 'ok'
248+
return 'ok' # $HttpResponse
249249

250250
@app.route("/args", methods=['GET']) # $routeSetup="/args"
251251
def args(): # $routeHandler
252252
print(request.path)
253253
print("request.args", request.args)
254254

255-
return 'ok'
255+
return 'ok' # $HttpResponse
256256

257257
# curl --header "My-Header: some-value" http://localhost:5000/debug/fooval/barval
258258
# curl --header "Pragma: foo, bar" --header "Pragma: stuff, foo" http://localhost:5000/debug/fooval/barval

0 commit comments

Comments
 (0)