mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
Add concept tests + fix typo
This commit is contained in:
@@ -1094,7 +1094,7 @@ module Http {
|
||||
/**
|
||||
* Gets the argument containing the headers dictionary.
|
||||
*/
|
||||
DataFlow::Node geBulkArg() { result = super.getBulkArg() }
|
||||
DataFlow::Node getBulkArg() { result = super.getBulkArg() }
|
||||
|
||||
/**
|
||||
* Holds if newlines are accepted in the header name argument.
|
||||
|
||||
@@ -58,7 +58,7 @@ module HttpHeaderInjection {
|
||||
KeyValuePair item;
|
||||
|
||||
HeaderBulkWriteDictLiteral() {
|
||||
exists(Dict dict | DataFlow::localFlow(DataFlow::exprNode(dict), super.geBulkArg()) |
|
||||
exists(Dict dict | DataFlow::localFlow(DataFlow::exprNode(dict), super.getBulkArg()) |
|
||||
item = dict.getAnItem()
|
||||
)
|
||||
}
|
||||
@@ -83,7 +83,7 @@ module HttpHeaderInjection {
|
||||
Tuple item;
|
||||
|
||||
HeaderBulkWriteListLiteral() {
|
||||
exists(List list | DataFlow::localFlow(DataFlow::exprNode(list), super.geBulkArg()) |
|
||||
exists(List list | DataFlow::localFlow(DataFlow::exprNode(list), super.getBulkArg()) |
|
||||
item = list.getAnElt()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -319,6 +319,43 @@ module HttpServerHttpResponseTest implements TestSig {
|
||||
}
|
||||
}
|
||||
|
||||
module HttpResponseHeaderWriteTest implements TestSig {
|
||||
string getARelevantTag() { result = ["headerWriteName", "headerWriteValue", "headerWriteBulk"] }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
(
|
||||
exists(Http::Server::ResponseHeaderWrite write, DataFlow::Node node |
|
||||
location = node.getLocation() and
|
||||
element = node.toString()
|
||||
|
|
||||
node = write.getNameArg() and
|
||||
tag = "headerWriteName" and
|
||||
(if write.nameAllowsNewline() then value = "unsanitized" else value = "sanitized")
|
||||
or
|
||||
node = write.getValueArg() and
|
||||
tag = "headerWriteValue" and
|
||||
(if write.valueAllowsNewline() then value = "unsanitized" else value = "sanitized")
|
||||
)
|
||||
or
|
||||
exists(Http::Server::ResponseHeaderBulkWrite write |
|
||||
location = write.getBulkArg().getLocation() and
|
||||
element = write.getBulkArg().toString() and
|
||||
(
|
||||
tag = "headerWriteBulk" and
|
||||
value = ""
|
||||
or
|
||||
tag = "headerWriteName" and
|
||||
(if write.nameAllowsNewline() then value = "unsanitized" else value = "sanitized")
|
||||
or
|
||||
tag = "headerWriteValue" and
|
||||
(if write.valueAllowsNewline() then value = "unsanitized" else value = "sanitized")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module HttpServerHttpRedirectResponseTest implements TestSig {
|
||||
string getARelevantTag() { result in ["HttpRedirectResponse", "redirectLocation"] }
|
||||
|
||||
@@ -559,7 +596,8 @@ import MakeTest<MergeTests5<MergeTests5<SystemCommandExecutionTest, DecodingTest
|
||||
MergeTests5<SqlConstructionTest, SqlExecutionTest, XPathConstructionTest, XPathExecutionTest,
|
||||
EscapingTest>,
|
||||
MergeTests5<HttpServerRouteSetupTest, HttpServerRequestHandlerTest, HttpServerHttpResponseTest,
|
||||
HttpServerHttpRedirectResponseTest, HttpServerCookieWriteTest>,
|
||||
HttpServerHttpRedirectResponseTest,
|
||||
MergeTests<HttpServerCookieWriteTest, HttpResponseHeaderWriteTest>>,
|
||||
MergeTests5<FileSystemAccessTest, FileSystemWriteAccessTest, PathNormalizationTest,
|
||||
SafeAccessCheckTest, PublicKeyGenerationTest>,
|
||||
MergeTests5<CryptographicOperationTest, HttpClientRequestTest, CsrfProtectionSettingTest,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import json
|
||||
|
||||
from flask import Flask, make_response, jsonify, Response, request, redirect
|
||||
from werkzeug.datastructures import Headers
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -117,7 +118,7 @@ def response_modification1(): # $requestHandler
|
||||
@app.route("/content-type/response-modification2") # $routeSetup="/content-type/response-modification2"
|
||||
def response_modification2(): # $requestHandler
|
||||
resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp.headers["content-type"] = "text/plain" # $ MISSING: HttpResponse mimetype=text/plain
|
||||
resp.headers["content-type"] = "text/plain" # $ headerWriteName=unsanitized headerWriteValue=sanitized MISSING: HttpResponse mimetype=text/plain
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -147,7 +148,7 @@ def Response3(): # $requestHandler
|
||||
@app.route("/content-type/Response4") # $routeSetup="/content-type/Response4"
|
||||
def Response4(): # $requestHandler
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/plain"}) # $HttpResponse responseBody="<h1>hello</h1>" SPURIOUS: mimetype=text/html MISSING: mimetype=text/plain
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/plain"}) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized HttpResponse responseBody="<h1>hello</h1>" SPURIOUS: mimetype=text/html MISSING: mimetype=text/plain
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -155,7 +156,7 @@ def Response4(): # $requestHandler
|
||||
def Response5(): # $requestHandler
|
||||
# content_type argument takes priority (and result is text/plain)
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, content_type="text/plain; charset=utf-8") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, content_type="text/plain; charset=utf-8") # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -163,7 +164,7 @@ def Response5(): # $requestHandler
|
||||
def Response6(): # $requestHandler
|
||||
# mimetype argument takes priority over header (and result is text/plain)
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, mimetype="text/plain") # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -207,12 +208,44 @@ def setting_cookie(): # $requestHandler
|
||||
resp = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers.add("Set-Cookie", "key2=value2") # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.headers.add("Set-Cookie", "key2=value2") # $ headerWriteName=unsanitized headerWriteValue=sanitized MISSING: CookieWrite CookieRawHeader="key2=value2"
|
||||
resp.delete_cookie("key3") # $ CookieWrite CookieName="key3"
|
||||
resp.delete_cookie(key="key3") # $ CookieWrite CookieName="key3"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
################################################################################
|
||||
# Headers
|
||||
################################################################################
|
||||
|
||||
@app.route("/headers") # $routeSetup="/headers"
|
||||
def headers(): # $requestHandler
|
||||
resp1 = Response() # $ HttpResponse mimetype=text/html
|
||||
resp1.headers['X-MyHeader'] = 'a' # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
resp2 = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp2.headers['X-MyHeader'] = 'a' # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
resp2.headers.extend({'X-MyHeader2': 'b'}) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
resp3 = make_response("hello", 200, {'X-MyHeader3': 'c'}) # $ HttpResponse mimetype=text/html responseBody="hello" headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
resp4 = make_response("hello", {'X-MyHeader4': 'd'}) # $ HttpResponse mimetype=text/html responseBody="hello" headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
return resp4 # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp4
|
||||
|
||||
@app.route("/werkzeug-headers") # $routeSetup="/werkzeug-headers"
|
||||
def werkzeug_headers(): # $requestHandler
|
||||
response = Response() # $ HttpResponse mimetype=text/html
|
||||
headers = Headers()
|
||||
headers.add("X-MyHeader1", "a") # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
headers.add_header("X-MyHeader2", "b") # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
headers.set("X-MyHeader3", "c") # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
headers.setdefault("X-MyHeader4", "d") # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
headers.__setitem__("X-MyHeader5", "e") # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
headers["X-MyHeader6"] = "f" # $ headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
h1 = {"X-MyHeader7": "g"}
|
||||
headers.extend(h1) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
h2 = [("X-MyHeader8", "h")]
|
||||
headers.extend(h2) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=sanitized
|
||||
response.headers = headers
|
||||
return response # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=response
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# see https://docs.python.org/3/library/wsgiref.html#wsgiref.simple_server.WSGIServer
|
||||
import sys
|
||||
import wsgiref.simple_server
|
||||
import wsgiref.headers
|
||||
|
||||
def ignore(*arg, **kwargs): pass
|
||||
ensure_tainted = ensure_not_tainted = ignore
|
||||
@@ -17,7 +18,7 @@ def func(environ, start_response): # $ requestHandler
|
||||
environ, # $ tainted
|
||||
environ["PATH_INFO"], # $ tainted
|
||||
)
|
||||
write = start_response("200 OK", [("Content-Type", "text/plain")])
|
||||
write = start_response("200 OK", [("Content-Type", "text/plain")]) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
write(b"hello") # $ HttpResponse responseBody=b"hello"
|
||||
write(data=b" ") # $ HttpResponse responseBody=b" "
|
||||
|
||||
@@ -32,9 +33,17 @@ class MyServer(wsgiref.simple_server.WSGIServer):
|
||||
self.set_app(self.my_method)
|
||||
|
||||
def my_method(self, _env, start_response): # $ requestHandler
|
||||
start_response("200 OK", [])
|
||||
start_response("200 OK", []) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
return [b"my_method"] # $ HttpResponse responseBody=List
|
||||
|
||||
def func2(environ, start_response): # $ requestHandler
|
||||
headers = wsgiref.headers.Headers([("Content-Type", "text/plain")]) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
headers.add_header("X-MyHeader", "a") # $ headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
headers.setdefault("X-MyHeader2", "b") # $ headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
headers.__setitem__("X-MyHeader3", "c") # $ headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
headers["X-MyHeader4"] = "d" # $ headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
start_response(status, headers) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
return [b"Hello"] # $ HttpResponse responseBody=List
|
||||
|
||||
case = sys.argv[1]
|
||||
if case == "1":
|
||||
@@ -45,9 +54,11 @@ elif case == "2":
|
||||
elif case == "3":
|
||||
server = MyServer()
|
||||
def func3(_env, start_response): # $ requestHandler
|
||||
start_response("200 OK", [])
|
||||
start_response("200 OK", []) # $ headerWriteBulk headerWriteName=unsanitized headerWriteValue=unsanitized
|
||||
return [b"foo"] # $ HttpResponse responseBody=List
|
||||
server.set_app(func3)
|
||||
elif case == "4":
|
||||
server = wsgiref.simple_server.make_server(ADDRESS[0], ADDRESS[1], func2)
|
||||
else:
|
||||
sys.exit("wrong case")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user