Skip to content

Commit c400b45

Browse files
committed
JS: make the Fastify model support isUserControlledObject
1 parent 894033d commit c400b45

File tree

4 files changed

+143
-6
lines changed

4 files changed

+143
-6
lines changed

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,51 @@ module Fastify {
146146
override RouteHandler getRouteHandler() { result = rh }
147147

148148
override string getKind() { result = kind }
149+
150+
override predicate isUserControlledObject() {
151+
kind = "body" and
152+
(
153+
usesFastifyPlugin(rh, DataFlow::moduleImport(["fastify-xml-body-parser", "fastify-formbody"]))
154+
or
155+
usesMiddleware(rh,
156+
any(ExpressLibraries::BodyParser bodyParser | bodyParser.producesUserControlledObjects()))
157+
)
158+
or
159+
kind = "parameter" and
160+
usesFastifyPlugin(rh, DataFlow::moduleImport("fastify-qs"))
161+
}
162+
}
163+
164+
/**
165+
* Holds if `rh` uses `plugin`.
166+
*/
167+
private predicate usesFastifyPlugin(RouteHandler rh, DataFlow::SourceNode plugin) {
168+
exists(RouteSetup setup |
169+
plugin
170+
.flowsTo(setup
171+
.getServer()
172+
.flow()
173+
.(DataFlow::SourceNode)
174+
.getAMethodCall("register")
175+
.getArgument(0)) and // only matches the plugins that apply to all routes
176+
rh = setup.getARouteHandler()
177+
)
178+
}
179+
180+
/**
181+
* Holds if `rh` uses `plugin`.
182+
*/
183+
private predicate usesMiddleware(RouteHandler rh, DataFlow::SourceNode middleware) {
184+
exists(RouteSetup setup |
185+
middleware
186+
.flowsTo(setup
187+
.getServer()
188+
.flow()
189+
.(DataFlow::SourceNode)
190+
.getAMethodCall("use")
191+
.getArgument(0)) and // only matches the middlewares that apply to all routes
192+
rh = setup.getARouteHandler()
193+
)
149194
}
150195

