mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
update the predicates on Express::RouteHandler to use dataflow nodes
This commit is contained in:
committed by
erik-krogh
parent
4cfbf15d18
commit
8266b083d7
@@ -30,29 +30,31 @@ module Connect {
|
||||
*
|
||||
* `kind` is one of: "error", "request", "response", "next".
|
||||
*/
|
||||
abstract Parameter getRouteHandlerParameter(string kind);
|
||||
abstract DataFlow::ParameterNode getRouteHandlerParameter(string kind);
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the request object.
|
||||
*/
|
||||
override Parameter getRequestParameter() { result = getRouteHandlerParameter("request") }
|
||||
override DataFlow::ParameterNode getRequestParameter() {
|
||||
result = getRouteHandlerParameter("request")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the response object.
|
||||
*/
|
||||
override Parameter getResponseParameter() { result = getRouteHandlerParameter("response") }
|
||||
override DataFlow::ParameterNode getResponseParameter() {
|
||||
result = getRouteHandlerParameter("response")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Connect route handler installed by a route setup.
|
||||
*/
|
||||
class StandardRouteHandler extends RouteHandler {
|
||||
override Function astNode;
|
||||
|
||||
class StandardRouteHandler extends RouteHandler, DataFlow::FunctionNode {
|
||||
StandardRouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
result = getRouteHandlerParameter(astNode, kind)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
result = getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ module ConnectExpressShared {
|
||||
/**
|
||||
* Holds if `function` appears to match the given signature based on parameter naming.
|
||||
*/
|
||||
private predicate matchesSignature(Function function, RouteHandlerSignature sig) {
|
||||
private predicate matchesSignature(DataFlow::FunctionNode function, RouteHandlerSignature sig) {
|
||||
function.getNumParameter() = sig.getArity() and
|
||||
function.getParameter(sig.getParameterIndex("request")).getName() = ["req", "request"] and
|
||||
function.getParameter(sig.getParameterIndex("response")).getName() = ["res", "response"] and
|
||||
@@ -71,8 +71,8 @@ module ConnectExpressShared {
|
||||
* so the caller should restrict the function accordingly.
|
||||
*/
|
||||
pragma[inline]
|
||||
private Parameter getRouteHandlerParameter(
|
||||
Function routeHandler, RouteHandlerSignature sig, string kind
|
||||
private DataFlow::ParameterNode getRouteHandlerParameter(
|
||||
DataFlow::FunctionNode routeHandler, RouteHandlerSignature sig, string kind
|
||||
) {
|
||||
result = routeHandler.getParameter(sig.getParameterIndex(kind))
|
||||
}
|
||||
@@ -83,7 +83,9 @@ module ConnectExpressShared {
|
||||
* `kind` is one of: "error", "request", "response", "next".
|
||||
*/
|
||||
pragma[inline]
|
||||
Parameter getRouteParameterHandlerParameter(Function routeHandler, string kind) {
|
||||
DataFlow::ParameterNode getRouteParameterHandlerParameter(
|
||||
DataFlow::FunctionNode routeHandler, string kind
|
||||
) {
|
||||
result =
|
||||
getRouteHandlerParameter(routeHandler, RouteHandlerSignature::requestResponseNextParameter(),
|
||||
kind)
|
||||
@@ -95,7 +97,7 @@ module ConnectExpressShared {
|
||||
* `kind` is one of: "error", "request", "response", "next".
|
||||
*/
|
||||
pragma[inline]
|
||||
Parameter getRouteHandlerParameter(Function routeHandler, string kind) {
|
||||
DataFlow::ParameterNode getRouteHandlerParameter(DataFlow::FunctionNode routeHandler, string kind) {
|
||||
if routeHandler.getNumParameter() = 4
|
||||
then
|
||||
// For arity 4 there is ambiguity between (err, req, res, next) and (req, res, next, param)
|
||||
@@ -115,7 +117,7 @@ module ConnectExpressShared {
|
||||
*/
|
||||
class RouteHandlerCandidate extends HTTP::RouteHandlerCandidate {
|
||||
RouteHandlerCandidate() {
|
||||
matchesSignature(astNode, _) and
|
||||
matchesSignature(this, _) and
|
||||
not (
|
||||
// heuristic: not a class method (the server invokes this with a function call)
|
||||
astNode = any(MethodDefinition def).getBody()
|
||||
|
||||
@@ -286,14 +286,12 @@ module Express {
|
||||
* The callback given to passport in PassportRouteSetup.
|
||||
*/
|
||||
private class PassportRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
|
||||
DataFlow::ValueNode {
|
||||
override Function astNode;
|
||||
|
||||
DataFlow::FunctionNode {
|
||||
PassportRouteHandler() { this = any(PassportRouteSetup setup).getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and
|
||||
result = astNode.getParameter(0)
|
||||
result = this.getParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,40 +476,41 @@ module Express {
|
||||
*
|
||||
* `kind` is one of: "error", "request", "response", "next", or "parameter".
|
||||
*/
|
||||
abstract Parameter getRouteHandlerParameter(string kind); // TODO: DataFlow::ParameterNode
|
||||
abstract DataFlow::ParameterNode getRouteHandlerParameter(string kind);
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the request object.
|
||||
*/
|
||||
Parameter getRequestParameter() { result = this.getRouteHandlerParameter("request") } // TODO: DataFlow::ParameterNode
|
||||
DataFlow::ParameterNode getRequestParameter() {
|
||||
result = this.getRouteHandlerParameter("request")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the response object.
|
||||
*/
|
||||
Parameter getResponseParameter() { result = this.getRouteHandlerParameter("response") } // TODO: DataFlow::ParameterNode
|
||||
DataFlow::ParameterNode getResponseParameter() {
|
||||
result = this.getRouteHandlerParameter("response")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a request body access of this handler.
|
||||
*/
|
||||
Expr getARequestBodyAccess() {
|
||||
result.(PropAccess).accesses(this.getARequestNode().asExpr(), "body")
|
||||
} // TODO: DataFlow::Node
|
||||
DataFlow::PropRead getARequestBodyAccess() { result.accesses(this.getARequestNode(), "body") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An Express route handler installed by a route setup.
|
||||
*/
|
||||
class StandardRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
|
||||
DataFlow::ValueNode {
|
||||
override Function astNode;
|
||||
DataFlow::FunctionNode {
|
||||
RouteSetup routeSetup;
|
||||
|
||||
StandardRouteHandler() { this = routeSetup.getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
if routeSetup.isParameterHandler()
|
||||
then result = getRouteParameterHandlerParameter(astNode, kind)
|
||||
else result = getRouteHandlerParameter(astNode, kind)
|
||||
then result = getRouteParameterHandlerParameter(this, kind)
|
||||
else result = getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,7 +539,7 @@ module Express {
|
||||
RouteHandler rh;
|
||||
|
||||
ExplicitResponseSource() {
|
||||
this = DataFlow::parameterNode(rh.getResponseParameter())
|
||||
this = rh.getResponseParameter()
|
||||
or
|
||||
isChainableResponseMethodCall(rh, this.asExpr())
|
||||
}
|
||||
@@ -570,7 +569,7 @@ module Express {
|
||||
private class ExplicitRequestSource extends RequestSource {
|
||||
RouteHandler rh;
|
||||
|
||||
ExplicitRequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
|
||||
ExplicitRequestSource() { this = rh.getRequestParameter() }
|
||||
|
||||
/**
|
||||
* Gets the route handler that handles this request.
|
||||
@@ -637,7 +636,7 @@ module Express {
|
||||
|
||||
ParamHandlerInputAccess() {
|
||||
exists(RouteSetup setup | rh = setup.getARouteHandler() |
|
||||
this = DataFlow::parameterNode(rh.getRouteHandlerParameter("parameter"))
|
||||
this = rh.getRouteHandlerParameter("parameter")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -778,7 +777,8 @@ module Express {
|
||||
* An access to the HTTP request body.
|
||||
*/
|
||||
class RequestBodyAccess extends Expr {
|
||||
RequestBodyAccess() { any(RouteHandler h).getARequestBodyAccess() = this }
|
||||
// TODO: DataFlow::Node
|
||||
RequestBodyAccess() { any(RouteHandler h).getARequestBodyAccess().asExpr() = this }
|
||||
}
|
||||
|
||||
abstract private class HeaderDefinition extends HTTP::Servers::StandardHeaderDefinition {
|
||||
@@ -1049,10 +1049,10 @@ module Express {
|
||||
|
||||
TrackedRouteHandlerCandidateWithSetup() { this = routeSetup.getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
if routeSetup.isParameterHandler()
|
||||
then result = getRouteParameterHandlerParameter(astNode, kind)
|
||||
else result = getRouteHandlerParameter(astNode, kind)
|
||||
then result = getRouteParameterHandlerParameter(this, kind)
|
||||
else result = getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,15 +216,13 @@ module Firebase {
|
||||
* A function used as a route handler.
|
||||
*/
|
||||
private class RouteHandler extends Express::RouteHandler, HTTP::Servers::StandardRouteHandler,
|
||||
DataFlow::ValueNode {
|
||||
override Function astNode;
|
||||
|
||||
DataFlow::FunctionNode {
|
||||
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and result = astNode.getParameter(0)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and result = this.getParameter(0)
|
||||
or
|
||||
kind = "response" and result = astNode.getParameter(1)
|
||||
kind = "response" and result = this.getParameter(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,16 +83,12 @@ private module HttpProxy {
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getRequestParameter() {
|
||||
exists(int req | routeHandlingEventHandler(event, req, _) |
|
||||
result = getFunction().getParameter(req)
|
||||
)
|
||||
override DataFlow::ParameterNode getRequestParameter() {
|
||||
exists(int req | routeHandlingEventHandler(event, req, _) | result = getParameter(req))
|
||||
}
|
||||
|
||||
override Parameter getResponseParameter() {
|
||||
exists(int res | routeHandlingEventHandler(event, _, res) |
|
||||
result = getFunction().getParameter(res)
|
||||
)
|
||||
override DataFlow::ParameterNode getResponseParameter() {
|
||||
exists(int res | routeHandlingEventHandler(event, _, res) | result = getParameter(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ private module LiveServer {
|
||||
class RouteHandler extends Connect::RouteHandler, DataFlow::FunctionNode {
|
||||
RouteHandler() { this = any(RouteSetup setup).getARouteHandler() }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(astNode, kind)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,10 +230,10 @@ module NextJS {
|
||||
)
|
||||
}
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and result = this.getFunction().getParameter(0)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
kind = "request" and result = this.getParameter(0)
|
||||
or
|
||||
kind = "response" and result = this.getFunction().getParameter(1)
|
||||
kind = "response" and result = this.getParameter(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,12 +114,12 @@ module NodeJSLib {
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the request object.
|
||||
*/
|
||||
Parameter getRequestParameter() { result = this.getFunction().getParameter(0) }
|
||||
DataFlow::ParameterNode getRequestParameter() { result = this.getParameter(0) }
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the response object.
|
||||
*/
|
||||
Parameter getResponseParameter() { result = this.getFunction().getParameter(1) }
|
||||
DataFlow::ParameterNode getResponseParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,7 +141,7 @@ module NodeJSLib {
|
||||
private class StandardResponseSource extends ResponseSource {
|
||||
RouteHandler rh;
|
||||
|
||||
StandardResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) }
|
||||
StandardResponseSource() { this = rh.getResponseParameter() }
|
||||
|
||||
/**
|
||||
* Gets the route handler that provides this response.
|
||||
@@ -161,7 +161,7 @@ module NodeJSLib {
|
||||
private class StandardRequestSource extends RequestSource {
|
||||
RouteHandler rh;
|
||||
|
||||
StandardRequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
|
||||
StandardRequestSource() { this = rh.getRequestParameter() }
|
||||
|
||||
/**
|
||||
* Gets the route handler that handles this request.
|
||||
|
||||
@@ -29,8 +29,8 @@ private class PromotedExpressCandidate extends Express::RouteHandler,
|
||||
HTTP::Servers::StandardRouteHandler {
|
||||
PromotedExpressCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ private class PromotedConnectCandidate extends Connect::RouteHandler,
|
||||
HTTP::Servers::StandardRouteHandler {
|
||||
PromotedConnectCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate }
|
||||
|
||||
override Parameter getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind)
|
||||
override DataFlow::ParameterNode getRouteHandlerParameter(string kind) {
|
||||
result = ConnectExpressShared::getRouteHandlerParameter(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
|
||||
rateLimiterClassName.matches("RateLimiter%") and
|
||||
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
|
||||
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
|
||||
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
|
||||
request = getRouteHandlerParameter(this, "request") and
|
||||
request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().asSink())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_RouteHandler(Express::RouteHandler rh, Parameter res0, Parameter res1) {
|
||||
query predicate test_RouteHandler(
|
||||
Express::RouteHandler rh, DataFlow::ParameterNode res0, DataFlow::ParameterNode res1
|
||||
) {
|
||||
res0 = rh.getRequestParameter() and res1 = rh.getResponseParameter()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_RouteHandler_getARequestBodyAccess(Express::RouteHandler rh, Expr res) {
|
||||
query predicate test_RouteHandler_getARequestBodyAccess(Express::RouteHandler rh, DataFlow::Node res) {
|
||||
res = rh.getARequestBodyAccess()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_StandardRouteHandler(
|
||||
Express::StandardRouteHandler rh, DataFlow::Node res0, SimpleParameter res1, SimpleParameter res2
|
||||
Express::StandardRouteHandler rh, DataFlow::Node res0, DataFlow::ParameterNode res1,
|
||||
DataFlow::ParameterNode res2
|
||||
) {
|
||||
res0 = rh.getServer() and res1 = rh.getRequestParameter() and res2 = rh.getResponseParameter()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user