Skip to content

Commit 132a8b8

Browse files
committed
JS: Model json and jsonp methods
1 parent d729ab5 commit 132a8b8

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Express.qll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,40 @@ module Express {
781781
override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
782782
}
783783

784+
/**
785+
* A call to `res.json()` or `res.jsonp()`.
786+
*
787+
* This sets the `content-type` header.
788+
*/
789+
private class ResponseJsonCall extends DataFlow::MethodCallNode, Http::HeaderDefinition {
790+
private ResponseSource response;
791+
792+
ResponseJsonCall() { this = response.ref().getAMethodCall(["json", "jsonp"]) }
793+
794+
override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
795+
796+
override string getAHeaderName() { result = "content-type" }
797+
798+
override predicate defines(string headerName, string headerValue) {
799+
// Note: for `jsonp` the actual content-type header will be `text/javascript` or similar, but to avoid
800+
// generating a spurious HTML injection sink, we treat it as `application/json` here.
801+
headerName = "content-type" and headerValue = "application/json"
802+
}
803+
}
804+
805+
/**
806+
* An argument passed to the `json` or `json` method of an HTTP response object.
807+
*/
808+
private class ResponseJsonCallArgument extends Http::ResponseSendArgument {
809+
ResponseJsonCall call;
810+
811+
ResponseJsonCallArgument() { this = call.getArgument(0) }
812+
813+
override RouteHandler getRouteHandler() { result = call.getRouteHandler() }
814+
815+
override HeaderDefinition getAnAssociatedHeaderDefinition() { result = call }
816+
}
817+
784818
/**
785819
* An invocation of the `cookie` method on an HTTP response object.
786820
*/

