Skip to content

Commit 0883346

Browse files
authored
Merge pull request #386 from xiemaisi/js/lodash_partial
Approved by esben-semmle
2 parents 86b3f01 + c75d785 commit 0883346

File tree

11 files changed

+72
-17
lines changed

11 files changed

+72
-17
lines changed

change-notes/1.19/analysis-javascript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features:
1010
- file system access, for example through [fs-extra](https://github.com/jprichardson/node-fs-extra) or [globby](https://www.npmjs.com/package/globby)
1111
- outbound network access, for example through the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
12-
- the [Google Cloud Spanner](https://cloud.google.com/spanner) database
12+
- the [Google Cloud Spanner](https://cloud.google.com/spanner), [lodash](https://lodash.com) and [underscore](https://underscorejs.org/) libraries
1313

1414
* The type inference now handles nested imports (that is, imports not appearing at the toplevel). This may yield fewer false-positive results on projects that use this non-standard language feature.
1515

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,24 @@ private class BindPartialCall extends AdditionalPartialInvokeNode, DataFlow::Met
418418
}
419419

420420
/**
421-
* A partial call through `_.partial` or a function with a similar interface.
421+
* A partial call through `_.partial`.
422422
*/
423-
private class LibraryPartialCall extends AdditionalPartialInvokeNode {
424-
LibraryPartialCall() {
425-
this = LodashUnderscore::member("partial").getACall() or
423+
private class LodashPartialCall extends AdditionalPartialInvokeNode {
424+
LodashPartialCall() {
425+
this = LodashUnderscore::member("partial").getACall()
426+
}
427+
428+
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
429+
callback = getArgument(0) and
430+
argument = getArgument(index+1)
431+
}
432+
}
433+
434+
/**
435+
* A partial call through `ramda.partial`.
436+
*/
437+
private class RamdaPartialCall extends AdditionalPartialInvokeNode {
438+
RamdaPartialCall() {
426439
this = DataFlow::moduleMember("ramda", "partial").getACall()
427440
}
428441

javascript/ql/test/library-tests/InterProceduralFlow/DataFlow.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
1717
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
1818
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
19+
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
20+
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
21+
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
22+
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
1923
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
2024
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |
2125
| promises.js:11:22:11:31 | "resolved" | promises.js:27:16:27:16 | v |

javascript/ql/test/library-tests/InterProceduralFlow/GermanFlow.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
1818
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
1919
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
20+
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
21+
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
22+
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
23+
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
2024
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
2125
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |
2226
| promises.js:11:22:11:31 | "resolved" | promises.js:27:16:27:16 | v |

javascript/ql/test/library-tests/InterProceduralFlow/TaintTracking.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
2020
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
2121
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
22+
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
23+
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
24+
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
25+
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
2226
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
2327
| promises.js:2:16:2:24 | "tainted" | promises.js:38:32:38:32 | v |
2428
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
let underscore = require('underscore');
2+
let lodash = require('lodash');
3+
let R = require('ramda');
4+
5+
let source1 = "tainted1";
6+
let source2 = "tainted2";
7+
8+
function f1(x, y) {
9+
let sink1 = x;
10+
let sink2 = y;
11+
}
12+
f1.bind(null, source1)(source2);
13+
14+
function f2(x, y) {
15+
let sink1 = x;
16+
let sink2 = y;
17+
}
18+
underscore.partial(f2, source1)(source2);
19+
20+
function f3(x, y) {
21+
let sink1 = x;
22+
let sink2 = y;
23+
}
24+
lodash.partial(f3, source1)(source2);
25+
26+
function f4(x, y) {
27+
let sink1 = x;
28+
let sink2 = y;
29+
}
30+
R.partial(f4, [source1])(source2);

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
44
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
55
| partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
6-
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:52:22:58 | req.url | user-provided value |
7-
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:48:31:54 | req.url | user-provided value |
6+
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
7+
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
88
| partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
99
| promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
1010
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.expected

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ edges
1616
| partial.js:13:42:13:48 | req.url | partial.js:9:25:9:25 | x |
1717
| partial.js:18:25:18:25 | x | partial.js:19:14:19:14 | x |
1818
| partial.js:19:14:19:14 | x | partial.js:19:14:19:18 | x + y |
19-
| partial.js:22:52:22:58 | req.url | partial.js:18:25:18:25 | x |
19+
| partial.js:22:51:22:57 | req.url | partial.js:18:25:18:25 | x |
2020
| partial.js:27:25:27:25 | x | partial.js:28:14:28:14 | x |
2121
| partial.js:28:14:28:14 | x | partial.js:28:14:28:18 | x + y |
22-
| partial.js:31:48:31:54 | req.url | partial.js:27:25:27:25 | x |
22+
| partial.js:31:47:31:53 | req.url | partial.js:27:25:27:25 | x |
2323
| partial.js:36:25:36:25 | x | partial.js:37:14:37:14 | x |
2424
| partial.js:37:14:37:14 | x | partial.js:37:14:37:18 | x + y |
2525
| partial.js:40:43:40:49 | req.url | partial.js:36:25:36:25 | x |
@@ -38,8 +38,8 @@ edges
3838
| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
3939
| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
4040
| partial.js:10:14:10:18 | x + y | partial.js:13:42:13:48 | req.url | partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
41-
| partial.js:19:14:19:18 | x + y | partial.js:22:52:22:58 | req.url | partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:52:22:58 | req.url | user-provided value |
42-
| partial.js:28:14:28:18 | x + y | partial.js:31:48:31:54 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:48:31:54 | req.url | user-provided value |
41+
| partial.js:19:14:19:18 | x + y | partial.js:22:51:22:57 | req.url | partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
42+
| partial.js:28:14:28:18 | x + y | partial.js:31:47:31:53 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
4343
| partial.js:37:14:37:18 | x + y | partial.js:40:43:40:49 | req.url | partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
4444
| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
4545
| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssWithCustomSanitizer.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
33
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
44
| partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
5-
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:52:22:58 | req.url | user-provided value |
6-
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:48:31:54 | req.url | user-provided value |
5+
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
6+
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
77
| partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
88
| promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
99
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssWithCustomSanitizer_old.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ WARNING: Predicate flowsFrom has been deprecated and may be removed in future (R
66
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
77
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
88
| partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
9-
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:52:22:58 | req.url | user-provided value |
10-
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:48:31:54 | req.url | user-provided value |
9+
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
10+
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
1111
| partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
1212
| promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
1313
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

0 commit comments

Comments
 (0)