Python: Model FastAPI FileResponse as FileSystemAccess

This was an oversight from our initial FastAPI modeling work.
This commit is contained in:
Rasmus Wriedt Larsen
2021-11-24 11:31:59 +01:00
parent 8c9e817c0d
commit d493cfdf3a
3 changed files with 19 additions and 3 deletions

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Extended the modeling of FastAPI such that `fastapi.responses.FileResponse` are considered `FileSystemAccess`, making them sinks for the _Uncontrolled data used in path expression_ (`py/path-injection`) query.

View File

@@ -226,6 +226,17 @@ private module FastApi {
}
}
/**
* A direct instantiation of a FileResponse.
*/
private class FileResponseInstantiation extends ResponseInstantiation, FileSystemAccess::Range {
FileResponseInstantiation() { baseApiNode = getModeledResponseClass("FileResponse") }
override DataFlow::Node getAPathArgument() {
result in [this.getArg(0), this.getArgByName("path")]
}
}
/**
* An implicit response from a return of FastAPI request handler.
*/
@@ -256,7 +267,8 @@ private module FastApi {
* An implicit response from a return of FastAPI request handler, that has
* `response_class` set to a `FileResponse`.
*/
private class FastApiRequestHandlerFileResponseReturn extends FastApiRequestHandlerReturn {
private class FastApiRequestHandlerFileResponseReturn extends FastApiRequestHandlerReturn,
FileSystemAccess::Range {
FastApiRequestHandlerFileResponseReturn() {
exists(API::Node responseClass |
responseClass.getAUse() = routeSetup.getResponseClassArg() and
@@ -265,6 +277,8 @@ private module FastApi {
}
override DataFlow::Node getBody() { none() }
override DataFlow::Node getAPathArgument() { result = this }
}
/**

View File

@@ -136,10 +136,10 @@ async def file_response(): # $ requestHandler
# We don't really have any good QL modeling of passing a file-path, whose content
# will be returned as part of the response... so will leave this as a TODO for now.
resp = fastapi.responses.FileResponse(__file__) # $ HttpResponse
resp = fastapi.responses.FileResponse(__file__) # $ HttpResponse getAPathArgument=__file__
return resp # $ SPURIOUS: HttpResponse mimetype=application/json responseBody=resp
@app.get("/file_response2", response_class=fastapi.responses.FileResponse) # $ routeSetup="/file_response2"
async def file_response2(): # $ requestHandler
return __file__ # $ HttpResponse
return __file__ # $ HttpResponse getAPathArgument=__file__