javascript/ql/test/library-tests/frameworks/Express/tests.expected

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ test_ResponseBody
674674
| src/express.js:61:12:61:25 | req.params.foo | src/express.js:59:23:63:1 | functio ... res);\\n} |
675675
| src/express.js:67:12:67:25 | req.params.foo | src/express.js:65:27:69:1 | functio ... res);\\n} |
676676
| src/express.js:73:12:73:19 | req.path | src/express.js:71:23:75:1 | functio ... res);\\n} |
677+
| src/json.js:5:14:5:27 | req.query.data | src/json.js:4:23:6:1 | functio ... ata);\\n} |
678+
| src/json.js:9:15:9:28 | req.query.data | src/json.js:8:24:10:1 | functio ... ata);\\n} |
677679
| src/params.js:8:18:8:22 | value | src/params.js:4:18:12:1 | (req, r ... }\\n} |
678680
| src/params.js:15:12:15:18 | "Hello" | src/params.js:14:24:16:1 | functio ... lo");\\n} |
679681
test_ResponseExpr
@@ -1005,6 +1007,8 @@ test_HeaderDefinition
10051007
| src/express.js:66:3:66:42 | res.hea ... plain") | src/express.js:65:27:69:1 | functio ... res);\\n} |
10061008
| src/express.js:72:3:72:41 | res.hea ... /html") | src/express.js:71:23:75:1 | functio ... res);\\n} |
10071009
| src/inheritedFromNode.js:6:2:6:16 | res.setHeader() | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
1010+
| src/json.js:5:5:5:28 | res.jso ... y.data) | src/json.js:4:23:6:1 | functio ... ata);\\n} |
1011+
| src/json.js:9:5:9:29 | res.jso ... y.data) | src/json.js:8:24:10:1 | functio ... ata);\\n} |
10081012
| src/responseExprs.js:19:5:19:16 | res.append() | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
10091013
| src/responseExprs.js:37:5:37:28 | f(res.a ... ppend() | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
10101014
| src/responseExprs.js:37:7:37:18 | res.append() | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
@@ -1163,6 +1167,8 @@ test_ResponseSendArgument
11631167
| src/express.js:61:12:61:25 | req.params.foo | src/express.js:59:23:63:1 | functio ... res);\\n} |
11641168
| src/express.js:67:12:67:25 | req.params.foo | src/express.js:65:27:69:1 | functio ... res);\\n} |
11651169
| src/express.js:73:12:73:19 | req.path | src/express.js:71:23:75:1 | functio ... res);\\n} |
1170+
| src/json.js:5:14:5:27 | req.query.data | src/json.js:4:23:6:1 | functio ... ata);\\n} |
1171+
| src/json.js:9:15:9:28 | req.query.data | src/json.js:8:24:10:1 | functio ... ata);\\n} |
11661172
| src/params.js:8:18:8:22 | value | src/params.js:4:18:12:1 | (req, r ... }\\n} |
11671173
| src/params.js:15:12:15:18 | "Hello" | src/params.js:14:24:16:1 | functio ... lo");\\n} |
11681174
test_RouteSetup_getRouter
@@ -1366,6 +1372,8 @@ test_HeaderDefinition_defines
13661372
| src/express.js:60:3:60:47 | res.hea ... n/xml") | content-type | application/xml |
13671373
| src/express.js:66:3:66:42 | res.hea ... plain") | content-type | text/plain |
13681374
| src/express.js:72:3:72:41 | res.hea ... /html") | content-type | text/html |
1375+
| src/json.js:5:5:5:28 | res.jso ... y.data) | content-type | application/json |
1376+
| src/json.js:9:5:9:29 | res.jso ... y.data) | content-type | application/json |
13691377
test_RouteHandlerExpr_getBody
13701378
| src/advanced-routehandler-registration.js:51:9:51:60 | (req, r ... tever") | src/advanced-routehandler-registration.js:51:9:51:60 | (req, r ... tever") |
13711379
| src/advanced-routehandler-registration.js:64:9:64:53 | (req, r ... q, res) | src/advanced-routehandler-registration.js:64:9:64:53 | (req, r ... q, res) |
@@ -2139,6 +2147,8 @@ test_HeaderDefinition_getAHeaderName
21392147
| src/express.js:60:3:60:47 | res.hea ... n/xml") | content-type |
21402148
| src/express.js:66:3:66:42 | res.hea ... plain") | content-type |
21412149
| src/express.js:72:3:72:41 | res.hea ... /html") | content-type |
2150+
| src/json.js:5:5:5:28 | res.jso ... y.data) | content-type |
2151+
| src/json.js:9:5:9:29 | res.jso ... y.data) | content-type |
21422152
test_RouteHandlerExpr_getAsSubRouter
21432153
| src/csurf-example.js:13:17:13:19 | api | src/csurf-example.js:30:16:30:35 | new express.Router() |
21442154
| src/express2.js:6:9:6:14 | router | src/express2.js:2:14:2:23 | e.Router() |
@@ -2155,6 +2165,8 @@ test_RouteHandler_getAResponseHeader
21552165
| src/express.js:65:27:69:1 | functio ... res);\\n} | content-type | src/express.js:66:3:66:42 | res.hea ... plain") |
21562166
| src/express.js:71:23:75:1 | functio ... res);\\n} | access-control-allow-credentials | src/express.js:12:3:12:54 | arg.hea ... , true) |
21572167
| src/express.js:71:23:75:1 | functio ... res);\\n} | content-type | src/express.js:72:3:72:41 | res.hea ... /html") |
2168+
| src/json.js:4:23:6:1 | functio ... ata);\\n} | content-type | src/json.js:5:5:5:28 | res.jso ... y.data) |
2169+
| src/json.js:8:24:10:1 | functio ... ata);\\n} | content-type | src/json.js:9:5:9:29 | res.jso ... y.data) |
21582170
test_RouteSetup_getARouteHandlerExpr
21592171
| src/advanced-routehandler-registration.js:10:3:10:24 | app.get ... es0[p]) | src/advanced-routehandler-registration.js:10:14:10:23 | routes0[p] |
21602172
| src/advanced-routehandler-registration.js:19:3:19:18 | app.use(handler) | src/advanced-routehandler-registration.js:19:11:19:17 | handler |

0 commit comments

Comments
 (0)