mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #7228 from RasmusWL/fastapi-improvements
Python: FastAPI improvements
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Extended the modeling of FastAPI such that custom subclasses of `fastapi.APIRouter` are recognized.
|
||||
@@ -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.
|
||||
@@ -33,7 +33,7 @@ private module FastApi {
|
||||
module APIRouter {
|
||||
/** Gets a reference to an instance of `fastapi.APIRouter`. */
|
||||
API::Node instance() {
|
||||
result = API::moduleImport("fastapi").getMember("APIRouter").getReturn()
|
||||
result = API::moduleImport("fastapi").getMember("APIRouter").getASubclass*().getReturn()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# like blueprints in Flask
|
||||
# see https://fastapi.tiangolo.com/tutorial/bigger-applications/
|
||||
# see basic.py for instructions for how to run this code.
|
||||
|
||||
from fastapi import APIRouter, FastAPI
|
||||
|
||||
@@ -30,4 +31,23 @@ app = FastAPI()
|
||||
app.include_router(outer_router, prefix="/outer")
|
||||
app.include_router(items_router)
|
||||
|
||||
# see basic.py for instructions for how to run this code.
|
||||
# Using a custom router
|
||||
|
||||
class MyCustomRouter(APIRouter):
|
||||
"""
|
||||
Which automatically removes trailing slashes
|
||||
"""
|
||||
def api_route(self, path: str, **kwargs):
|
||||
path = path.rstrip("/")
|
||||
return super().api_route(path, **kwargs)
|
||||
|
||||
|
||||
custom_router = MyCustomRouter()
|
||||
|
||||
|
||||
@custom_router.get("/bar/") # $ routeSetup="/bar/"
|
||||
async def items(): # $ requestHandler
|
||||
return {"msg": "custom_router /bar/"} # $ HttpResponse
|
||||
|
||||
|
||||
app.include_router(custom_router)
|
||||
|
||||
Reference in New Issue
Block a user