Skip to content

Commit b24c6fd

Browse files
committed
for demonstration
1 parent de2ee4d commit b24c6fd

File tree

2 files changed

+28
-19
lines changed
  • javascript/ql
    • lib/semmle/javascript/frameworks
    • test/query-tests/Security/CWE-078/CommandInjection

2 files changed

+28
-19
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Execa.qll

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ module Execa {
119119
}
120120
}
121121

122-
API::Node test() { result = API::moduleImport("execa").getMember("$").getASuccessor*() }
123-
124122
/**
125123
* The system command execution nodes for `execa.$` or `execa.$.sync` tag functions
126124
*/
@@ -131,16 +129,17 @@ module Execa {
131129

132130
override predicate isShellInterpreted(DataFlow::Node arg) {
133131
isExecaShellEnable(this.getParameter(0)) and
134-
arg = this.getParameter(0).asSink()
132+
arg = this.getAParameter().asSink()
135133
}
136134

137135
override DataFlow::Node getArgumentList() {
138-
result = this.getParameter(any(int i | i > 1)).asSink()
136+
result = this.getParameter(any(int i | i > 1)).asSink() and
137+
not exists(string s | this.getACall().getArgument(0).mayHaveStringValue(s) | s.matches(""))
139138
}
140139

141-
override predicate isSync() { isSync = true }
142-
143140
override DataFlow::Node getOptionsArg() { result = this.getParameter(0).asSink() }
141+
142+
override predicate isSync() { isSync = true }
144143
}
145144

146145
/**

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,32 @@ import url from 'url'
44

55
http.createServer(async function (req, res) {
66
let cmd = url.parse(req.url, true).query["cmd"][0];
7-
let arg = url.parse(req.url, true).query["arg"];
7+
let arg1 = url.parse(req.url, true).query["arg1"];
8+
let arg2 = url.parse(req.url, true).query["arg2"];
89

9-
await $`${cmd} ${arg}`; // NOT OK
10-
$.sync`${cmd} ${arg}`; // NOT OK
11-
await $({ shell: true })`${cmd} ${arg}` // NOT OK
12-
await $({ shell: false })`${cmd} ${arg}` // NOT OK
10+
await $`${cmd} ${arg1} ${arg2}`; // NOT OK
11+
await $`ssh ${arg1} ${arg2}`; // NOT OK
12+
$({ shell: false }).sync`${cmd} ${arg} ${arg} ${arg2}`; // NOT OK
13+
$({ shell: true }).sync`${cmd} ${arg} ${arg} ${arg2}`; // NOT OK
14+
$({ shell: false }).sync`ssh ${arg} ${arg} ${arg2}`; // NOT OK
1315

14-
await execa(cmd, [arg]); // NOT OK
16+
$.sync`${cmd} ${arg1} ${arg2}`; // NOT OK
17+
$.sync`ssh ${arg1} ${arg2}`; // NOT OK
18+
await $({ shell: true })`${cmd} ${arg1} ${arg2}` // NOT OK
19+
await $({ shell: false })`${cmd} ${arg1} ${arg2}` // NOT OK
20+
await $({ shell: false })`ssh ${arg1} ${arg2}` // NOT OK
21+
22+
await execa(cmd, [arg1]); // NOT OK
1523
await execa(cmd, { shell: true }); // NOT OK
1624
await execa(cmd, { shell: true }); // NOT OK
17-
await execa(cmd, [arg], { shell: true }); // NOT OK
18-
execaSync(cmd, [arg]); // NOT OK
19-
execaSync(cmd, [arg], { shell: true }); // NOT OK
25+
await execa(cmd, [arg1], { shell: true }); // NOT OK
26+
27+
execaSync(cmd, [arg1]); // NOT OK
28+
execaSync(cmd, [arg1], { shell: true }); // NOT OK
29+
30+
await execaCommand(cmd + arg1); // NOT OK
31+
await execaCommand(cmd + arg1, { shell: true }); // NOT OK
2032

21-
await execaCommand(cmd + arg); // NOT OK
22-
execaCommandSync(cmd + arg); // NOT OK
23-
await execaCommand(cmd + arg, { shell: true }); // NOT OK
24-
execaCommandSync(cmd + arg, { shell: true }); // NOT OK
33+
execaCommandSync(cmd + arg1); // NOT OK
34+
execaCommandSync(cmd + arg1, { shell: true }); // NOT OK
2535
});

0 commit comments

Comments
 (0)