Add more tests

This commit is contained in:
Joe Farebrother
2024-04-08 17:48:14 +01:00
parent eeef062f7c
commit d4a072818f
4 changed files with 135 additions and 1 deletions

View File

@@ -201,7 +201,7 @@ module Werkzeug {
DataFlow::MethodCallNode
{
HeaderWriteCall() {
this.calls(instance(), ["add", "add_header", "set", "set_default", "__setitem__"])
this.calls(instance(), ["add", "add_header", "set", "setdefault", "__setitem__"])
}
override DataFlow::Node getNameArg() { result = this.getArg(0) }

View File

@@ -10,6 +10,7 @@ edges
| flask_tests.py:1:29:1:35 | ControlFlowNode for request | flask_tests.py:54:41:54:47 | ControlFlowNode for request | provenance | |
| flask_tests.py:1:29:1:35 | ControlFlowNode for request | flask_tests.py:59:18:59:24 | ControlFlowNode for request | provenance | |
| flask_tests.py:1:29:1:35 | ControlFlowNode for request | flask_tests.py:60:36:60:42 | ControlFlowNode for request | provenance | |
| flask_tests.py:1:29:1:35 | ControlFlowNode for request | flask_tests.py:71:18:71:24 | ControlFlowNode for request | provenance | |
| flask_tests.py:9:5:9:14 | ControlFlowNode for rfs_header | flask_tests.py:13:17:13:26 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:9:18:9:24 | ControlFlowNode for request | flask_tests.py:9:5:9:14 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:20:5:20:14 | ControlFlowNode for rfs_header | flask_tests.py:23:22:23:31 | ControlFlowNode for rfs_header | provenance | |
@@ -24,6 +25,33 @@ edges
| flask_tests.py:54:41:54:47 | ControlFlowNode for request | flask_tests.py:54:41:54:66 | ControlFlowNode for Subscript | provenance | |
| flask_tests.py:59:18:59:24 | ControlFlowNode for request | flask_tests.py:60:36:60:61 | ControlFlowNode for Subscript | provenance | |
| flask_tests.py:60:36:60:42 | ControlFlowNode for request | flask_tests.py:60:36:60:61 | ControlFlowNode for Subscript | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:74:17:74:26 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:75:24:75:33 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:76:17:76:26 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:77:24:77:33 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:78:25:78:34 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:79:13:79:22 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:80:11:80:20 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:82:12:82:21 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:85:11:85:20 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | flask_tests.py:86:12:86:21 | ControlFlowNode for rfs_header | provenance | |
| flask_tests.py:71:18:71:24 | ControlFlowNode for request | flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | provenance | |
| wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | wsgiref_tests.py:6:5:6:10 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | wsgiref_tests.py:7:5:7:9 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:6:5:6:10 | ControlFlowNode for h_name | wsgiref_tests.py:8:17:8:22 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:7:5:7:9 | ControlFlowNode for h_val | wsgiref_tests.py:8:42:8:46 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | wsgiref_tests.py:16:25:16:30 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | wsgiref_tests.py:17:24:17:29 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | wsgiref_tests.py:18:24:18:29 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | wsgiref_tests.py:19:25:19:30 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | wsgiref_tests.py:20:13:20:18 | ControlFlowNode for h_name | provenance | |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | wsgiref_tests.py:16:50:16:54 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | wsgiref_tests.py:17:32:17:36 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | wsgiref_tests.py:18:32:18:36 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | wsgiref_tests.py:19:33:19:37 | ControlFlowNode for h_val | provenance | |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | wsgiref_tests.py:20:23:20:27 | ControlFlowNode for h_val | provenance | |
nodes
| flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember |
| flask_tests.py:1:29:1:35 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
@@ -48,6 +76,36 @@ nodes
| flask_tests.py:59:18:59:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| flask_tests.py:60:36:60:42 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| flask_tests.py:60:36:60:61 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| flask_tests.py:71:5:71:14 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:71:18:71:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| flask_tests.py:74:17:74:26 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:75:24:75:33 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:76:17:76:26 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:77:24:77:33 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:78:25:78:34 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:79:13:79:22 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:80:11:80:20 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:82:12:82:21 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:85:11:85:20 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| flask_tests.py:86:12:86:21 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
| wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | semmle.label | ControlFlowNode for environ |
| wsgiref_tests.py:6:5:6:10 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:7:5:7:9 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:8:17:8:22 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:8:42:8:46 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | semmle.label | ControlFlowNode for environ |
| wsgiref_tests.py:14:5:14:10 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:15:5:15:9 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:16:25:16:30 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:16:50:16:54 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:17:24:17:29 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:17:32:17:36 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:18:24:18:29 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:18:32:18:36 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:19:25:19:30 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:19:33:19:37 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
| wsgiref_tests.py:20:13:20:18 | ControlFlowNode for h_name | semmle.label | ControlFlowNode for h_name |
| wsgiref_tests.py:20:23:20:27 | ControlFlowNode for h_val | semmle.label | ControlFlowNode for h_val |
subpaths
#select
| flask_tests.py:13:17:13:26 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:13:17:13:26 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
@@ -57,3 +115,25 @@ subpaths
| flask_tests.py:49:72:49:97 | ControlFlowNode for Subscript | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:49:72:49:97 | ControlFlowNode for Subscript | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:54:41:54:66 | ControlFlowNode for Subscript | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:54:41:54:66 | ControlFlowNode for Subscript | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:60:36:60:61 | ControlFlowNode for Subscript | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:60:36:60:61 | ControlFlowNode for Subscript | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:74:17:74:26 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:74:17:74:26 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:75:24:75:33 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:75:24:75:33 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:76:17:76:26 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:76:17:76:26 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:77:24:77:33 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:77:24:77:33 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:78:25:78:34 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:78:25:78:34 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:79:13:79:22 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:79:13:79:22 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:80:11:80:20 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:80:11:80:20 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:82:12:82:21 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:82:12:82:21 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:85:11:85:20 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:85:11:85:20 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| flask_tests.py:86:12:86:21 | ControlFlowNode for rfs_header | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_tests.py:86:12:86:21 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_tests.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value |
| wsgiref_tests.py:8:17:8:22 | ControlFlowNode for h_name | wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | wsgiref_tests.py:8:17:8:22 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:8:42:8:46 | ControlFlowNode for h_val | wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | wsgiref_tests.py:8:42:8:46 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:4:14:4:20 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:16:25:16:30 | ControlFlowNode for h_name | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:16:25:16:30 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:16:50:16:54 | ControlFlowNode for h_val | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:16:50:16:54 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:17:24:17:29 | ControlFlowNode for h_name | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:17:24:17:29 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:17:32:17:36 | ControlFlowNode for h_val | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:17:32:17:36 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:18:24:18:29 | ControlFlowNode for h_name | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:18:24:18:29 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:18:32:18:36 | ControlFlowNode for h_val | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:18:32:18:36 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:19:25:19:30 | ControlFlowNode for h_name | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:19:25:19:30 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:19:33:19:37 | ControlFlowNode for h_val | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:19:33:19:37 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:20:13:20:18 | ControlFlowNode for h_name | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:20:13:20:18 | ControlFlowNode for h_name | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |
| wsgiref_tests.py:20:23:20:27 | ControlFlowNode for h_val | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | wsgiref_tests.py:20:23:20:27 | ControlFlowNode for h_val | This HTTP header is constructed from a $@. | wsgiref_tests.py:12:15:12:21 | ControlFlowNode for environ | user-provided value |

View File

@@ -66,5 +66,27 @@ def flask_escaped():
resp = make_response("hello", {rfs_header.replace("\n", ""): "HeaderValue"}) # GOOD - Newlines are removed from the input.
return resp
@app.route("/werkzeug_methods")
def werkzeug_methods():
rfs_header = request.args["rfs_header"]
response = Response()
headers = Headers()
headers.add(rfs_header, "HeaderValue") # BAD
headers.add_header(rfs_header, "HeaderValue") # BAD
headers.set(rfs_header, "HeaderValue") # BAD
headers.setdefault(rfs_header, "HeaderValue") # BAD
headers.__setitem__(rfs_header, "HeaderValue") # BAD
headers[rfs_header] = "HeaderValue" # BAD
h1 = {rfs_header: "HeaderValue"}
headers.extend(h1) # BAD
h2 = [(rfs_header, "HeaderValue")]
headers.extend(h2) # BAD
response.headers = headers
h3 = {rfs_header: "HeaderValue"}
h4 = [(rfs_header, "HeaderValue")]
resp2 = make_response("hi", h3) # BAD
resp3 = make_response("hi", h4) # BAD
return response
# if __name__ == "__main__":
# app.run(debug=True)

View File

@@ -0,0 +1,32 @@
from wsgiref.simple_server import make_server
from wsgiref.headers import Headers
def test_app(environ, start_response):
status = "200 OK"
h_name = environ["source_n"]
h_val = environ["source_v"]
headers = [(h_name, "val"), ("name", h_val)]
start_response(status, headers) # BAD
return [b"Hello"]
def test_app2(environ, start_response):
status = "200 OK"
h_name = environ["source_n"]
h_val = environ["source_v"]
headers = Headers([(h_name, "val"), ("name", h_val)]) # BAD
headers.add_header(h_name, h_val) # BAD
headers.setdefault(h_name, h_val) # BAD
headers.__setitem__(h_name, h_val) # BAD
headers[h_name] = h_val # BAD
start_response(status, headers)
return [b"Hello"]
def main1():
with make_server('', 8000, test_app) as httpd:
print("Serving on port 8000...")
httpd.serve_forever()
def main2():
with make_server('', 8000, test_app2) as httpd:
print("Serving on port 8000...")
httpd.serve_forever()