Skip to content

Commit 060b98d

Browse files
committed
JS: enchance middleware taint tracking via local source
1 parent da21a06 commit 060b98d

File tree

3 files changed

+11
-3
lines changed

3 files changed

+11
-3
lines changed

javascript/ql/lib/semmle/javascript/Routing.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ module Routing {
925925
private DataFlow::Node getAnAccessPathRhs(Node base, int n, string path) {
926926
// Assigned in the body of a route handler function, which is a middleware
927927
exists(RouteHandler handler | base = handler |
928-
result = AccessPath::getAnAssignmentTo(handler.getParameter(n).ref(), path) and
928+
result = AccessPath::getAnAssignmentTo(handler.getParameter(n).ref(), path).getALocalSource() and
929929
(
930930
exists(handler.getAContinuationInvocation())
931931
or

javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
| apollo.serverSide.ts:8:39:8:64 | get(fil ... => {}) | apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:8:43:8:50 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:8:43:8:50 | file.url | URL | apollo.serverSide.ts:7:36:7:44 | { files } | user-provided value |
77
| apollo.serverSide.ts:18:37:18:62 | get(fil ... => {}) | apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:18:41:18:48 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:18:41:18:48 | file.url | URL | apollo.serverSide.ts:17:34:17:42 | { files } | user-provided value |
88
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | The $@ of this request depends on a $@. | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | endpoint | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | user-provided value |
9+
| serverSide2.js:17:28:17:47 | axios.get(targetUrl) | serverSide2.js:10:25:10:31 | req.url | serverSide2.js:17:38:17:46 | targetUrl | The $@ of this request depends on a $@. | serverSide2.js:17:38:17:46 | targetUrl | URL | serverSide2.js:10:25:10:31 | req.url | user-provided value |
910
| serverSide2.js:20:29:20:49 | axios.g ... etUrl1) | serverSide2.js:9:43:9:56 | req._parsedUrl | serverSide2.js:20:39:20:48 | targetUrl1 | The $@ of this request depends on a $@. | serverSide2.js:20:39:20:48 | targetUrl1 | URL | serverSide2.js:9:43:9:56 | req._parsedUrl | user-provided value |
1011
| serverSide2.js:23:29:23:49 | axios.g ... etUrl2) | serverSide2.js:22:24:22:30 | req.url | serverSide2.js:23:39:23:48 | targetUrl2 | The $@ of this request depends on a $@. | serverSide2.js:23:39:23:48 | targetUrl2 | URL | serverSide2.js:22:24:22:30 | req.url | user-provided value |
1112
| serverSide2.js:26:29:26:49 | axios.g ... etUrl3) | serverSide2.js:11:24:11:30 | req.url | serverSide2.js:26:39:26:48 | targetUrl3 | The $@ of this request depends on a $@. | serverSide2.js:26:39:26:48 | targetUrl3 | URL | serverSide2.js:11:24:11:30 | req.url | user-provided value |
@@ -66,7 +67,10 @@ edges
6667
| axiosInterceptors.serverSide.js:20:23:20:25 | url | axiosInterceptors.serverSide.js:20:5:20:25 | userProvidedUrl | provenance | |
6768
| serverSide2.js:9:34:9:63 | qs.pars ... .query) | serverSide2.js:19:24:19:51 | req.par ... rsedUrl | provenance | |
6869
| serverSide2.js:9:43:9:56 | req._parsedUrl | serverSide2.js:9:34:9:63 | qs.pars ... .query) | provenance | |
70+
| serverSide2.js:10:25:10:31 | req.url | serverSide2.js:16:23:16:41 | req.parsedQuery.url | provenance | |
6971
| serverSide2.js:11:24:11:30 | req.url | serverSide2.js:25:24:25:41 | req.SomeObject.url | provenance | |
72+
| serverSide2.js:16:11:16:41 | targetUrl | serverSide2.js:17:38:17:46 | targetUrl | provenance | |
73+
| serverSide2.js:16:23:16:41 | req.parsedQuery.url | serverSide2.js:16:11:16:41 | targetUrl | provenance | |
7074
| serverSide2.js:19:11:19:55 | targetUrl1 | serverSide2.js:20:39:20:48 | targetUrl1 | provenance | |
7175
| serverSide2.js:19:24:19:51 | req.par ... rsedUrl | serverSide2.js:19:11:19:55 | targetUrl1 | provenance | |
7276
| serverSide2.js:22:11:22:36 | targetUrl2 | serverSide2.js:23:39:23:48 | targetUrl2 | provenance | |
@@ -167,7 +171,11 @@ nodes
167171
| axiosInterceptors.serverSide.js:20:23:20:25 | url | semmle.label | url |
168172
| serverSide2.js:9:34:9:63 | qs.pars ... .query) | semmle.label | qs.pars ... .query) |
169173
| serverSide2.js:9:43:9:56 | req._parsedUrl | semmle.label | req._parsedUrl |
174+
| serverSide2.js:10:25:10:31 | req.url | semmle.label | req.url |
170175
| serverSide2.js:11:24:11:30 | req.url | semmle.label | req.url |
176+
| serverSide2.js:16:11:16:41 | targetUrl | semmle.label | targetUrl |
177+
| serverSide2.js:16:23:16:41 | req.parsedQuery.url | semmle.label | req.parsedQuery.url |
178+
| serverSide2.js:17:38:17:46 | targetUrl | semmle.label | targetUrl |
171179
| serverSide2.js:19:11:19:55 | targetUrl1 | semmle.label | targetUrl1 |
172180
| serverSide2.js:19:24:19:51 | req.par ... rsedUrl | semmle.label | req.par ... rsedUrl |
173181
| serverSide2.js:20:39:20:48 | targetUrl1 | semmle.label | targetUrl1 |

javascript/ql/test/query-tests/Security/CWE-918/serverSide2.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ const PORT = 3000;
77

88
app.use((req, res, next) => {
99
req.parsedQueryFromParsedUrl = qs.parse(req._parsedUrl.query); // $Source[js/request-forgery]
10-
req.parsedQuery.url = req.url || {}; // $MISSING:Source[js/request-forgery]
10+
req.parsedQuery.url = req.url || {}; // $Source[js/request-forgery]
1111
req.SomeObject.url = req.url; // $Source[js/request-forgery]
1212
next();
1313
});
1414

1515
app.get('/proxy', async (req, res) => {
1616
const targetUrl = req.parsedQuery.url;
17-
const response = await axios.get(targetUrl); // $MISSING:Alert[js/request-forgery]
17+
const response = await axios.get(targetUrl); // $Alert[js/request-forgery]
1818

1919
const targetUrl1 = req.parsedQueryFromParsedUrl.url;
2020
const response1 = await axios.get(targetUrl1); // $Alert[js/request-forgery]

0 commit comments

Comments
 (0)