Skip to content

Commit f462c9b

Browse files
committed
add taint through the parseqs library
1 parent bec1818 commit f462c9b

File tree

4 files changed

+120
-1
lines changed

4 files changed

+120
-1
lines changed

javascript/change-notes/2021-07-14-querystring.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ lgtm,codescanning
22
* The security queries now track taint through more query string parsers.
33
Affected packages are
44
[qs](https://npmjs.com/package/qs),
5-
[normailize-url](https://npmjs.com/package/normalize-url)
5+
[normailize-url](https://npmjs.com/package/normalize-url),
6+
[parseqs](https://npmjs.com/package/parseqs)

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,19 @@ private class NormalizeUrlStep extends TaintTracking::SharedTaintStep {
291291
}
292292
}
293293

294+
/**
295+
* A taint step through a call to [parseqs](https://npmjs.com/package/parseqs).
296+
*/
297+
private class ParseQsStep extends TaintTracking::SharedTaintStep {
298+
override predicate uriStep(DataFlow::Node pred, DataFlow::Node succ) {
299+
exists(API::CallNode call |
300+
call = API::moduleImport("parseqs").getMember(["encode", "decode"]).getACall() and
301+
pred = call.getArgument(0) and
302+
succ = call
303+
)
304+
}
305+
}
306+
294307
/**
295308
* Provides steps for the `goog.Uri` class in the closure library.
296309
*/

javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,44 @@ nodes
13771377
| TaintedPath.js:204:51:204:57 | req.url |
13781378
| TaintedPath.js:204:51:204:57 | req.url |
13791379
| TaintedPath.js:204:51:204:57 | req.url |
1380+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1381+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1382+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1383+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1384+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1385+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1386+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1387+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1388+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1389+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1390+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1391+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1392+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1393+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1394+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1395+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
1396+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1397+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1398+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1399+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1400+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1401+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1402+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1403+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1404+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1405+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1406+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1407+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1408+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1409+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1410+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1411+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1412+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
1413+
| TaintedPath.js:206:44:206:50 | req.url |
1414+
| TaintedPath.js:206:44:206:50 | req.url |
1415+
| TaintedPath.js:206:44:206:50 | req.url |
1416+
| TaintedPath.js:206:44:206:50 | req.url |
1417+
| TaintedPath.js:206:44:206:50 | req.url |
13801418
| normalizedPaths.js:11:7:11:27 | path |
13811419
| normalizedPaths.js:11:7:11:27 | path |
13821420
| normalizedPaths.js:11:7:11:27 | path |
@@ -5790,6 +5828,70 @@ edges
57905828
| TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:38:204:58 | normali ... eq.url) |
57915829
| TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:38:204:58 | normali ... eq.url) |
57925830
| TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:38:204:58 | normali ... eq.url) |
5831+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5832+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5833+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5834+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5835+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5836+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5837+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5838+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5839+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5840+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5841+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5842+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5843+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5844+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5845+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5846+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5847+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5848+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5849+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5850+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5851+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5852+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5853+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5854+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5855+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5856+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5857+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5858+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5859+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5860+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5861+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5862+
| TaintedPath.js:206:29:206:51 | parseqs ... eq.url) | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo |
5863+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5864+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5865+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5866+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5867+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5868+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5869+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5870+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5871+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5872+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5873+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5874+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5875+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5876+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5877+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5878+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5879+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5880+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5881+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5882+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5883+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5884+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5885+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5886+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5887+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5888+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5889+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5890+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5891+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5892+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5893+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
5894+
| TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:51 | parseqs ... eq.url) |
57935895
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
57945896
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
57955897
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
@@ -8913,6 +9015,7 @@ edges
89139015
| TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value |
89149016
| TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | TaintedPath.js:203:38:203:44 | req.url | TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | This path depends on $@. | TaintedPath.js:203:38:203:44 | req.url | a user-provided value |
89159017
| TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | This path depends on $@. | TaintedPath.js:204:51:204:57 | req.url | a user-provided value |
9018+
| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | This path depends on $@. | TaintedPath.js:206:44:206:50 | req.url | a user-provided value |
89169019
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
89179020
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
89189021
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |

javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,6 @@ var server = http.createServer(function(req, res) {
202202
const qs = require("qs");
203203
res.write(fs.readFileSync(qs.parse(req.url).foo)); // NOT OK
204204
res.write(fs.readFileSync(qs.parse(normalizeUrl(req.url)).foo)); // NOT OK
205+
const parseqs = require("parseqs");
206+
res.write(fs.readFileSync(parseqs.decode(req.url).foo)); // NOT OK
205207
});

0 commit comments

Comments
 (0)