mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
@@ -549,4 +549,72 @@ module ClientRequest {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to an instance of `chrome-remote-interface`.
|
||||
*
|
||||
* An instantiation of `chrome-remote-interface` either accepts a callback or returns a promise.
|
||||
*
|
||||
* The `isPromise` parameter reflects whether the reference is a promise containing
|
||||
* an instance of `chrome-remote-interface`, or an instance of `chrome-remote-interface`.
|
||||
*/
|
||||
private DataFlow::SourceNode chromeRemoteInterface(DataFlow::TypeTracker t, boolean isPromise) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call |
|
||||
call = DataFlow::moduleImport("chrome-remote-interface").getAnInvocation()
|
||||
|
|
||||
result = call and isPromise = true
|
||||
or
|
||||
result = call.getCallback([0 .. 1]).getParameter(0) and isPromise = false
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = chromeRemoteInterface(t2, isPromise).track(t2, t))
|
||||
or
|
||||
// Simple promise tracking.
|
||||
exists(DataFlow::TypeTracker t2, DataFlow::SourceNode pred |
|
||||
pred = chromeRemoteInterface(t2, true) and
|
||||
isPromise = false and
|
||||
(
|
||||
t2 = t and
|
||||
exists(AwaitExpr await | DataFlow::valueNode(await.getOperand()).getALocalSource() = pred |
|
||||
result.getEnclosingExpr() = await
|
||||
)
|
||||
or
|
||||
t2 = t and
|
||||
exists(DataFlow::MethodCallNode thenCall |
|
||||
thenCall.getMethodName() = "then" and pred = thenCall.getReceiver().getALocalSource()
|
||||
|
|
||||
result = thenCall.getCallback(0).getParameter(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to navigate a browser controlled by `chrome-remote-interface` to a specific URL.
|
||||
*/
|
||||
class ChromeRemoteInterfaceRequest extends ClientRequest::Range, DataFlow::CallNode {
|
||||
int optionsArg;
|
||||
|
||||
ChromeRemoteInterfaceRequest() {
|
||||
exists(DataFlow::SourceNode instance |
|
||||
instance = chromeRemoteInterface(DataFlow::TypeTracker::end(), false)
|
||||
|
|
||||
optionsArg = 0 and
|
||||
this = instance.getAPropertyRead("Page").getAMemberCall("navigate")
|
||||
or
|
||||
optionsArg = 1 and
|
||||
this = instance.getAMemberCall("send") and
|
||||
this.getArgument(0).mayHaveStringValue("Page.navigate")
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getUrl() {
|
||||
result = getArgument(optionsArg).getALocalSource().getAPropertyWrite("url").getRhs()
|
||||
}
|
||||
|
||||
override DataFlow::Node getHost() { none() }
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ nodes
|
||||
| tst.js:45:13:45:56 | 'http:/ ... tainted |
|
||||
| tst.js:45:13:45:56 | 'http:/ ... tainted |
|
||||
| tst.js:45:50:45:56 | tainted |
|
||||
| tst.js:58:9:58:52 | tainted |
|
||||
| tst.js:58:19:58:42 | url.par ... , true) |
|
||||
| tst.js:58:19:58:48 | url.par ... ).query |
|
||||
| tst.js:58:19:58:52 | url.par ... ery.url |
|
||||
| tst.js:58:29:58:35 | req.url |
|
||||
| tst.js:58:29:58:35 | req.url |
|
||||
| tst.js:61:29:61:35 | tainted |
|
||||
| tst.js:61:29:61:35 | tainted |
|
||||
| tst.js:64:30:64:36 | tainted |
|
||||
| tst.js:64:30:64:36 | tainted |
|
||||
edges
|
||||
| tst.js:14:9:14:52 | tainted | tst.js:18:13:18:19 | tainted |
|
||||
| tst.js:14:9:14:52 | tainted | tst.js:18:13:18:19 | tainted |
|
||||
@@ -75,6 +85,15 @@ edges
|
||||
| tst.js:43:46:43:52 | tainted | tst.js:43:13:43:54 | `http:/ ... inted}` |
|
||||
| tst.js:45:50:45:56 | tainted | tst.js:45:13:45:56 | 'http:/ ... tainted |
|
||||
| tst.js:45:50:45:56 | tainted | tst.js:45:13:45:56 | 'http:/ ... tainted |
|
||||
| tst.js:58:9:58:52 | tainted | tst.js:61:29:61:35 | tainted |
|
||||
| tst.js:58:9:58:52 | tainted | tst.js:61:29:61:35 | tainted |
|
||||
| tst.js:58:9:58:52 | tainted | tst.js:64:30:64:36 | tainted |
|
||||
| tst.js:58:9:58:52 | tainted | tst.js:64:30:64:36 | tainted |
|
||||
| tst.js:58:19:58:42 | url.par ... , true) | tst.js:58:19:58:48 | url.par ... ).query |
|
||||
| tst.js:58:19:58:48 | url.par ... ).query | tst.js:58:19:58:52 | url.par ... ery.url |
|
||||
| tst.js:58:19:58:52 | url.par ... ery.url | tst.js:58:9:58:52 | tainted |
|
||||
| tst.js:58:29:58:35 | req.url | tst.js:58:19:58:42 | url.par ... , true) |
|
||||
| tst.js:58:29:58:35 | req.url | tst.js:58:19:58:42 | url.par ... , true) |
|
||||
#select
|
||||
| tst.js:18:5:18:20 | request(tainted) | tst.js:14:29:14:35 | req.url | tst.js:18:13:18:19 | tainted | The $@ of this request depends on $@. | tst.js:18:13:18:19 | tainted | URL | tst.js:14:29:14:35 | req.url | a user-provided value |
|
||||
| tst.js:20:5:20:24 | request.get(tainted) | tst.js:14:29:14:35 | req.url | tst.js:20:17:20:23 | tainted | The $@ of this request depends on $@. | tst.js:20:17:20:23 | tainted | URL | tst.js:14:29:14:35 | req.url | a user-provided value |
|
||||
@@ -88,3 +107,5 @@ edges
|
||||
| tst.js:41:5:41:52 | request ... nted}`) | tst.js:14:29:14:35 | req.url | tst.js:41:13:41:51 | `http:/ ... inted}` | The $@ of this request depends on $@. | tst.js:41:13:41:51 | `http:/ ... inted}` | URL | tst.js:14:29:14:35 | req.url | a user-provided value |
|
||||
| tst.js:43:5:43:55 | request ... nted}`) | tst.js:14:29:14:35 | req.url | tst.js:43:13:43:54 | `http:/ ... inted}` | The $@ of this request depends on $@. | tst.js:43:13:43:54 | `http:/ ... inted}` | URL | tst.js:14:29:14:35 | req.url | a user-provided value |
|
||||
| tst.js:45:5:45:57 | request ... ainted) | tst.js:14:29:14:35 | req.url | tst.js:45:13:45:56 | 'http:/ ... tainted | The $@ of this request depends on $@. | tst.js:45:13:45:56 | 'http:/ ... tainted | URL | tst.js:14:29:14:35 | req.url | a user-provided value |
|
||||
| tst.js:61:2:61:37 | client. ... inted}) | tst.js:58:29:58:35 | req.url | tst.js:61:29:61:35 | tainted | The $@ of this request depends on $@. | tst.js:61:29:61:35 | tainted | URL | tst.js:58:29:58:35 | req.url | a user-provided value |
|
||||
| tst.js:64:3:64:38 | client. ... inted}) | tst.js:58:29:58:35 | req.url | tst.js:64:30:64:36 | tainted | The $@ of this request depends on $@. | tst.js:64:30:64:36 | tainted | URL | tst.js:58:29:58:35 | req.url | a user-provided value |
|
||||
|
||||
@@ -52,3 +52,15 @@ var server = http.createServer(function(req, res) {
|
||||
|
||||
request(`${base}${tainted}`); // OK - assumed safe
|
||||
})
|
||||
|
||||
var CDP = require("chrome-remote-interface");
|
||||
var server = http.createServer(async function(req, res) {
|
||||
var tainted = url.parse(req.url, true).query.url;
|
||||
|
||||
var client = await CDP(options);
|
||||
client.Page.navigate({url: tainted}); // NOT OK.
|
||||
|
||||
CDP(options, (client) => {
|
||||
client.Page.navigate({url: tainted}); // NOT OK.
|
||||
});
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user