Skip to content

Commit 063dbee

Browse files
authored
Merge pull request #1198 from esben-semmle/js/more-express-route-handlers
Approved by xiemaisi
2 parents 2f84aac + 0ec0aa3 commit 063dbee

File tree

4 files changed

+115
-18
lines changed

4 files changed

+115
-18
lines changed

change-notes/1.21/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [socket.io](http://socket.io)
88
- [Node.js](http://nodejs.org)
99
- [Firebase](https://firebase.google.com/)
10+
- [Express](https://expressjs.com/)
1011

1112
* The security queries now track data flow through Base64 decoders such as the Node.js `Buffer` class, the DOM function `atob`, and a number of npm packages intcluding [`abab`](https://www.npmjs.com/package/abab), [`atob`](https://www.npmjs.com/package/atob), [`btoa`](https://www.npmjs.com/package/btoa), [`base-64`](https://www.npmjs.com/package/base-64), [`js-base64`](https://www.npmjs.com/package/js-base64), [`Base64.js`](https://www.npmjs.com/package/Base64) and [`base64-js`](https://www.npmjs.com/package/base64-js).
1213

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

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ module Express {
1414
* Express application.
1515
*/
1616
DataFlow::SourceNode appCreation() {
17-
exists(DataFlow::ModuleImportNode express | express.getPath() = "express" |
18-
// `app = [new] express()`
19-
result = express.getAnInvocation()
20-
)
17+
// `app = [new] express()`
18+
result = DataFlow::moduleImport("express").getAnInvocation()
2119
or
2220
// `app = express.createServer()`
2321
result = DataFlow::moduleMember("express", "createServer").getAnInvocation()
@@ -40,7 +38,13 @@ module Express {
4038
private predicate isRouter(Expr e, RouterDefinition router) {
4139
router.flowsTo(e)
4240
or
43-
isRouter(e.(RouteSetup).getReceiver(), router)
41+
exists (DataFlow::MethodCallNode chain, DataFlow::Node base, string name |
42+
name = "route" or
43+
name = routeSetupMethodName() |
44+
chain.calls(base, name) and
45+
isRouter(base.asExpr(), router) and
46+
chain.flowsToExpr(e)
47+
)
4448
}
4549

4650
/**
@@ -50,31 +54,35 @@ module Express {
5054
RouterDefinition router;
5155

5256
RouteExpr() {
53-
isRouter(this.getReceiver(), router) and
54-
this.getMethodName() = "route"
55-
or
56-
this.(RouteSetup).getReceiver().(RouteExpr).getRouter() = router
57+
isRouter(this, router)
5758
}
5859

5960
/** Gets the router from which this route was created. */
6061
RouterDefinition getRouter() { result = router }
6162
}
6263

6364
/**
64-
* A call to an Express method that sets up a route.
65+
* Gets the name of an Express router method that sets up a route.
66+
*/
67+
string routeSetupMethodName() {
68+
result = "param" or
69+
result = "all" or
70+
result = "use" or
71+
result = any(HTTP::RequestMethodName m).toLowerCase() or
72+
// deprecated methods
73+
result = "error" or
74+
result = "del"
75+
}
76+
77+
/**
78+
* A call to an Express router method that sets up a route.
6579
*/
6680
class RouteSetup extends HTTP::Servers::StandardRouteSetup, MethodCallExpr {
6781
RouterDefinition router;
6882

6983
RouteSetup() {
70-
exists(string methodName | methodName = getMethodName() |
71-
(isRouter(getReceiver(), router) or getReceiver().(RouteExpr).getRouter() = router) and
72-
(
73-
methodName = "all" or
74-
methodName = "use" or
75-
methodName = any(HTTP::RequestMethodName m).toLowerCase()
76-
)
77-
)
84+
isRouter(getReceiver(), router) and
85+
getMethodName() = routeSetupMethodName()
7886
}
7987

8088
/** Gets the path associated with the route. */
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var express = require('express');
2+
3+
express.Router()
4+
.param('', h)
5+
.get('', h);
6+
7+
var app = express.createServer();
8+
app.error(h);
9+
10+
var router = express.Router();
11+
var root = router.route('/');
12+
root.post('', h);

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ test_RouteSetup_getLastRouteHandlerExpr
6666
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | src/responseExprs.js:13:23:15:1 | functio ... res4;\\n} |
6767
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
6868
| src/route.js:4:1:5:39 | router. ... xt) {}) | src/route.js:5:12:5:38 | functio ... ext) {} |
69+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | src/routesetups.js:4:13:4:13 | h |
70+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | src/routesetups.js:5:11:5:11 | h |
71+
| src/routesetups.js:8:1:8:12 | app.error(h) | src/routesetups.js:8:11:8:11 | h |
72+
| src/routesetups.js:12:1:12:16 | root.post('', h) | src/routesetups.js:12:15:12:15 | h |
6973
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:4:19:4:25 | protect |
7074
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:5:14:5:28 | makeSubRouter() |
7175
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | src/subrouter.js:9:27:9:34 | handler1 |
@@ -219,6 +223,10 @@ test_RouteSetup_getRouter
219223
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
220224
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | src/responseExprs.js:2:11:2:19 | express() |
221225
| src/route.js:4:1:5:39 | router. ... xt) {}) | src/route.js:2:14:2:29 | express.Router() |
226+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | src/routesetups.js:3:1:3:16 | express.Router() |
227+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | src/routesetups.js:3:1:3:16 | express.Router() |
228+
| src/routesetups.js:8:1:8:12 | app.error(h) | src/routesetups.js:7:11:7:32 | express ... erver() |
229+
| src/routesetups.js:12:1:12:16 | root.post('', h) | src/routesetups.js:10:14:10:29 | express.Router() |
222230
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:2:11:2:19 | express() |
223231
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:2:11:2:19 | express() |
224232
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | src/subrouter.js:8:16:8:31 | express.Router() |
@@ -483,6 +491,10 @@ test_RouteHandlerExpr
483491
| src/responseExprs.js:13:23:15:1 | functio ... res4;\\n} | src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | true |
484492
| src/responseExprs.js:16:30:42:1 | functio ... }\\n} | src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | true |
485493
| src/route.js:5:12:5:38 | functio ... ext) {} | src/route.js:4:1:5:39 | router. ... xt) {}) | true |
494+
| src/routesetups.js:4:13:4:13 | h | src/routesetups.js:3:1:4:14 | express ... ('', h) | true |
495+
| src/routesetups.js:5:11:5:11 | h | src/routesetups.js:3:1:5:12 | express ... ('', h) | true |
496+
| src/routesetups.js:8:11:8:11 | h | src/routesetups.js:8:1:8:12 | app.error(h) | true |
497+
| src/routesetups.js:12:15:12:15 | h | src/routesetups.js:12:1:12:16 | root.post('', h) | true |
486498
| src/subrouter.js:4:19:4:25 | protect | src/subrouter.js:4:1:4:26 | app.use ... rotect) | false |
487499
| src/subrouter.js:5:14:5:28 | makeSubRouter() | src/subrouter.js:5:1:5:29 | app.use ... uter()) | false |
488500
| src/subrouter.js:9:27:9:34 | handler1 | src/subrouter.js:9:3:9:35 | router. ... ndler1) | true |
@@ -517,6 +529,7 @@ test_appCreation
517529
| src/express4.js:2:11:2:19 | express() |
518530
| src/express.js:2:11:2:19 | express() |
519531
| src/responseExprs.js:2:11:2:19 | express() |
532+
| src/routesetups.js:7:11:7:32 | express ... erver() |
520533
| src/subrouter.js:2:11:2:19 | express() |
521534
test_RouteSetup_getRequestMethod
522535
| src/csurf-example.js:20:1:23:2 | app.get ... ) })\\n}) | GET |
@@ -538,11 +551,56 @@ test_RouteSetup_getRequestMethod
538551
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | GET |
539552
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | GET |
540553
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | POST |
554+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | GET |
555+
| src/routesetups.js:12:1:12:16 | root.post('', h) | POST |
541556
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | POST |
542557
| src/subrouter.js:10:3:10:41 | router. ... ndler2) | POST |
543558
test_RouteExpr
559+
| src/auth.js:4:1:4:53 | app.use ... d' }})) | src/auth.js:1:13:1:32 | require('express')() |
560+
| src/csurf-example.js:13:1:13:20 | app.use('/api', api) | src/csurf-example.js:7:11:7:19 | express() |
561+
| src/csurf-example.js:16:1:16:51 | app.use ... lse })) | src/csurf-example.js:7:11:7:19 | express() |
562+
| src/csurf-example.js:17:1:17:23 | app.use ... rser()) | src/csurf-example.js:7:11:7:19 | express() |
563+
| src/csurf-example.js:18:1:18:31 | app.use ... rue })) | src/csurf-example.js:7:11:7:19 | express() |
564+
| src/csurf-example.js:20:1:23:2 | app.get ... ) })\\n}) | src/csurf-example.js:7:11:7:19 | express() |
565+
| src/csurf-example.js:25:1:27:2 | app.pos ... re')\\n}) | src/csurf-example.js:7:11:7:19 | express() |
566+
| src/csurf-example.js:32:3:34:4 | router. ... ')\\n }) | src/csurf-example.js:30:16:30:35 | new express.Router() |
567+
| src/csurf-example.js:39:1:39:48 | app.get ... es) {}) | src/csurf-example.js:7:11:7:19 | express() |
568+
| src/csurf-example.js:40:1:40:49 | app.pos ... es) {}) | src/csurf-example.js:7:11:7:19 | express() |
569+
| src/express2.js:2:14:2:23 | e.Router() | src/express2.js:2:14:2:23 | e.Router() |
570+
| src/express2.js:3:1:3:56 | router. ... res }) | src/express2.js:2:14:2:23 | e.Router() |
571+
| src/express2.js:3:1:4:77 | router. ... sult }) | src/express2.js:2:14:2:23 | e.Router() |
572+
| src/express2.js:6:1:6:15 | app.use(router) | src/express2.js:5:11:5:13 | e() |
573+
| src/express3.js:4:1:7:2 | app.get ... l");\\n}) | src/express3.js:2:11:2:19 | express() |
574+
| src/express3.js:12:1:12:21 | app.use ... dler()) | src/express3.js:2:11:2:19 | express() |
575+
| src/express4.js:4:1:6:2 | app.get ... ery;\\n}) | src/express4.js:2:11:2:19 | express() |
576+
| src/express.js:4:1:9:2 | app.get ... es);\\n}) | src/express.js:2:11:2:19 | express() |
577+
| src/express.js:16:3:18:4 | router. ... );\\n }) | src/express.js:2:11:2:19 | express() |
578+
| src/express.js:22:1:32:2 | app.pos ... r');\\n}) | src/express.js:2:11:2:19 | express() |
579+
| src/express.js:34:1:34:53 | app.get ... andler) | src/express.js:2:11:2:19 | express() |
580+
| src/express.js:39:1:39:21 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
581+
| src/express.js:44:1:44:26 | app.use ... dler()) | src/express.js:2:11:2:19 | express() |
582+
| src/express.js:46:1:51:2 | app.pos ... me];\\n}) | src/express.js:2:11:2:19 | express() |
583+
| src/responseExprs.js:4:1:6:2 | app.get ... res1\\n}) | src/responseExprs.js:2:11:2:19 | express() |
584+
| src/responseExprs.js:7:1:9:2 | app.get ... es2;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
585+
| src/responseExprs.js:10:1:12:2 | app.get ... es3;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
586+
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | src/responseExprs.js:2:11:2:19 | express() |
587+
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | src/responseExprs.js:2:11:2:19 | express() |
588+
| src/route.js:2:14:2:29 | express.Router() | src/route.js:2:14:2:29 | express.Router() |
544589
| src/route.js:4:1:4:31 | router. ... er_id') | src/route.js:2:14:2:29 | express.Router() |
545590
| src/route.js:4:1:5:39 | router. ... xt) {}) | src/route.js:2:14:2:29 | express.Router() |
591+
| src/routesetups.js:3:1:3:16 | express.Router() | src/routesetups.js:3:1:3:16 | express.Router() |
592+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | src/routesetups.js:3:1:3:16 | express.Router() |
593+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | src/routesetups.js:3:1:3:16 | express.Router() |
594+
| src/routesetups.js:7:11:7:32 | express ... erver() | src/routesetups.js:7:11:7:32 | express ... erver() |
595+
| src/routesetups.js:8:1:8:12 | app.error(h) | src/routesetups.js:7:11:7:32 | express ... erver() |
596+
| src/routesetups.js:10:14:10:29 | express.Router() | src/routesetups.js:10:14:10:29 | express.Router() |
597+
| src/routesetups.js:11:12:11:28 | router.route('/') | src/routesetups.js:10:14:10:29 | express.Router() |
598+
| src/routesetups.js:12:1:12:16 | root.post('', h) | src/routesetups.js:10:14:10:29 | express.Router() |
599+
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:2:11:2:19 | express() |
600+
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:2:11:2:19 | express() |
601+
| src/subrouter.js:8:16:8:31 | express.Router() | src/subrouter.js:8:16:8:31 | express.Router() |
602+
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | src/subrouter.js:8:16:8:31 | express.Router() |
603+
| src/subrouter.js:10:3:10:41 | router. ... ndler2) | src/subrouter.js:8:16:8:31 | express.Router() |
546604
test_RouteHandler_getAResponseExpr
547605
| src/csurf-example.js:20:18:23:1 | functio ... () })\\n} | src/csurf-example.js:22:3:22:5 | res |
548606
| src/csurf-example.js:25:22:27:1 | functio ... ere')\\n} | src/csurf-example.js:26:3:26:5 | res |
@@ -727,6 +785,10 @@ test_RouteSetup_getARouteHandler
727785
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | src/responseExprs.js:13:23:15:1 | functio ... res4;\\n} |
728786
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
729787
| src/route.js:4:1:5:39 | router. ... xt) {}) | src/route.js:5:12:5:38 | functio ... ext) {} |
788+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | src/routesetups.js:4:13:4:13 | h |
789+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | src/routesetups.js:5:11:5:11 | h |
790+
| src/routesetups.js:8:1:8:12 | app.error(h) | src/routesetups.js:8:11:8:11 | h |
791+
| src/routesetups.js:12:1:12:16 | root.post('', h) | src/routesetups.js:12:15:12:15 | h |
730792
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:4:19:4:25 | protect |
731793
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:5:14:5:28 | makeSubRouter() |
732794
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:8:16:8:31 | express.Router() |
@@ -765,6 +827,9 @@ test_isRouterCreation
765827
| src/express.js:2:11:2:19 | express() |
766828
| src/responseExprs.js:2:11:2:19 | express() |
767829
| src/route.js:2:14:2:29 | express.Router() |
830+
| src/routesetups.js:3:1:3:16 | express.Router() |
831+
| src/routesetups.js:7:11:7:32 | express ... erver() |
832+
| src/routesetups.js:10:14:10:29 | express.Router() |
768833
| src/subrouter.js:2:11:2:19 | express() |
769834
| src/subrouter.js:8:16:8:31 | express.Router() |
770835
test_RouteSetup_getRouteHandlerExpr
@@ -797,6 +862,10 @@ test_RouteSetup_getRouteHandlerExpr
797862
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | 0 | src/responseExprs.js:13:23:15:1 | functio ... res4;\\n} |
798863
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | 0 | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
799864
| src/route.js:4:1:5:39 | router. ... xt) {}) | 0 | src/route.js:5:12:5:38 | functio ... ext) {} |
865+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | 0 | src/routesetups.js:4:13:4:13 | h |
866+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | 0 | src/routesetups.js:5:11:5:11 | h |
867+
| src/routesetups.js:8:1:8:12 | app.error(h) | 0 | src/routesetups.js:8:11:8:11 | h |
868+
| src/routesetups.js:12:1:12:16 | root.post('', h) | 0 | src/routesetups.js:12:15:12:15 | h |
800869
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | 0 | src/subrouter.js:4:19:4:25 | protect |
801870
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | 0 | src/subrouter.js:5:14:5:28 | makeSubRouter() |
802871
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | 0 | src/subrouter.js:9:27:9:34 | handler1 |
@@ -813,6 +882,9 @@ test_RouterDefinition_RouterDefinition
813882
| src/express.js:2:11:2:19 | express() |
814883
| src/responseExprs.js:2:11:2:19 | express() |
815884
| src/route.js:2:14:2:29 | express.Router() |
885+
| src/routesetups.js:3:1:3:16 | express.Router() |
886+
| src/routesetups.js:7:11:7:32 | express ... erver() |
887+
| src/routesetups.js:10:14:10:29 | express.Router() |
816888
| src/subrouter.js:2:11:2:19 | express() |
817889
| src/subrouter.js:8:16:8:31 | express.Router() |
818890
test_RouteHandler_getARequestBodyAccess
@@ -878,6 +950,10 @@ test_RouteSetup_getARouteHandlerExpr
878950
| src/responseExprs.js:13:1:15:2 | app.get ... es4;\\n}) | src/responseExprs.js:13:23:15:1 | functio ... res4;\\n} |
879951
| src/responseExprs.js:16:1:42:2 | app.pos ... }\\n}) | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
880952
| src/route.js:4:1:5:39 | router. ... xt) {}) | src/route.js:5:12:5:38 | functio ... ext) {} |
953+
| src/routesetups.js:3:1:4:14 | express ... ('', h) | src/routesetups.js:4:13:4:13 | h |
954+
| src/routesetups.js:3:1:5:12 | express ... ('', h) | src/routesetups.js:5:11:5:11 | h |
955+
| src/routesetups.js:8:1:8:12 | app.error(h) | src/routesetups.js:8:11:8:11 | h |
956+
| src/routesetups.js:12:1:12:16 | root.post('', h) | src/routesetups.js:12:15:12:15 | h |
881957
| src/subrouter.js:4:1:4:26 | app.use ... rotect) | src/subrouter.js:4:19:4:25 | protect |
882958
| src/subrouter.js:5:1:5:29 | app.use ... uter()) | src/subrouter.js:5:14:5:28 | makeSubRouter() |
883959
| src/subrouter.js:9:3:9:35 | router. ... ndler1) | src/subrouter.js:9:27:9:34 | handler1 |

0 commit comments

Comments
 (0)