Merge master into next.

As of 2846d80f1c.
This commit is contained in:
Aditya Sharad
2018-11-06 11:52:51 +00:00
105 changed files with 3462 additions and 1462 deletions

View File

@@ -163,6 +163,12 @@ predicate whitelisted(UnusedLocal v) {
isEnumMember(vd) or
// ignore ambient declarations - too noisy
vd.isAmbient()
) or
exists (DirectEval eval |
// eval nearby
eval.getEnclosingFunction() = v.getADeclaration().getEnclosingFunction() and
// ... but not on the RHS
not v.getAnAssignedExpr() = eval
)
}

View File

@@ -105,7 +105,7 @@ class AMDModuleDefinition extends CallExpr {
* parameters `pdep1` and `pdep2` correspond to dependencies
* `dep1` and `dep2`.
*/
private SimpleParameter getDependencyParameter(string name) {
Parameter getDependencyParameter(string name) {
exists (PathExpr dep |
dependencyParameter(dep, result) and
dep.getValue() = name

View File

@@ -418,11 +418,24 @@ private class BindPartialCall extends AdditionalPartialInvokeNode, DataFlow::Met
}
/**
* A partial call through `_.partial` or a function with a similar interface.
* A partial call through `_.partial`.
*/
private class LibraryPartialCall extends AdditionalPartialInvokeNode {
LibraryPartialCall() {
this = LodashUnderscore::member("partial").getACall() or
private class LodashPartialCall extends AdditionalPartialInvokeNode {
LodashPartialCall() {
this = LodashUnderscore::member("partial").getACall()
}
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
callback = getArgument(0) and
argument = getArgument(index+1)
}
}
/**
* A partial call through `ramda.partial`.
*/
private class RamdaPartialCall extends AdditionalPartialInvokeNode {
RamdaPartialCall() {
this = DataFlow::moduleMember("ramda", "partial").getACall()
}

View File

@@ -399,10 +399,8 @@ class ModuleImportNode extends DataFlow::DefaultSourceNode {
)
or
// declared AMD dependency
exists (AMDModuleDefinition amd, PathExpr dep, Parameter p |
amd.dependencyParameter(dep, p) and
path = dep.getValue() and
this = DataFlow::parameterNode(p)
exists (AMDModuleDefinition amd |
this = DataFlow::parameterNode(amd.getDependencyParameter(path))
)
or
// AMD require

View File

@@ -6,6 +6,7 @@
import javascript
import SyntacticHeuristics
private import semmle.javascript.security.dataflow.CommandInjection
/**
* A heuristic source of data flow in a security query.
@@ -26,3 +27,13 @@ private class RemoteFlowPassword extends HeuristicSource, RemoteFlowSource {
}
}
/**
* A use of `JSON.stringify`, viewed as a source for command line injections
* since it does not properly escape single quotes and dollar symbols.
*/
private class JSONStringifyAsCommandInjectionSource extends HeuristicSource, CommandInjection::Source {
JSONStringifyAsCommandInjectionSource() {
this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify")
}
}

View File

@@ -16,6 +16,10 @@
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |
| promises.js:11:22:11:31 | "resolved" | promises.js:27:16:27:16 | v |

View File

@@ -17,6 +17,10 @@
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |
| promises.js:11:22:11:31 | "resolved" | promises.js:27:16:27:16 | v |

View File

@@ -19,6 +19,10 @@
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:7:13:7:18 | nj.foo |
| nodeJsLib.js:2:15:2:23 | "tainted" | esClient.js:10:13:10:17 | njFoo |
| nodeJsLib.js:2:15:2:23 | "tainted" | nodeJsClient.js:4:13:4:18 | nj.foo |
| partial.js:5:15:5:24 | "tainted1" | partial.js:9:15:9:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:15:15:15:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:21:15:21:15 | x |
| partial.js:5:15:5:24 | "tainted1" | partial.js:27:15:27:15 | x |
| promises.js:2:16:2:24 | "tainted" | promises.js:7:16:7:18 | val |
| promises.js:2:16:2:24 | "tainted" | promises.js:38:32:38:32 | v |
| promises.js:11:22:11:31 | "resolved" | promises.js:19:20:19:20 | v |

View File

@@ -0,0 +1,30 @@
let underscore = require('underscore');
let lodash = require('lodash');
let R = require('ramda');
let source1 = "tainted1";
let source2 = "tainted2";
function f1(x, y) {
let sink1 = x;
let sink2 = y;
}
f1.bind(null, source1)(source2);
function f2(x, y) {
let sink1 = x;
let sink2 = y;
}
underscore.partial(f2, source1)(source2);
function f3(x, y) {
let sink1 = x;
let sink2 = y;
}
lodash.partial(f3, source1)(source2);
function f4(x, y) {
let sink1 = x;
let sink2 = y;
}
R.partial(f4, [source1])(source2);

View File

@@ -1,2 +1,3 @@
| additionalCommandInjections.js:2:28:2:35 | password |
| sources.js:2:5:2:12 | password |
| sources.js:3:5:3:20 | JSON.stringify() |

View File

@@ -1,3 +1,4 @@
(function() {
password;
JSON.stringify();
})();

View File

@@ -1,6 +1,8 @@
| Babelrc/importPragma.jsx:2:1:2:27 | import ... react'; | Unused import q. |
| decorated.ts:1:1:1:126 | import ... where'; | Unused import actionHandler. |
| decorated.ts:4:10:4:12 | fun | Unused function fun. |
| eval.js:10:9:10:24 | not_used_by_eval | Unused variable not_used_by_eval. |
| eval.js:19:9:19:24 | not_used_by_eval | Unused variable not_used_by_eval. |
| externs.js:6:5:6:13 | iAmUnused | Unused variable iAmUnused. |
| importWithoutPragma.jsx:1:1:1:27 | import ... react'; | Unused import h. |
| multi-imports.js:1:1:1:29 | import ... om 'x'; | Unused imports a, b, d. |

View File

@@ -0,0 +1,20 @@
(function(){
var used_by_eval = f();
eval(src);
});
(function(){
eval(src);
var used_by_eval = f();
});
(function(){
var not_used_by_eval = f();
(function(){
eval(src);
})
});
(function(){
(function(){
eval(src);
})
var not_used_by_eval = f();
});

View File

@@ -3,8 +3,8 @@
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

View File

@@ -16,10 +16,10 @@ edges
| partial.js:13:42:13:48 | req.url | partial.js:9:25:9:25 | x |
| partial.js:18:25:18:25 | x | partial.js:19:14:19:14 | x |
| partial.js:19:14:19:14 | x | partial.js:19:14:19:18 | x + y |
| partial.js:22:52:22:58 | req.url | partial.js:18:25:18:25 | x |
| partial.js:22:51:22:57 | req.url | partial.js:18:25:18:25 | x |
| partial.js:27:25:27:25 | x | partial.js:28:14:28:14 | x |
| partial.js:28:14:28:14 | x | partial.js:28:14:28:18 | x + y |
| partial.js:31:48:31:54 | req.url | partial.js:27:25:27:25 | x |
| partial.js:31:47:31:53 | req.url | partial.js:27:25:27:25 | x |
| partial.js:36:25:36:25 | x | partial.js:37:14:37:14 | x |
| partial.js:37:14:37:14 | x | partial.js:37:14:37:18 | x + y |
| partial.js:40:43:40:49 | req.url | partial.js:36:25:36:25 | x |
@@ -38,8 +38,8 @@ edges
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |

View File

@@ -2,8 +2,8 @@
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

View File

@@ -6,8 +6,8 @@ WARNING: Type XssDataFlowConfiguration has been deprecated and may be removed in
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |

View File

@@ -19,7 +19,7 @@ app.get("/underscore", (req, res) => {
res.send(x + y); // NOT OK
}
let callback = underscore.partial(sendResponse, [req.url]);
let callback = underscore.partial(sendResponse, req.url);
[1, 2, 3].forEach(callback);
});
@@ -28,7 +28,7 @@ app.get("/lodash", (req, res) => {
res.send(x + y); // NOT OK
}
let callback = lodash.partial(sendResponse, [req.url]);
let callback = lodash.partial(sendResponse, req.url);
[1, 2, 3].forEach(callback);
});