Skip to content

Commit 1313821

Browse files
authored
Merge pull request #1904 from erik-semmle/passportModel
Approved by asger-semmle, esben-semmle
2 parents f5cae9b + 03b210a commit 1313821

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,48 @@ module Express {
147147
this.getRequestMethod() = that.getRequestMethod()
148148
}
149149
}
150+
151+
/**
152+
* A call that sets up a Passport router that includes the request object.
153+
*/
154+
private class PassportRouteSetup extends HTTP::Servers::StandardRouteSetup, CallExpr {
155+
DataFlow::ModuleImportNode importNode;
156+
DataFlow::FunctionNode callback;
157+
158+
// looks for this pattern: passport.use(new Strategy({passReqToCallback: true}, callback))
159+
PassportRouteSetup() {
160+
importNode = DataFlow::moduleImport("passport") and
161+
this = importNode.getAMemberCall("use").asExpr() and
162+
exists(DataFlow::NewNode strategy |
163+
strategy.flowsToExpr(this.getArgument(0)) and
164+
strategy.getNumArgument() = 2 and
165+
// new Strategy({passReqToCallback: true}, ...)
166+
strategy.getOptionArgument(0, "passReqToCallback").mayHaveBooleanValue(true) and
167+
callback.flowsTo(strategy.getArgument(1))
168+
)
169+
}
170+
171+
override Expr getServer() { result = importNode.asExpr() }
172+
173+
override DataFlow::SourceNode getARouteHandler() {
174+
result = callback
175+
}
176+
}
177+
178+
/**
179+
* The callback given to passport in PassportRouteSetup.
180+
*/
181+
private class PassportRouteHandler extends RouteHandler, HTTP::Servers::StandardRouteHandler,
182+
DataFlow::ValueNode {
183+
override Function astNode;
184+
185+
PassportRouteHandler() { this = any(PassportRouteSetup setup).getARouteHandler() }
186+
187+
override SimpleParameter getRouteHandlerParameter(string kind) {
188+
kind = "request" and
189+
result = astNode.getParameter(0)
190+
}
191+
}
150192

151193
/**
152194
* An expression used as an Express route handler, such as `submitHandler` below:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var express = require("express");
2+
var passport = require('passport');
3+
var twitter = require('passport-twitter');
4+
5+
passport.use(new twitter.Strategy({
6+
consumerKey : "foo",
7+
consumerSecret : "bar",
8+
callbackURL : "baz"
9+
}, function(accessToken, refreshToken, profile, done) {
10+
accessToken.body; // Not tainted. No passReqToCallback flag.
11+
}));
12+
13+
passport.use(new twitter.Strategy({
14+
consumerKey : "foo",
15+
consumerSecret : "bar",
16+
callbackURL : "baz",
17+
passReqToCallback : false
18+
}, function(accessToken, refreshToken, profile, done) {
19+
accessToken.body; // Not tainted. No passReqToCallback set to false.
20+
}));
21+
22+
passport.use(new twitter.Strategy({
23+
consumerKey : "foo",
24+
consumerSecret : "bar",
25+
callbackURL : "baz",
26+
passReqToCallback : true
27+
}, function(req, accessToken, refreshToken, profile, done) {
28+
req.body; // `passReqToCallback` is `true`, so `req` is assumed to be an Express request object, causing this to be a `RequestInputAccss`
29+
}));

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ test_isRequest
197197
| src/express.js:49:3:49:5 | req |
198198
| src/express.js:50:3:50:5 | req |
199199
| src/inheritedFromNode.js:7:2:7:4 | req |
200+
| src/passport.js:28:2:28:4 | req |
200201
| src/responseExprs.js:17:5:17:7 | req |
201202
test_RouteSetup_getRouter
202203
| src/auth.js:4:1:4:53 | app.use ... d' }})) | src/auth.js:1:13:1:32 | require('express')() |
@@ -279,6 +280,7 @@ test_RequestInputAccess
279280
| src/express.js:49:3:49:14 | req.hostname | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
280281
| src/express.js:50:3:50:32 | req.hea ... erName] | header | src/express.js:46:22:51:1 | functio ... ame];\\n} |
281282
| src/inheritedFromNode.js:7:2:7:8 | req.url | url | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
283+
| src/passport.js:28:2:28:9 | req.body | body | src/passport.js:27:4:29:1 | functio ... ccss`\\n} |
282284
test_SetCookie
283285
| src/express.js:31:3:31:26 | res.coo ... 'bar') | src/express.js:22:30:32:1 | functio ... ar');\\n} |
284286
| src/responseExprs.js:23:5:23:16 | res.cookie() | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
@@ -448,6 +450,7 @@ test_ExpressSession
448450
| src/express-session.js:7:1:9:2 | session ... -3"]\\n}) | secret | src/express-session.js:8:13:8:44 | ["secre ... key-3"] |
449451
test_RequestBodyAccess
450452
| src/express.js:23:3:23:10 | req.body |
453+
| src/passport.js:28:2:28:9 | req.body |
451454
test_RouteSetup_getServer
452455
| src/csurf-example.js:20:1:23:2 | app.get ... ) })\\n}) | src/csurf-example.js:7:11:7:19 | express() |
453456
| src/csurf-example.js:25:1:27:2 | app.pos ... re')\\n}) | src/csurf-example.js:7:11:7:19 | express() |
@@ -918,6 +921,7 @@ test_RouterDefinition_RouterDefinition
918921
| src/subrouter.js:8:16:8:31 | express.Router() |
919922
test_RouteHandler_getARequestBodyAccess
920923
| src/express.js:22:30:32:1 | functio ... ar');\\n} | src/express.js:23:3:23:10 | req.body |
924+
| src/passport.js:27:4:29:1 | functio ... ccss`\\n} | src/passport.js:28:2:28:9 | req.body |
921925
test_RouterDefinition_getMiddlewareStack
922926
| src/auth.js:1:13:1:32 | require('express')() | src/auth.js:4:9:4:52 | basicAu ... rd' }}) |
923927
| src/csurf-example.js:7:11:7:19 | express() | src/csurf-example.js:18:9:18:30 | csrf({ ... true }) |
@@ -1023,6 +1027,7 @@ test_RequestExpr
10231027
| src/express.js:49:3:49:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
10241028
| src/express.js:50:3:50:5 | req | src/express.js:46:22:51:1 | functio ... ame];\\n} |
10251029
| src/inheritedFromNode.js:7:2:7:4 | req | src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} |
1030+
| src/passport.js:28:2:28:4 | req | src/passport.js:27:4:29:1 | functio ... ccss`\\n} |
10261031
| src/responseExprs.js:17:5:17:7 | req | src/responseExprs.js:16:30:42:1 | functio ... }\\n} |
10271032
test_RequestExprStandalone
10281033
| typed_src/tst.ts:6:3:6:3 | x |
@@ -1055,4 +1060,5 @@ test_RouteHandler_getARequestExpr
10551060
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:49:3:49:5 | req |
10561061
| src/express.js:46:22:51:1 | functio ... ame];\\n} | src/express.js:50:3:50:5 | req |
10571062
| src/inheritedFromNode.js:4:15:8:1 | functio ... .url;\\n} | src/inheritedFromNode.js:7:2:7:4 | req |
1063+
| src/passport.js:27:4:29:1 | functio ... ccss`\\n} | src/passport.js:28:2:28:4 | req |
10581064
| src/responseExprs.js:16:30:42:1 | functio ... }\\n} | src/responseExprs.js:17:5:17:7 | req |

0 commit comments

Comments
 (0)