Skip to content

Commit 2bb9636

Browse files
authored
Merge pull request #4868 from erik-krogh/boundShell
Approved by esbena
2 parents 7c6b4d7 + da9a4e5 commit 2bb9636

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,11 @@ module DataFlow {
628628
override string getPropertyName() { result = astNode.getArgument(1).getStringValue() }
629629

630630
override Node getRhs() {
631-
result = astNode.getArgument(2).(ObjectExpr).getPropertyByName("value").getInit().flow()
631+
exists(ObjectExpr obj | obj = astNode.getArgument(2) |
632+
result = obj.getPropertyByName("value").getInit().flow()
633+
or
634+
result = obj.getPropertyByName("get").getInit().flow().(DataFlow::FunctionNode).getAReturn()
635+
)
632636
}
633637

634638
override ControlFlowNode getWriteNode() { result = astNode }

javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ module UnsafeShellCommandConstruction {
5151
*/
5252
class ExternalInputSource extends Source, DataFlow::ParameterNode {
5353
ExternalInputSource() {
54-
this =
55-
Exports::getAValueExportedBy(Exports::getTopmostPackageJSON())
56-
.getAFunctionValue()
57-
.getAParameter() and
54+
exists(int bound, DataFlow::FunctionNode func |
55+
func =
56+
Exports::getAValueExportedBy(Exports::getTopmostPackageJSON())
57+
.getABoundFunctionValue(bound) and
58+
this = func.getParameter(any(int arg | arg >= bound))
59+
) and
5860
not this.getName() = ["cmd", "command"] // looks to be on purpose.
5961
}
6062
}

javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ nodes
191191
| lib/lib.js:340:22:340:26 | id(n) |
192192
| lib/lib.js:340:22:340:26 | id(n) |
193193
| lib/lib.js:340:25:340:25 | n |
194+
| lib/lib.js:343:29:343:34 | unsafe |
195+
| lib/lib.js:343:29:343:34 | unsafe |
196+
| lib/lib.js:345:22:345:27 | unsafe |
197+
| lib/lib.js:345:22:345:27 | unsafe |
194198
edges
195199
| lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name |
196200
| lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name |
@@ -417,6 +421,10 @@ edges
417421
| lib/lib.js:339:39:339:39 | n | lib/lib.js:340:25:340:25 | n |
418422
| lib/lib.js:340:25:340:25 | n | lib/lib.js:340:22:340:26 | id(n) |
419423
| lib/lib.js:340:25:340:25 | n | lib/lib.js:340:22:340:26 | id(n) |
424+
| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe |
425+
| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe |
426+
| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe |
427+
| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe |
420428
#select
421429
| lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command |
422430
| lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command |
@@ -472,3 +480,4 @@ edges
472480
| lib/lib.js:320:11:320:26 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name | $@ based on library input is later used in $@. | lib/lib.js:320:11:320:26 | "rm -rf " + name | String concatenation | lib/lib.js:320:3:320:27 | cp.exec ... + name) | shell command |
473481
| lib/lib.js:325:12:325:51 | "MyWind ... " + arg | lib/lib.js:324:40:324:42 | arg | lib/lib.js:325:49:325:51 | arg | $@ based on library input is later used in $@. | lib/lib.js:325:12:325:51 | "MyWind ... " + arg | String concatenation | lib/lib.js:326:2:326:13 | cp.exec(cmd) | shell command |
474482
| lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | lib/lib.js:339:39:339:39 | n | lib/lib.js:340:22:340:26 | id(n) | $@ based on library input is later used in $@. | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | String concatenation | lib/lib.js:340:2:340:27 | cp.exec ... id(n)) | shell command |
483+
| lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | $@ based on library input is later used in $@. | lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | String concatenation | lib/lib.js:345:2:345:28 | cp.exec ... unsafe) | shell command |

javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,14 @@ module.exports.unproblematic = function() {
339339
module.exports.problematic = function(n) {
340340
cp.exec("rm -rf " + id(n)); // NOT OK
341341
};
342+
343+
function boundProblem(safe, unsafe) {
344+
cp.exec("rm -rf " + safe); // OK
345+
cp.exec("rm -rf " + unsafe); // NOT OK
346+
}
347+
348+
Object.defineProperty(module.exports, "boundProblem", {
349+
get: function () {
350+
return boundProblem.bind(this, "safe");
351+
}
352+
});

0 commit comments

Comments
 (0)