mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
convert the remaining Koa models to DataFlow nodes
This commit is contained in:
committed by
erik-krogh
parent
fc54ba823b
commit
136124fbaa
@@ -24,7 +24,7 @@ module Koa {
|
||||
|
||||
HeaderDefinition() {
|
||||
// ctx.set('Cache-Control', 'no-cache');
|
||||
this.calls(rh.getAResponseOrContextExpr().flow(), "set")
|
||||
this.calls(rh.getAResponseOrContextNode(), "set")
|
||||
or
|
||||
// ctx.response.header('Cache-Control', 'no-cache')
|
||||
this.calls(rh.getAResponseNode(), "header")
|
||||
@@ -40,10 +40,17 @@ module Koa {
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the context object.
|
||||
*/
|
||||
Parameter getContextParameter() {
|
||||
result = this.getAFunctionValue().getFunction().getParameter(0)
|
||||
DataFlow::ParameterNode getContextParameter() {
|
||||
result = this.getAFunctionValue().getParameter(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getAContextNode` instead.
|
||||
* Gets an expression that contains the "context" object of
|
||||
* a route handler invocation.
|
||||
*/
|
||||
deprecated Expr getAContextExpr() { result.(ContextExpr).getRouteHandler() = this }
|
||||
|
||||
/**
|
||||
* Gets an expression that contains the "context" object of
|
||||
* a route handler invocation.
|
||||
@@ -52,24 +59,40 @@ module Koa {
|
||||
* `this` or `ctx`, given as the first and only argument to the
|
||||
* route handler.
|
||||
*/
|
||||
Expr getAContextExpr() { result.(ContextExpr).getRouteHandler() = this }
|
||||
DataFlow::Node getAContextNode() { result.(ContextNode).getRouteHandler() = this }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getAResponseOrContextNode` instead.
|
||||
* Gets an expression that contains the context or response
|
||||
* object of a route handler invocation.
|
||||
*/
|
||||
deprecated Expr getAResponseOrContextExpr() {
|
||||
result = this.getAResponseNode().asExpr() or result = this.getAContextExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that contains the context or response
|
||||
* object of a route handler invocation.
|
||||
*/
|
||||
Expr getAResponseOrContextExpr() {
|
||||
// TODO: DataFlow::Node
|
||||
result = this.getAResponseNode().asExpr() or result = this.getAContextExpr()
|
||||
DataFlow::Node getAResponseOrContextNode() {
|
||||
result = this.getAResponseNode() or result = this.getAContextNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getARequestOrContextNode` instead.
|
||||
* Gets an expression that contains the context or request
|
||||
* object of a route handler invocation.
|
||||
*/
|
||||
deprecated Expr getARequestOrContextExpr() {
|
||||
result = this.getARequestNode().asExpr() or result = this.getAContextExpr()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that contains the context or request
|
||||
* object of a route handler invocation.
|
||||
*/
|
||||
Expr getARequestOrContextExpr() {
|
||||
// TODO: DataFlow::Node
|
||||
result = this.getARequestNode().asExpr() or result = this.getAContextExpr()
|
||||
DataFlow::Node getARequestOrContextNode() {
|
||||
result = this.getARequestNode() or result = this.getAContextNode()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +133,7 @@ module Koa {
|
||||
RouteHandler rh;
|
||||
|
||||
ContextSource() {
|
||||
this = DataFlow::parameterNode(rh.getContextParameter())
|
||||
this = rh.getContextParameter()
|
||||
or
|
||||
this.(DataFlow::ThisNode).getBinder() = rh
|
||||
}
|
||||
@@ -206,10 +229,10 @@ module Koa {
|
||||
* A Koa request source, that is, an access to the `request` property
|
||||
* of a context object.
|
||||
*/
|
||||
private class RequestSource extends HTTP::Servers::RequestSource {
|
||||
ContextExpr ctx;
|
||||
private class RequestSource extends HTTP::Servers::RequestSource instanceof DataFlow::PropRead {
|
||||
ContextNode ctx;
|
||||
|
||||
RequestSource() { this.asExpr().(PropAccess).accesses(ctx, "request") }
|
||||
RequestSource() { super.accesses(ctx, "request") }
|
||||
|
||||
/**
|
||||
* Gets the route handler that provides this response.
|
||||
@@ -241,10 +264,10 @@ module Koa {
|
||||
* A Koa response source, that is, an access to the `response` property
|
||||
* of a context object.
|
||||
*/
|
||||
private class ResponseSource extends HTTP::Servers::ResponseSource {
|
||||
ContextExpr ctx;
|
||||
private class ResponseSource extends HTTP::Servers::ResponseSource instanceof DataFlow::PropRead {
|
||||
ContextNode ctx;
|
||||
|
||||
ResponseSource() { this.asExpr().(PropAccess).accesses(ctx, "response") }
|
||||
ResponseSource() { super.accesses(ctx, "response") }
|
||||
|
||||
/**
|
||||
* Gets the route handler that provides this response.
|
||||
@@ -253,12 +276,25 @@ module Koa {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ContextNode` instead.
|
||||
* An expression that may hold a Koa context object.
|
||||
*/
|
||||
class ContextExpr extends Expr {
|
||||
deprecated class ContextExpr extends Expr {
|
||||
ContextNode node;
|
||||
|
||||
ContextExpr() { node.asExpr() = this }
|
||||
|
||||
/** Gets the route handler that provides this response. */
|
||||
deprecated RouteHandler getRouteHandler() { result = node.getRouteHandler() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that may hold a Koa context object.
|
||||
*/
|
||||
class ContextNode extends DataFlow::Node {
|
||||
ContextSource src;
|
||||
|
||||
ContextExpr() { src.ref().flowsTo(DataFlow::valueNode(this)) }
|
||||
ContextNode() { src.ref().flowsTo(this) }
|
||||
|
||||
/**
|
||||
* Gets the route handler that provides this response.
|
||||
@@ -310,11 +346,11 @@ module Koa {
|
||||
kind = "parameter" and
|
||||
this = rh.getARequestParameterAccess()
|
||||
or
|
||||
exists(Expr e | rh.getARequestOrContextExpr() = e |
|
||||
exists(DataFlow::Node e | rh.getARequestOrContextNode() = e |
|
||||
// `ctx.request.url`, `ctx.request.originalUrl`, or `ctx.request.href`
|
||||
exists(string propName |
|
||||
kind = "url" and
|
||||
this.asExpr().(PropAccess).accesses(e, propName)
|
||||
this.(DataFlow::PropRead).accesses(e, propName)
|
||||
|
|
||||
propName = "url"
|
||||
or
|
||||
@@ -325,19 +361,19 @@ module Koa {
|
||||
or
|
||||
// params, when handler is registered by `koa-router` or similar.
|
||||
kind = "parameter" and
|
||||
this.asExpr().(PropAccess).accesses(e, "params")
|
||||
this.(DataFlow::PropRead).accesses(e, "params")
|
||||
or
|
||||
// `ctx.request.body`
|
||||
e.flow() instanceof RequestNode and
|
||||
e instanceof RequestNode and
|
||||
kind = "body" and
|
||||
this.asExpr().(PropAccess).accesses(e, "body")
|
||||
this.(DataFlow::PropRead).accesses(e, "body")
|
||||
or
|
||||
// `ctx.cookies.get(<name>)`
|
||||
exists(PropAccess cookies |
|
||||
e instanceof ContextExpr and
|
||||
exists(DataFlow::PropRead cookies |
|
||||
e instanceof ContextNode and
|
||||
kind = "cookie" and
|
||||
cookies.accesses(e, "cookies") and
|
||||
this = cookies.flow().(DataFlow::SourceNode).getAMethodCall("get")
|
||||
this = cookies.getAMethodCall("get")
|
||||
)
|
||||
or
|
||||
exists(RequestHeaderAccess access | access = this |
|
||||
@@ -356,9 +392,9 @@ module Koa {
|
||||
|
||||
private DataFlow::Node getAQueryParameterAccess(RouteHandler rh) {
|
||||
// `ctx.query.name` or `ctx.request.query.name`
|
||||
exists(PropAccess q |
|
||||
q.accesses(rh.getARequestOrContextExpr(), "query") and
|
||||
result = q.flow().(DataFlow::SourceNode).getAPropertyRead()
|
||||
exists(DataFlow::PropRead q |
|
||||
q.accesses(rh.getARequestOrContextNode(), "query") and
|
||||
result = q.getAPropertyRead()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -369,18 +405,18 @@ module Koa {
|
||||
RouteHandler rh;
|
||||
|
||||
RequestHeaderAccess() {
|
||||
exists(Expr e | e = rh.getARequestOrContextExpr() |
|
||||
exists(string propName, PropAccess headers |
|
||||
exists(DataFlow::Node e | e = rh.getARequestOrContextNode() |
|
||||
exists(string propName, DataFlow::PropRead headers |
|
||||
// `ctx.request.header.<name>`, `ctx.request.headers.<name>`
|
||||
headers.accesses(e, propName) and
|
||||
this = headers.flow().(DataFlow::SourceNode).getAPropertyRead()
|
||||
this = headers.getAPropertyRead()
|
||||
|
|
||||
propName = "header" or
|
||||
propName = "headers"
|
||||
)
|
||||
or
|
||||
// `ctx.request.get(<name>)`
|
||||
this.asExpr().(MethodCallExpr).calls(e, "get")
|
||||
this.(DataFlow::MethodCallNode).calls(e, "get")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -427,9 +463,7 @@ module Koa {
|
||||
RouteHandler rh;
|
||||
|
||||
ResponseSendArgument() {
|
||||
exists(DataFlow::PropWrite pwn |
|
||||
pwn.writes(DataFlow::valueNode(rh.getAResponseOrContextExpr()), "body", this)
|
||||
)
|
||||
exists(DataFlow::PropWrite pwn | pwn.writes(rh.getAResponseOrContextNode(), "body", this))
|
||||
}
|
||||
|
||||
override RouteHandler getRouteHandler() { result = rh }
|
||||
@@ -438,12 +472,10 @@ module Koa {
|
||||
/**
|
||||
* An invocation of the `redirect` method of an HTTP response object.
|
||||
*/
|
||||
private class RedirectInvocation extends HTTP::RedirectInvocation, DataFlow::MethodCallNode {
|
||||
private class RedirectInvocation extends HTTP::RedirectInvocation instanceof DataFlow::MethodCallNode {
|
||||
RouteHandler rh;
|
||||
|
||||
RedirectInvocation() {
|
||||
this.asExpr().(MethodCallExpr).calls(rh.getAResponseOrContextExpr(), "redirect")
|
||||
} // TODO: Improve this.
|
||||
RedirectInvocation() { super.calls(rh.getAResponseOrContextNode(), "redirect") }
|
||||
|
||||
override DataFlow::Node getUrlArgument() { result = this.getArgument(0) }
|
||||
|
||||
|
||||
@@ -49,8 +49,7 @@ module NodeJSLib {
|
||||
/**
|
||||
* Holds if `call` is an invocation of `http.createServer` or `https.createServer`.
|
||||
*/
|
||||
predicate isCreateServer(CallExpr call) {
|
||||
// TODO: DataFlow::Node
|
||||
predicate isCreateServer(DataFlow::CallNode call) {
|
||||
exists(string pkg, string fn |
|
||||
pkg = "http" and fn = "createServer"
|
||||
or
|
||||
@@ -61,7 +60,7 @@ module NodeJSLib {
|
||||
or
|
||||
pkg = "http2" and fn = "createSecureServer"
|
||||
|
|
||||
call = DataFlow::moduleMember(pkg, fn).getAnInvocation().asExpr()
|
||||
call = DataFlow::moduleMember(pkg, fn).getAnInvocation()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -423,7 +422,7 @@ module NodeJSLib {
|
||||
* An expression that creates a new Node.js server.
|
||||
*/
|
||||
class ServerDefinition extends HTTP::Servers::StandardServerDefinition {
|
||||
ServerDefinition() { isCreateServer(this.asExpr()) }
|
||||
ServerDefinition() { isCreateServer(this) }
|
||||
}
|
||||
|
||||
/** An expression that is passed as `http.request({ auth: <expr> }, ...)`. */
|
||||
|
||||
@@ -61,9 +61,7 @@ module CleartextStorage {
|
||||
/**
|
||||
* An expression set as a value of localStorage or sessionStorage.
|
||||
*/
|
||||
class WebStorageSink extends Sink {
|
||||
WebStorageSink() { this.asExpr() instanceof WebStorageWrite }
|
||||
}
|
||||
class WebStorageSink extends Sink instanceof WebStorageWrite { }
|
||||
|
||||
/**
|
||||
* An expression stored by AngularJS.
|
||||
|
||||
@@ -104,7 +104,9 @@ module ClientSideUrlRedirect {
|
||||
xss = true
|
||||
or
|
||||
// An assignment to `location`
|
||||
exists(Assignment assgn | isLocation(assgn.getTarget()) and astNode = assgn.getRhs()) and
|
||||
exists(Assignment assgn |
|
||||
isLocationNode(assgn.getTarget().flow()) and astNode = assgn.getRhs()
|
||||
) and
|
||||
xss = true
|
||||
or
|
||||
// An assignment to `location.href`, `location.protocol` or `location.hostname`
|
||||
|
||||
@@ -143,18 +143,17 @@ class DomPropWriteNode extends Assignment {
|
||||
/**
|
||||
* A value written to web storage, like `localStorage` or `sessionStorage`.
|
||||
*/
|
||||
class WebStorageWrite extends Expr {
|
||||
// TODO: DataFlow::Node
|
||||
class WebStorageWrite extends DataFlow::Node {
|
||||
WebStorageWrite() {
|
||||
exists(DataFlow::SourceNode webStorage |
|
||||
webStorage = DataFlow::globalVarRef("localStorage") or
|
||||
webStorage = DataFlow::globalVarRef("sessionStorage")
|
||||
|
|
||||
// an assignment to `window.localStorage[someProp]`
|
||||
this = webStorage.getAPropertyWrite().getRhs().asExpr()
|
||||
this = webStorage.getAPropertyWrite().getRhs()
|
||||
or
|
||||
// an invocation of `window.localStorage.setItem`
|
||||
this = webStorage.getAMethodCall("setItem").getArgument(1).asExpr()
|
||||
this = webStorage.getAMethodCall("setItem").getArgument(1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_isCreateServer(CallExpr e) { NodeJSLib::isCreateServer(e) }
|
||||
query predicate test_isCreateServer(DataFlow::CallNode e) { NodeJSLib::isCreateServer(e) }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import javascript
|
||||
|
||||
query predicate test_ContextExpr(Koa::ContextExpr e, Koa::RouteHandler res) {
|
||||
query predicate test_ContextExpr(Koa::ContextNode e, Koa::RouteHandler res) {
|
||||
res = e.getRouteHandler()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import semmle.javascript.frameworks.Express
|
||||
|
||||
query predicate test_RouteHandler_getAContextExpr(Koa::RouteHandler rh, Expr res) {
|
||||
res = rh.getAContextExpr()
|
||||
query predicate test_RouteHandler_getAContextExpr(Koa::RouteHandler rh, DataFlow::Node res) {
|
||||
res = rh.getAContextNode()
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ test_ResponseExpr
|
||||
| src/koa.js:18:3:18:14 | ctx.response | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:44:2:44:13 | ctx.response | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
test_RouteHandler_getAContextExpr
|
||||
| src/koa.js:7:1:7:22 | functio ... r1() {} | src/koa.js:7:1:7:0 | this |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:10:10:10:9 | this |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:10:28:10:30 | ctx |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:10:28:10:30 | ctx |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:11:3:11:6 | this |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:12:3:12:6 | this |
|
||||
@@ -64,6 +67,7 @@ test_RouteHandler_getAContextExpr
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:26:3:26:5 | ctx |
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:27:3:27:5 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:30:16:30:18 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:30:16:30:18 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:31:2:31:4 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:32:2:32:4 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:33:2:33:4 | ctx |
|
||||
@@ -78,9 +82,11 @@ test_RouteHandler_getAContextExpr
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:43:2:43:4 | ctx |
|
||||
| src/koa.js:30:10:45:1 | async c ... url);\\n} | src/koa.js:44:2:44:4 | ctx |
|
||||
| src/koa.js:47:10:56:1 | async c ... .foo;\\n} | src/koa.js:47:16:47:18 | ctx |
|
||||
| src/koa.js:47:10:56:1 | async c ... .foo;\\n} | src/koa.js:47:16:47:18 | ctx |
|
||||
| src/koa.js:47:10:56:1 | async c ... .foo;\\n} | src/koa.js:48:16:48:18 | ctx |
|
||||
| src/koa.js:47:10:56:1 | async c ... .foo;\\n} | src/koa.js:51:14:51:16 | ctx |
|
||||
| src/koa.js:47:10:56:1 | async c ... .foo;\\n} | src/koa.js:54:16:54:18 | ctx |
|
||||
| src/koa.js:59:10:61:1 | functio ... .url;\\n} | src/koa.js:59:10:59:9 | this |
|
||||
| src/koa.js:59:10:61:1 | functio ... .url;\\n} | src/koa.js:60:2:60:5 | this |
|
||||
test_HeaderDefinition
|
||||
| src/koa.js:11:3:11:25 | this.se ... 1', '') | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
@@ -157,6 +163,9 @@ test_RouteHandler_getARequestExpr
|
||||
| src/koa.js:10:10:28:1 | functio ... az');\\n} | src/koa.js:26:3:26:13 | ctx.request |
|
||||
| src/koa.js:59:10:61:1 | functio ... .url;\\n} | src/koa.js:60:2:60:13 | this.request |
|
||||
test_ContextExpr
|
||||
| src/koa.js:7:1:7:0 | this | src/koa.js:7:1:7:22 | functio ... r1() {} |
|
||||
| src/koa.js:10:10:10:9 | this | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:10:28:10:30 | ctx | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:10:28:10:30 | ctx | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:11:3:11:6 | this | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:12:3:12:6 | this | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
@@ -174,6 +183,7 @@ test_ContextExpr
|
||||
| src/koa.js:26:3:26:5 | ctx | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:27:3:27:5 | ctx | src/koa.js:10:10:28:1 | functio ... az');\\n} |
|
||||
| src/koa.js:30:16:30:18 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:30:16:30:18 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:31:2:31:4 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:32:2:32:4 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:33:2:33:4 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
@@ -188,9 +198,11 @@ test_ContextExpr
|
||||
| src/koa.js:43:2:43:4 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:44:2:44:4 | ctx | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
| src/koa.js:47:16:47:18 | ctx | src/koa.js:47:10:56:1 | async c ... .foo;\\n} |
|
||||
| src/koa.js:47:16:47:18 | ctx | src/koa.js:47:10:56:1 | async c ... .foo;\\n} |
|
||||
| src/koa.js:48:16:48:18 | ctx | src/koa.js:47:10:56:1 | async c ... .foo;\\n} |
|
||||
| src/koa.js:51:14:51:16 | ctx | src/koa.js:47:10:56:1 | async c ... .foo;\\n} |
|
||||
| src/koa.js:54:16:54:18 | ctx | src/koa.js:47:10:56:1 | async c ... .foo;\\n} |
|
||||
| src/koa.js:59:10:59:9 | this | src/koa.js:59:10:61:1 | functio ... .url;\\n} |
|
||||
| src/koa.js:60:2:60:5 | this | src/koa.js:59:10:61:1 | functio ... .url;\\n} |
|
||||
test_RedirectInvocation
|
||||
| src/koa.js:43:2:43:18 | ctx.redirect(url) | src/koa.js:43:15:43:17 | url | src/koa.js:30:10:45:1 | async c ... url);\\n} |
|
||||
|
||||
Reference in New Issue
Block a user