151196
/**
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import javascript
22

33
query predicate test_RequestInputAccess(
4-
HTTP::RequestInputAccess ria, string res, Fastify::RouteHandler rh
4+
HTTP::RequestInputAccess ria, string res, Fastify::RouteHandler rh, boolean isUserControlledObject
55
) {
6-
ria.getRouteHandler() = rh and res = ria.getKind()
6+
ria.getRouteHandler() = rh and
7+
res = ria.getKind() and
8+
if ria.isUserControlledObject()
9+
then isUserControlledObject = true
10+
else isUserControlledObject = false
711
}

javascript/ql/test/library-tests/frameworks/fastify/src/fastify.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,47 @@ fastify.post(
4646
}
4747
);
4848
fastify.listen(3000);
49+
50+
var fastifyWithObjects1 = require("fastify")();
51+
fastifyWithObjects1.register(require("fastify-xml-body-parser"));
52+
fastifyWithObjects1.post(
53+
"/:params",
54+
/* handler */ function(request, reply) {
55+
request.query;
56+
request.body;
57+
request.params;
58+
}
59+
);
60+
61+
var fastifyWithObjects2 = require("fastify")();
62+
fastifyWithObjects2.register(require("fastify-formbody"));
63+
fastifyWithObjects2.post(
64+
"/:params",
65+
/* handler */ function(request, reply) {
66+
request.query;
67+
request.body;
68+
request.params;
69+
}
70+
);
71+
72+
var fastifyWithObjects3 = require("fastify")();
73+
fastifyWithObjects3.register(require("fastify-qs"));
74+
fastifyWithObjects3.post(
75+
"/:params",
76+
/* handler */ function(request, reply) {
77+
request.query;
78+
request.body;
79+
request.params;
80+
}
81+
);
82+
83+
var fastifyWithObjects4 = require("fastify")();
84+
fastifyWithObjects4.use(require("body-parser").urlencoded({ extended: true }));
85+
fastifyWithObjects4.post(
86+
"/:params",
87+
/* handler */ function(request, reply) {
88+
request.query;
89+
request.body;
90+
request.params;
91+
}
92+
);

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

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,27 @@ test_RouteSetup
33
| src/fastify.js:10:1:21:2 | fastify ... > {}\\n}) |
44
| src/fastify.js:23:1:29:1 | fastify ... e\\n }\\n) |
55
| src/fastify.js:31:1:47:1 | fastify ... m\\n }\\n) |
6+
| src/fastify.js:52:1:59:1 | fastify ... ;\\n }\\n) |
7+
| src/fastify.js:63:1:70:1 | fastify ... ;\\n }\\n) |
8+
| src/fastify.js:74:1:81:1 | fastify ... ;\\n }\\n) |
9+
| src/fastify.js:85:1:92:1 | fastify ... ;\\n }\\n) |
610
test_RequestInputAccess
7-
| src/fastify.js:36:5:36:17 | request.query | parameter | src/fastify.js:34:17:46:3 | functio ... eam\\n } |
8-
| src/fastify.js:37:5:37:16 | request.body | body | src/fastify.js:34:17:46:3 | functio ... eam\\n } |
9-
| src/fastify.js:38:5:38:18 | request.params | parameter | src/fastify.js:34:17:46:3 | functio ... eam\\n } |
10-
| src/fastify.js:39:5:39:24 | request.headers.name | header | src/fastify.js:34:17:46:3 | functio ... eam\\n } |
11+
| src/fastify.js:36:5:36:17 | request.query | parameter | src/fastify.js:34:17:46:3 | functio ... eam\\n } | false |
12+
| src/fastify.js:37:5:37:16 | request.body | body | src/fastify.js:34:17:46:3 | functio ... eam\\n } | false |
13+
| src/fastify.js:38:5:38:18 | request.params | parameter | src/fastify.js:34:17:46:3 | functio ... eam\\n } | false |
14+
| src/fastify.js:39:5:39:24 | request.headers.name | header | src/fastify.js:34:17:46:3 | functio ... eam\\n } | false |
15+
| src/fastify.js:55:5:55:17 | request.query | parameter | src/fastify.js:54:17:58:3 | functio ... ms;\\n } | false |
16+
| src/fastify.js:56:5:56:16 | request.body | body | src/fastify.js:54:17:58:3 | functio ... ms;\\n } | true |
17+
| src/fastify.js:57:5:57:18 | request.params | parameter | src/fastify.js:54:17:58:3 | functio ... ms;\\n } | false |
18+
| src/fastify.js:66:5:66:17 | request.query | parameter | src/fastify.js:65:17:69:3 | functio ... ms;\\n } | false |
19+
| src/fastify.js:67:5:67:16 | request.body | body | src/fastify.js:65:17:69:3 | functio ... ms;\\n } | true |
20+
| src/fastify.js:68:5:68:18 | request.params | parameter | src/fastify.js:65:17:69:3 | functio ... ms;\\n } | false |
21+
| src/fastify.js:77:5:77:17 | request.query | parameter | src/fastify.js:76:17:80:3 | functio ... ms;\\n } | true |
22+
| src/fastify.js:78:5:78:16 | request.body | body | src/fastify.js:76:17:80:3 | functio ... ms;\\n } | false |
23+
| src/fastify.js:79:5:79:18 | request.params | parameter | src/fastify.js:76:17:80:3 | functio ... ms;\\n } | true |
24+
| src/fastify.js:88:5:88:17 | request.query | parameter | src/fastify.js:87:17:91:3 | functio ... ms;\\n } | false |
25+
| src/fastify.js:89:5:89:16 | request.body | body | src/fastify.js:87:17:91:3 | functio ... ms;\\n } | true |
26+
| src/fastify.js:90:5:90:18 | request.params | parameter | src/fastify.js:87:17:91:3 | functio ... ms;\\n } | false |
1127
test_RouteHandler_getAResponseHeader
1228
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | name | src/fastify.js:42:5:42:33 | reply.h ... value") |
1329
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | name | src/fastify.js:43:5:43:36 | reply.h ... lue" }) |
@@ -22,11 +38,19 @@ test_RouteSetup_getServer
2238
| src/fastify.js:10:1:21:2 | fastify ... > {}\\n}) | src/fastify.js:1:15:1:34 | require("fastify")() |
2339
| src/fastify.js:23:1:29:1 | fastify ... e\\n }\\n) | src/fastify.js:1:15:1:34 | require("fastify")() |
2440
| src/fastify.js:31:1:47:1 | fastify ... m\\n }\\n) | src/fastify.js:1:15:1:34 | require("fastify")() |
41+
| src/fastify.js:52:1:59:1 | fastify ... ;\\n }\\n) | src/fastify.js:50:27:50:46 | require("fastify")() |
42+
| src/fastify.js:63:1:70:1 | fastify ... ;\\n }\\n) | src/fastify.js:61:27:61:46 | require("fastify")() |
43+
| src/fastify.js:74:1:81:1 | fastify ... ;\\n }\\n) | src/fastify.js:72:27:72:46 | require("fastify")() |
44+
| src/fastify.js:85:1:92:1 | fastify ... ;\\n }\\n) | src/fastify.js:83:27:83:46 | require("fastify")() |
2545
test_HeaderDefinition_getAHeaderName
2646
| src/fastify.js:42:5:42:33 | reply.h ... value") | name |
2747
| src/fastify.js:43:5:43:36 | reply.h ... lue" }) | name |
2848
test_ServerDefinition
2949
| src/fastify.js:1:15:1:34 | require("fastify")() |
50+
| src/fastify.js:50:27:50:46 | require("fastify")() |
51+
| src/fastify.js:61:27:61:46 | require("fastify")() |
52+
| src/fastify.js:72:27:72:46 | require("fastify")() |
53+
| src/fastify.js:83:27:83:46 | require("fastify")() |
3054
test_HeaderAccess
3155
| src/fastify.js:39:5:39:24 | request.headers.name | name |
3256
test_RouteSetup_getARouteHandler
@@ -41,6 +65,10 @@ test_RouteSetup_getARouteHandler
4165
| src/fastify.js:10:1:21:2 | fastify ... > {}\\n}) | src/fastify.js:20:26:20:47 | (reques ... ) => {} |
4266
| src/fastify.js:23:1:29:1 | fastify ... e\\n }\\n) | src/fastify.js:26:17:28:3 | (reques ... nse\\n } |
4367
| src/fastify.js:31:1:47:1 | fastify ... m\\n }\\n) | src/fastify.js:34:17:46:3 | functio ... eam\\n } |
68+
| src/fastify.js:52:1:59:1 | fastify ... ;\\n }\\n) | src/fastify.js:54:17:58:3 | functio ... ms;\\n } |
69+
| src/fastify.js:63:1:70:1 | fastify ... ;\\n }\\n) | src/fastify.js:65:17:69:3 | functio ... ms;\\n } |
70+
| src/fastify.js:74:1:81:1 | fastify ... ;\\n }\\n) | src/fastify.js:76:17:80:3 | functio ... ms;\\n } |
71+
| src/fastify.js:85:1:92:1 | fastify ... ;\\n }\\n) | src/fastify.js:87:17:91:3 | functio ... ms;\\n } |
4472
test_RouteHandler
4573
| src/fastify.js:5:17:7:3 | async ( ... nse\\n } | src/fastify.js:1:15:1:34 | require("fastify")() |
4674
| src/fastify.js:13:28:13:55 | (reques ... ) => {} | src/fastify.js:1:15:1:34 | require("fastify")() |
@@ -53,11 +81,27 @@ test_RouteHandler
5381
| src/fastify.js:20:26:20:47 | (reques ... ) => {} | src/fastify.js:1:15:1:34 | require("fastify")() |
5482
| src/fastify.js:26:17:28:3 | (reques ... nse\\n } | src/fastify.js:1:15:1:34 | require("fastify")() |
5583
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | src/fastify.js:1:15:1:34 | require("fastify")() |
84+
| src/fastify.js:54:17:58:3 | functio ... ms;\\n } | src/fastify.js:50:27:50:46 | require("fastify")() |
85+
| src/fastify.js:65:17:69:3 | functio ... ms;\\n } | src/fastify.js:61:27:61:46 | require("fastify")() |
86+
| src/fastify.js:76:17:80:3 | functio ... ms;\\n } | src/fastify.js:72:27:72:46 | require("fastify")() |
87+
| src/fastify.js:87:17:91:3 | functio ... ms;\\n } | src/fastify.js:83:27:83:46 | require("fastify")() |
5688
test_RouteHandler_getARequestExpr
5789
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | src/fastify.js:36:5:36:11 | request |
5890
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | src/fastify.js:37:5:37:11 | request |
5991
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | src/fastify.js:38:5:38:11 | request |
6092
| src/fastify.js:34:17:46:3 | functio ... eam\\n } | src/fastify.js:39:5:39:11 | request |
93+
| src/fastify.js:54:17:58:3 | functio ... ms;\\n } | src/fastify.js:55:5:55:11 | request |
94+
| src/fastify.js:54:17:58:3 | functio ... ms;\\n } | src/fastify.js:56:5:56:11 | request |
95+
| src/fastify.js:54:17:58:3 | functio ... ms;\\n } | src/fastify.js:57:5:57:11 | request |
96+
| src/fastify.js:65:17:69:3 | functio ... ms;\\n } | src/fastify.js:66:5:66:11 | request |
97+
| src/fastify.js:65:17:69:3 | functio ... ms;\\n } | src/fastify.js:67:5:67:11 | request |
98+
| src/fastify.js:65:17:69:3 | functio ... ms;\\n } | src/fastify.js:68:5:68:11 | request |
99+
| src/fastify.js:76:17:80:3 | functio ... ms;\\n } | src/fastify.js:77:5:77:11 | request |
100+
| src/fastify.js:76:17:80:3 | functio ... ms;\\n } | src/fastify.js:78:5:78:11 | request |
101+
| src/fastify.js:76:17:80:3 | functio ... ms;\\n } | src/fastify.js:79:5:79:11 | request |
102+
| src/fastify.js:87:17:91:3 | functio ... ms;\\n } | src/fastify.js:88:5:88:11 | request |
103+
| src/fastify.js:87:17:91:3 | functio ... ms;\\n } | src/fastify.js:89:5:89:11 | request |
104+
| src/fastify.js:87:17:91:3 | functio ... ms;\\n } | src/fastify.js:90:5:90:11 | request |
61105
test_ResponseSendArgument
62106
| src/fastify.js:6:12:6:29 | { hello: "world" } | src/fastify.js:5:17:7:3 | async ( ... nse\\n } |
63107
| src/fastify.js:27:16:27:33 | { hello: "world" } | src/fastify.js:26:17:28:3 | (reques ... nse\\n } |

0 commit comments

Comments
 (0)