mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
Merge branch 'main' into js/shared-dataflow
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
passingPositiveTests
|
||||
| PASSED | CommandInjection | tests.js:11:46:11:70 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:12:43:12:67 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:13:63:13:87 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:14:62:14:86 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:15:60:15:84 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:17:45:17:69 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:18:42:18:66 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:19:62:19:86 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:20:63:20:87 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:21:60:21:84 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:23:43:23:67 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:24:40:24:64 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:25:40:25:64 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:26:60:26:84 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:28:41:28:65 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:29:58:29:82 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:31:51:31:75 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:32:68:32:92 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:34:49:34:73 | // test ... jection |
|
||||
| PASSED | CommandInjection | tests.js:35:66:35:90 | // test ... jection |
|
||||
failingPositiveTests
|
||||
@@ -0,0 +1,36 @@
|
||||
import { execa, execaSync, execaCommand, execaCommandSync, $ } from 'execa';
|
||||
import http from 'node:http'
|
||||
import url from 'url'
|
||||
|
||||
http.createServer(async function (req, res) {
|
||||
let cmd = url.parse(req.url, true).query["cmd"][0];
|
||||
let arg1 = url.parse(req.url, true).query["arg1"];
|
||||
let arg2 = url.parse(req.url, true).query["arg2"];
|
||||
let arg3 = url.parse(req.url, true).query["arg3"];
|
||||
|
||||
await $`${cmd} ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
await $`ssh ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
$({ shell: false }).sync`${cmd} ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
$({ shell: true }).sync`${cmd} ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
$({ shell: false }).sync`ssh ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
|
||||
$.sync`${cmd} ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
$.sync`ssh ${arg1} ${arg2} ${arg3}`; // test: CommandInjection
|
||||
await $({ shell: true })`${cmd} ${arg1} ${arg2} ${arg3}` // test: CommandInjection
|
||||
await $({ shell: false })`${cmd} ${arg1} ${arg2} ${arg3}` // test: CommandInjection
|
||||
await $({ shell: false })`ssh ${arg1} ${arg2} ${arg3}` // test: CommandInjection
|
||||
|
||||
await execa(cmd, [arg1, arg2, arg3]); // test: CommandInjection
|
||||
await execa(cmd, { shell: true }); // test: CommandInjection
|
||||
await execa(cmd, { shell: true }); // test: CommandInjection
|
||||
await execa(cmd, [arg1, arg2, arg3], { shell: true }); // test: CommandInjection
|
||||
|
||||
execaSync(cmd, [arg1, arg2, arg3]); // test: CommandInjection
|
||||
execaSync(cmd, [arg1, arg2, arg3], { shell: true }); // test: CommandInjection
|
||||
|
||||
await execaCommand(cmd + arg1 + arg2 + arg3); // test: CommandInjection
|
||||
await execaCommand(cmd + arg1 + arg2 + arg3, { shell: true }); // test: CommandInjection
|
||||
|
||||
execaCommandSync(cmd + arg1 + arg2 + arg3); // test: CommandInjection
|
||||
execaCommandSync(cmd + arg1 + arg2 + arg3, { shell: true }); // test: CommandInjection
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import javascript
|
||||
|
||||
class InlineTest extends LineComment {
|
||||
string tests;
|
||||
|
||||
InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
|
||||
|
||||
string getPositiveTest() {
|
||||
result = tests.trim().splitAt(",").trim() and not result.matches("!%")
|
||||
}
|
||||
|
||||
predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
|
||||
|
||||
predicate inNode(DataFlow::Node n) {
|
||||
this.getLocation().getFile() = n.getFile() and
|
||||
this.getLocation().getStartLine() = n.getStartLine()
|
||||
}
|
||||
}
|
||||
|
||||
import experimental.semmle.javascript.Execa
|
||||
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "CommandInjection" and
|
||||
exists(SystemCommandExecution n |
|
||||
t.inNode(n.getArgumentList()) or t.inNode(n.getACommandArgument())
|
||||
)
|
||||
}
|
||||
|
||||
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "CommandInjection" and
|
||||
not exists(SystemCommandExecution n |
|
||||
t.inNode(n.getArgumentList()) or t.inNode(n.getACommandArgument())
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
passingPositiveTests
|
||||
| PASSED | PathInjection | tests.js:9:43:9:64 | // test ... jection |
|
||||
| PASSED | PathInjection | tests.js:12:50:12:71 | // test ... jection |
|
||||
| PASSED | PathInjection | tests.js:15:61:15:82 | // test ... jection |
|
||||
| PASSED | PathInjection | tests.js:18:73:18:94 | // test ... jection |
|
||||
failingPositiveTests
|
||||
19
javascript/ql/test/experimental/Execa/PathInjection/tests.js
Normal file
19
javascript/ql/test/experimental/Execa/PathInjection/tests.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { execa, $ } from 'execa';
|
||||
import http from 'node:http'
|
||||
import url from 'url'
|
||||
|
||||
http.createServer(async function (req, res) {
|
||||
let filePath = url.parse(req.url, true).query["filePath"][0];
|
||||
|
||||
// Piping to stdin from a file
|
||||
await $({ inputFile: filePath })`cat` // test: PathInjection
|
||||
|
||||
// Piping to stdin from a file
|
||||
await execa('cat', { inputFile: filePath }); // test: PathInjection
|
||||
|
||||
// Piping Stdout to file
|
||||
await execa('echo', ['example3']).pipeStdout(filePath); // test: PathInjection
|
||||
|
||||
// Piping all of command output to file
|
||||
await execa('echo', ['example4'], { all: true }).pipeAll(filePath); // test: PathInjection
|
||||
});
|
||||
34
javascript/ql/test/experimental/Execa/PathInjection/tests.ql
Normal file
34
javascript/ql/test/experimental/Execa/PathInjection/tests.ql
Normal file
@@ -0,0 +1,34 @@
|
||||
import javascript
|
||||
|
||||
class InlineTest extends LineComment {
|
||||
string tests;
|
||||
|
||||
InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
|
||||
|
||||
string getPositiveTest() {
|
||||
result = tests.trim().splitAt(",").trim() and not result.matches("!%")
|
||||
}
|
||||
|
||||
predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
|
||||
|
||||
predicate inNode(DataFlow::Node n) {
|
||||
this.getLocation().getFile() = n.getFile() and
|
||||
this.getLocation().getStartLine() = n.getStartLine()
|
||||
}
|
||||
}
|
||||
|
||||
import experimental.semmle.javascript.Execa
|
||||
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "PathInjection" and
|
||||
exists(FileSystemReadAccess n | t.inNode(n.getAPathArgument()))
|
||||
}
|
||||
|
||||
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "PathInjection" and
|
||||
not exists(FileSystemReadAccess n | t.inNode(n.getAPathArgument()))
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
nodes
|
||||
| busybus.js:9:30:9:33 | file |
|
||||
| busybus.js:9:30:9:33 | file |
|
||||
| busybus.js:9:36:9:39 | info |
|
||||
| busybus.js:9:36:9:39 | info |
|
||||
| busybus.js:10:19:10:50 | { filen ... eType } |
|
||||
| busybus.js:10:19:10:57 | encoding |
|
||||
| busybus.js:10:19:10:57 | filename |
|
||||
| busybus.js:10:19:10:57 | mimeType |
|
||||
| busybus.js:10:21:10:28 | filename |
|
||||
| busybus.js:10:31:10:38 | encoding |
|
||||
| busybus.js:10:41:10:48 | mimeType |
|
||||
| busybus.js:10:54:10:57 | info |
|
||||
| busybus.js:12:18:12:25 | filename |
|
||||
| busybus.js:12:18:12:25 | filename |
|
||||
| busybus.js:12:28:12:35 | encoding |
|
||||
| busybus.js:12:28:12:35 | encoding |
|
||||
| busybus.js:12:38:12:45 | mimeType |
|
||||
| busybus.js:12:38:12:45 | mimeType |
|
||||
| busybus.js:13:23:13:23 | z |
|
||||
| busybus.js:13:31:13:36 | sink() |
|
||||
| busybus.js:13:31:13:36 | sink() |
|
||||
| busybus.js:15:30:15:33 | data |
|
||||
| busybus.js:15:30:15:33 | data |
|
||||
| busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:22:25:22:42 | data |
|
||||
| busybus.js:22:32:22:42 | this.read() |
|
||||
| busybus.js:22:32:22:42 | this.read() |
|
||||
| busybus.js:23:26:23:29 | data |
|
||||
| busybus.js:23:26:23:29 | data |
|
||||
| busybus.js:27:25:27:28 | name |
|
||||
| busybus.js:27:25:27:28 | name |
|
||||
| busybus.js:27:31:27:33 | val |
|
||||
| busybus.js:27:31:27:33 | val |
|
||||
| busybus.js:27:36:27:39 | info |
|
||||
| busybus.js:27:36:27:39 | info |
|
||||
| busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:28:29:28:32 | info |
|
||||
| busybus.js:28:29:28:32 | info |
|
||||
| dicer.js:12:23:12:26 | part |
|
||||
| dicer.js:12:23:12:26 | part |
|
||||
| dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:14:28:14:33 | header |
|
||||
| dicer.js:14:28:14:33 | header |
|
||||
| dicer.js:16:22:16:27 | header |
|
||||
| dicer.js:16:22:16:30 | header[h] |
|
||||
| dicer.js:16:22:16:30 | header[h] |
|
||||
| dicer.js:19:26:19:29 | data |
|
||||
| dicer.js:19:26:19:29 | data |
|
||||
| dicer.js:20:18:20:21 | data |
|
||||
| dicer.js:20:18:20:21 | data |
|
||||
| formidable.js:7:11:7:25 | [fields, files] |
|
||||
| formidable.js:7:11:7:49 | fields |
|
||||
| formidable.js:7:11:7:49 | files |
|
||||
| formidable.js:7:12:7:17 | fields |
|
||||
| formidable.js:7:20:7:24 | files |
|
||||
| formidable.js:7:29:7:49 | await f ... se(req) |
|
||||
| formidable.js:7:35:7:49 | form.parse(req) |
|
||||
| formidable.js:7:35:7:49 | form.parse(req) |
|
||||
| formidable.js:8:10:8:15 | fields |
|
||||
| formidable.js:8:10:8:15 | fields |
|
||||
| formidable.js:8:18:8:22 | files |
|
||||
| formidable.js:8:18:8:22 | files |
|
||||
| formidable.js:9:27:9:34 | formname |
|
||||
| formidable.js:9:27:9:34 | formname |
|
||||
| formidable.js:9:37:9:40 | file |
|
||||
| formidable.js:9:37:9:40 | file |
|
||||
| formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:12:22:12:29 | formname |
|
||||
| formidable.js:12:22:12:29 | formname |
|
||||
| formidable.js:12:32:12:35 | file |
|
||||
| formidable.js:12:32:12:35 | file |
|
||||
| formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:15:23:15:31 | fieldName |
|
||||
| formidable.js:15:23:15:31 | fieldName |
|
||||
| formidable.js:15:34:15:43 | fieldValue |
|
||||
| formidable.js:15:34:15:43 | fieldValue |
|
||||
| formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:16:25:16:34 | fieldValue |
|
||||
| formidable.js:16:25:16:34 | fieldValue |
|
||||
| multiparty.js:8:22:8:25 | part |
|
||||
| multiparty.js:8:22:8:25 | part |
|
||||
| multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:14:37:14:42 | fields |
|
||||
| multiparty.js:14:37:14:42 | fields |
|
||||
| multiparty.js:14:45:14:49 | files |
|
||||
| multiparty.js:14:45:14:49 | files |
|
||||
| multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:15:22:15:26 | files |
|
||||
| multiparty.js:15:22:15:26 | files |
|
||||
edges
|
||||
| busybus.js:9:30:9:33 | file | busybus.js:13:23:13:23 | z |
|
||||
| busybus.js:9:30:9:33 | file | busybus.js:13:23:13:23 | z |
|
||||
| busybus.js:9:36:9:39 | info | busybus.js:10:54:10:57 | info |
|
||||
| busybus.js:9:36:9:39 | info | busybus.js:10:54:10:57 | info |
|
||||
| busybus.js:10:19:10:50 | { filen ... eType } | busybus.js:10:21:10:28 | filename |
|
||||
| busybus.js:10:19:10:50 | { filen ... eType } | busybus.js:10:31:10:38 | encoding |
|
||||
| busybus.js:10:19:10:50 | { filen ... eType } | busybus.js:10:41:10:48 | mimeType |
|
||||
| busybus.js:10:19:10:57 | encoding | busybus.js:12:28:12:35 | encoding |
|
||||
| busybus.js:10:19:10:57 | encoding | busybus.js:12:28:12:35 | encoding |
|
||||
| busybus.js:10:19:10:57 | filename | busybus.js:12:18:12:25 | filename |
|
||||
| busybus.js:10:19:10:57 | filename | busybus.js:12:18:12:25 | filename |
|
||||
| busybus.js:10:19:10:57 | mimeType | busybus.js:12:38:12:45 | mimeType |
|
||||
| busybus.js:10:19:10:57 | mimeType | busybus.js:12:38:12:45 | mimeType |
|
||||
| busybus.js:10:21:10:28 | filename | busybus.js:10:19:10:57 | filename |
|
||||
| busybus.js:10:31:10:38 | encoding | busybus.js:10:19:10:57 | encoding |
|
||||
| busybus.js:10:41:10:48 | mimeType | busybus.js:10:19:10:57 | mimeType |
|
||||
| busybus.js:10:54:10:57 | info | busybus.js:10:19:10:50 | { filen ... eType } |
|
||||
| busybus.js:13:23:13:23 | z | busybus.js:13:31:13:36 | sink() |
|
||||
| busybus.js:13:23:13:23 | z | busybus.js:13:31:13:36 | sink() |
|
||||
| busybus.js:15:30:15:33 | data | busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:15:30:15:33 | data | busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:15:30:15:33 | data | busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:15:30:15:33 | data | busybus.js:16:22:16:25 | data |
|
||||
| busybus.js:22:25:22:42 | data | busybus.js:23:26:23:29 | data |
|
||||
| busybus.js:22:25:22:42 | data | busybus.js:23:26:23:29 | data |
|
||||
| busybus.js:22:32:22:42 | this.read() | busybus.js:22:25:22:42 | data |
|
||||
| busybus.js:22:32:22:42 | this.read() | busybus.js:22:25:22:42 | data |
|
||||
| busybus.js:27:25:27:28 | name | busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:27:25:27:28 | name | busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:27:25:27:28 | name | busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:27:25:27:28 | name | busybus.js:28:18:28:21 | name |
|
||||
| busybus.js:27:31:27:33 | val | busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:27:31:27:33 | val | busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:27:31:27:33 | val | busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:27:31:27:33 | val | busybus.js:28:24:28:26 | val |
|
||||
| busybus.js:27:36:27:39 | info | busybus.js:28:29:28:32 | info |
|
||||
| busybus.js:27:36:27:39 | info | busybus.js:28:29:28:32 | info |
|
||||
| busybus.js:27:36:27:39 | info | busybus.js:28:29:28:32 | info |
|
||||
| busybus.js:27:36:27:39 | info | busybus.js:28:29:28:32 | info |
|
||||
| dicer.js:12:23:12:26 | part | dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:12:23:12:26 | part | dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:12:23:12:26 | part | dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:12:23:12:26 | part | dicer.js:13:19:13:24 | sink() |
|
||||
| dicer.js:14:28:14:33 | header | dicer.js:16:22:16:27 | header |
|
||||
| dicer.js:14:28:14:33 | header | dicer.js:16:22:16:27 | header |
|
||||
| dicer.js:16:22:16:27 | header | dicer.js:16:22:16:30 | header[h] |
|
||||
| dicer.js:16:22:16:27 | header | dicer.js:16:22:16:30 | header[h] |
|
||||
| dicer.js:19:26:19:29 | data | dicer.js:20:18:20:21 | data |
|
||||
| dicer.js:19:26:19:29 | data | dicer.js:20:18:20:21 | data |
|
||||
| dicer.js:19:26:19:29 | data | dicer.js:20:18:20:21 | data |
|
||||
| dicer.js:19:26:19:29 | data | dicer.js:20:18:20:21 | data |
|
||||
| formidable.js:7:11:7:25 | [fields, files] | formidable.js:7:12:7:17 | fields |
|
||||
| formidable.js:7:11:7:25 | [fields, files] | formidable.js:7:20:7:24 | files |
|
||||
| formidable.js:7:11:7:49 | fields | formidable.js:8:10:8:15 | fields |
|
||||
| formidable.js:7:11:7:49 | fields | formidable.js:8:10:8:15 | fields |
|
||||
| formidable.js:7:11:7:49 | files | formidable.js:8:18:8:22 | files |
|
||||
| formidable.js:7:11:7:49 | files | formidable.js:8:18:8:22 | files |
|
||||
| formidable.js:7:12:7:17 | fields | formidable.js:7:11:7:49 | fields |
|
||||
| formidable.js:7:20:7:24 | files | formidable.js:7:11:7:49 | files |
|
||||
| formidable.js:7:29:7:49 | await f ... se(req) | formidable.js:7:11:7:25 | [fields, files] |
|
||||
| formidable.js:7:35:7:49 | form.parse(req) | formidable.js:7:29:7:49 | await f ... se(req) |
|
||||
| formidable.js:7:35:7:49 | form.parse(req) | formidable.js:7:29:7:49 | await f ... se(req) |
|
||||
| formidable.js:9:27:9:34 | formname | formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:9:27:9:34 | formname | formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:9:27:9:34 | formname | formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:9:27:9:34 | formname | formidable.js:10:14:10:21 | formname |
|
||||
| formidable.js:9:37:9:40 | file | formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:9:37:9:40 | file | formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:9:37:9:40 | file | formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:9:37:9:40 | file | formidable.js:10:24:10:27 | file |
|
||||
| formidable.js:12:22:12:29 | formname | formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:12:22:12:29 | formname | formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:12:22:12:29 | formname | formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:12:22:12:29 | formname | formidable.js:13:14:13:21 | formname |
|
||||
| formidable.js:12:32:12:35 | file | formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:12:32:12:35 | file | formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:12:32:12:35 | file | formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:12:32:12:35 | file | formidable.js:13:24:13:27 | file |
|
||||
| formidable.js:15:23:15:31 | fieldName | formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:15:23:15:31 | fieldName | formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:15:23:15:31 | fieldName | formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:15:23:15:31 | fieldName | formidable.js:16:14:16:22 | fieldName |
|
||||
| formidable.js:15:34:15:43 | fieldValue | formidable.js:16:25:16:34 | fieldValue |
|
||||
| formidable.js:15:34:15:43 | fieldValue | formidable.js:16:25:16:34 | fieldValue |
|
||||
| formidable.js:15:34:15:43 | fieldValue | formidable.js:16:25:16:34 | fieldValue |
|
||||
| formidable.js:15:34:15:43 | fieldValue | formidable.js:16:25:16:34 | fieldValue |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:9:14:9:17 | part |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:8:22:8:25 | part | multiparty.js:10:19:10:24 | sink() |
|
||||
| multiparty.js:14:37:14:42 | fields | multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:14:37:14:42 | fields | multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:14:37:14:42 | fields | multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:14:37:14:42 | fields | multiparty.js:15:14:15:19 | fields |
|
||||
| multiparty.js:14:45:14:49 | files | multiparty.js:15:22:15:26 | files |
|
||||
| multiparty.js:14:45:14:49 | files | multiparty.js:15:22:15:26 | files |
|
||||
| multiparty.js:14:45:14:49 | files | multiparty.js:15:22:15:26 | files |
|
||||
| multiparty.js:14:45:14:49 | files | multiparty.js:15:22:15:26 | files |
|
||||
#select
|
||||
| busybus.js:12:18:12:25 | filename | busybus.js:9:36:9:39 | info | busybus.js:12:18:12:25 | filename | This entity depends on a $@. | busybus.js:9:36:9:39 | info | user-provided value |
|
||||
| busybus.js:12:28:12:35 | encoding | busybus.js:9:36:9:39 | info | busybus.js:12:28:12:35 | encoding | This entity depends on a $@. | busybus.js:9:36:9:39 | info | user-provided value |
|
||||
| busybus.js:12:38:12:45 | mimeType | busybus.js:9:36:9:39 | info | busybus.js:12:38:12:45 | mimeType | This entity depends on a $@. | busybus.js:9:36:9:39 | info | user-provided value |
|
||||
| busybus.js:13:31:13:36 | sink() | busybus.js:9:30:9:33 | file | busybus.js:13:31:13:36 | sink() | This entity depends on a $@. | busybus.js:9:30:9:33 | file | user-provided value |
|
||||
| busybus.js:16:22:16:25 | data | busybus.js:15:30:15:33 | data | busybus.js:16:22:16:25 | data | This entity depends on a $@. | busybus.js:15:30:15:33 | data | user-provided value |
|
||||
| busybus.js:23:26:23:29 | data | busybus.js:22:32:22:42 | this.read() | busybus.js:23:26:23:29 | data | This entity depends on a $@. | busybus.js:22:32:22:42 | this.read() | user-provided value |
|
||||
| busybus.js:28:18:28:21 | name | busybus.js:27:25:27:28 | name | busybus.js:28:18:28:21 | name | This entity depends on a $@. | busybus.js:27:25:27:28 | name | user-provided value |
|
||||
| busybus.js:28:24:28:26 | val | busybus.js:27:31:27:33 | val | busybus.js:28:24:28:26 | val | This entity depends on a $@. | busybus.js:27:31:27:33 | val | user-provided value |
|
||||
| busybus.js:28:29:28:32 | info | busybus.js:27:36:27:39 | info | busybus.js:28:29:28:32 | info | This entity depends on a $@. | busybus.js:27:36:27:39 | info | user-provided value |
|
||||
| dicer.js:13:19:13:24 | sink() | dicer.js:12:23:12:26 | part | dicer.js:13:19:13:24 | sink() | This entity depends on a $@. | dicer.js:12:23:12:26 | part | user-provided value |
|
||||
| dicer.js:16:22:16:30 | header[h] | dicer.js:14:28:14:33 | header | dicer.js:16:22:16:30 | header[h] | This entity depends on a $@. | dicer.js:14:28:14:33 | header | user-provided value |
|
||||
| dicer.js:20:18:20:21 | data | dicer.js:19:26:19:29 | data | dicer.js:20:18:20:21 | data | This entity depends on a $@. | dicer.js:19:26:19:29 | data | user-provided value |
|
||||
| formidable.js:8:10:8:15 | fields | formidable.js:7:35:7:49 | form.parse(req) | formidable.js:8:10:8:15 | fields | This entity depends on a $@. | formidable.js:7:35:7:49 | form.parse(req) | user-provided value |
|
||||
| formidable.js:8:18:8:22 | files | formidable.js:7:35:7:49 | form.parse(req) | formidable.js:8:18:8:22 | files | This entity depends on a $@. | formidable.js:7:35:7:49 | form.parse(req) | user-provided value |
|
||||
| formidable.js:10:14:10:21 | formname | formidable.js:9:27:9:34 | formname | formidable.js:10:14:10:21 | formname | This entity depends on a $@. | formidable.js:9:27:9:34 | formname | user-provided value |
|
||||
| formidable.js:10:24:10:27 | file | formidable.js:9:37:9:40 | file | formidable.js:10:24:10:27 | file | This entity depends on a $@. | formidable.js:9:37:9:40 | file | user-provided value |
|
||||
| formidable.js:13:14:13:21 | formname | formidable.js:12:22:12:29 | formname | formidable.js:13:14:13:21 | formname | This entity depends on a $@. | formidable.js:12:22:12:29 | formname | user-provided value |
|
||||
| formidable.js:13:24:13:27 | file | formidable.js:12:32:12:35 | file | formidable.js:13:24:13:27 | file | This entity depends on a $@. | formidable.js:12:32:12:35 | file | user-provided value |
|
||||
| formidable.js:16:14:16:22 | fieldName | formidable.js:15:23:15:31 | fieldName | formidable.js:16:14:16:22 | fieldName | This entity depends on a $@. | formidable.js:15:23:15:31 | fieldName | user-provided value |
|
||||
| formidable.js:16:25:16:34 | fieldValue | formidable.js:15:34:15:43 | fieldValue | formidable.js:16:25:16:34 | fieldValue | This entity depends on a $@. | formidable.js:15:34:15:43 | fieldValue | user-provided value |
|
||||
| multiparty.js:9:14:9:17 | part | multiparty.js:8:22:8:25 | part | multiparty.js:9:14:9:17 | part | This entity depends on a $@. | multiparty.js:8:22:8:25 | part | user-provided value |
|
||||
| multiparty.js:10:19:10:24 | sink() | multiparty.js:8:22:8:25 | part | multiparty.js:10:19:10:24 | sink() | This entity depends on a $@. | multiparty.js:8:22:8:25 | part | user-provided value |
|
||||
| multiparty.js:15:14:15:19 | fields | multiparty.js:14:37:14:42 | fields | multiparty.js:15:14:15:19 | fields | This entity depends on a $@. | multiparty.js:14:37:14:42 | fields | user-provided value |
|
||||
| multiparty.js:15:22:15:26 | files | multiparty.js:14:45:14:49 | files | multiparty.js:15:22:15:26 | files | This entity depends on a $@. | multiparty.js:14:45:14:49 | files | user-provided value |
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @name Remote Form Flow Sources
|
||||
* @description Using remote user controlled sources from Forms
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5
|
||||
* @precision high
|
||||
* @id js/remote-flow-source
|
||||
* @tags correctness
|
||||
* security
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import DataFlow::PathGraph
|
||||
import experimental.semmle.javascript.FormParsers
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for test
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "RemoteFlowSourcesOUserForm" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = API::moduleImport("sink").getAParameter().asSink() or
|
||||
sink = API::moduleImport("sink").getReturn().asSource()
|
||||
}
|
||||
}
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "This entity depends on a $@.", source.getNode(),
|
||||
"user-provided value"
|
||||
33
javascript/ql/test/experimental/FormParsers/busybus.js
Normal file
33
javascript/ql/test/experimental/FormParsers/busybus.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const http = require('http');
|
||||
const zlib = require('node:zlib');
|
||||
const busboy = require('busboy');
|
||||
const sink = require('sink');
|
||||
|
||||
http.createServer((req, res) => {
|
||||
if (req.method === 'POST') {
|
||||
const bb = busboy({ headers: req.headers });
|
||||
bb.on('file', (name, file, info) => {
|
||||
const { filename, encoding, mimeType } = info;
|
||||
const z = zlib.createGzip();
|
||||
sink(filename, encoding, mimeType) // sink
|
||||
file.pipe(z).pipe(sink())
|
||||
|
||||
file.on('data', (data) => {
|
||||
sink(data)
|
||||
})
|
||||
|
||||
file.on('readable', function () {
|
||||
// There is some data to read now.
|
||||
let data;
|
||||
while ((data = this.read()) !== null) {
|
||||
sink(data)
|
||||
}
|
||||
});
|
||||
});
|
||||
bb.on('field', (name, val, info) => {
|
||||
sink(name, val, info)
|
||||
});
|
||||
}
|
||||
}).listen(8000, () => {
|
||||
console.log('Listening for requests');
|
||||
});
|
||||
25
javascript/ql/test/experimental/FormParsers/dicer.js
Normal file
25
javascript/ql/test/experimental/FormParsers/dicer.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const { inspect } = require('util');
|
||||
const http = require('http');
|
||||
const Dicer = require('dicer');
|
||||
const sink = require('sink');
|
||||
|
||||
const PORT = 8080;
|
||||
|
||||
http.createServer((req, res) => {
|
||||
let m;
|
||||
const dicer = new Dicer({ boundary: m[1] || m[2] });
|
||||
|
||||
dicer.on('part', (part) => {
|
||||
part.pipe(sink())
|
||||
part.on('header', (header) => {
|
||||
for (h in header) {
|
||||
sink(header[h])
|
||||
}
|
||||
});
|
||||
part.on('data', (data) => {
|
||||
sink(data)
|
||||
});
|
||||
});
|
||||
}).listen(PORT, () => {
|
||||
console.log(`Listening for requests on port ${PORT}`);
|
||||
});
|
||||
22
javascript/ql/test/experimental/FormParsers/formidable.js
Normal file
22
javascript/ql/test/experimental/FormParsers/formidable.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import http from 'node:http';
|
||||
import formidable from 'formidable';
|
||||
const sink = require('sink');
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
const form = formidable({});
|
||||
const [fields, files] = await form.parse(req);
|
||||
sink(fields, files)
|
||||
form.on('fileBegin', (formname, file) => {
|
||||
sink(formname, file)
|
||||
});
|
||||
form.on('file', (formname, file) => {
|
||||
sink(formname, file)
|
||||
});
|
||||
form.on('field', (fieldName, fieldValue) => {
|
||||
sink(fieldName, fieldValue)
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(8080, () => {
|
||||
console.log('Server listening on http://localhost:8080/ ...');
|
||||
});
|
||||
19
javascript/ql/test/experimental/FormParsers/multiparty.js
Normal file
19
javascript/ql/test/experimental/FormParsers/multiparty.js
Normal file
@@ -0,0 +1,19 @@
|
||||
var multiparty = require('multiparty');
|
||||
var http = require('http');
|
||||
var util = require('util');
|
||||
const sink = require('sink');
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
var form = new multiparty.Form();
|
||||
form.on('part', (part) => {
|
||||
sink(part)
|
||||
part.pipe(sink())
|
||||
});
|
||||
|
||||
var form2 = new multiparty.Form();
|
||||
form2.parse(req, function (err, fields, files) {
|
||||
sink(fields, files)
|
||||
});
|
||||
form2.parse(req);
|
||||
|
||||
}).listen(8080);
|
||||
@@ -0,0 +1,51 @@
|
||||
nodes
|
||||
| test.js:5:11:5:44 | payload |
|
||||
| test.js:5:21:5:44 | req.que ... rameter |
|
||||
| test.js:5:21:5:44 | req.que ... rameter |
|
||||
| test.js:6:9:6:43 | payloadURL |
|
||||
| test.js:6:22:6:43 | new URL ... + sth) |
|
||||
| test.js:6:30:6:36 | payload |
|
||||
| test.js:6:30:6:42 | payload + sth |
|
||||
| test.js:7:16:7:25 | payloadURL |
|
||||
| test.js:7:16:7:25 | payloadURL |
|
||||
| test.js:9:5:9:39 | payloadURL |
|
||||
| test.js:9:18:9:39 | new URL ... + sth) |
|
||||
| test.js:9:26:9:32 | payload |
|
||||
| test.js:9:26:9:38 | payload + sth |
|
||||
| test.js:10:16:10:25 | payloadURL |
|
||||
| test.js:10:16:10:25 | payloadURL |
|
||||
| test.js:17:11:17:44 | payload |
|
||||
| test.js:17:21:17:44 | req.que ... rameter |
|
||||
| test.js:17:21:17:44 | req.que ... rameter |
|
||||
| test.js:18:18:18:24 | payload |
|
||||
| test.js:18:18:18:24 | payload |
|
||||
| test.js:19:18:19:24 | payload |
|
||||
| test.js:19:18:19:30 | payload + sth |
|
||||
| test.js:19:18:19:30 | payload + sth |
|
||||
edges
|
||||
| test.js:5:11:5:44 | payload | test.js:6:30:6:36 | payload |
|
||||
| test.js:5:11:5:44 | payload | test.js:9:26:9:32 | payload |
|
||||
| test.js:5:21:5:44 | req.que ... rameter | test.js:5:11:5:44 | payload |
|
||||
| test.js:5:21:5:44 | req.que ... rameter | test.js:5:11:5:44 | payload |
|
||||
| test.js:6:9:6:43 | payloadURL | test.js:7:16:7:25 | payloadURL |
|
||||
| test.js:6:9:6:43 | payloadURL | test.js:7:16:7:25 | payloadURL |
|
||||
| test.js:6:22:6:43 | new URL ... + sth) | test.js:6:9:6:43 | payloadURL |
|
||||
| test.js:6:30:6:36 | payload | test.js:6:30:6:42 | payload + sth |
|
||||
| test.js:6:30:6:42 | payload + sth | test.js:6:22:6:43 | new URL ... + sth) |
|
||||
| test.js:9:5:9:39 | payloadURL | test.js:10:16:10:25 | payloadURL |
|
||||
| test.js:9:5:9:39 | payloadURL | test.js:10:16:10:25 | payloadURL |
|
||||
| test.js:9:18:9:39 | new URL ... + sth) | test.js:9:5:9:39 | payloadURL |
|
||||
| test.js:9:26:9:32 | payload | test.js:9:26:9:38 | payload + sth |
|
||||
| test.js:9:26:9:38 | payload + sth | test.js:9:18:9:39 | new URL ... + sth) |
|
||||
| test.js:17:11:17:44 | payload | test.js:18:18:18:24 | payload |
|
||||
| test.js:17:11:17:44 | payload | test.js:18:18:18:24 | payload |
|
||||
| test.js:17:11:17:44 | payload | test.js:19:18:19:24 | payload |
|
||||
| test.js:17:21:17:44 | req.que ... rameter | test.js:17:11:17:44 | payload |
|
||||
| test.js:17:21:17:44 | req.que ... rameter | test.js:17:11:17:44 | payload |
|
||||
| test.js:19:18:19:24 | payload | test.js:19:18:19:30 | payload + sth |
|
||||
| test.js:19:18:19:24 | payload | test.js:19:18:19:30 | payload + sth |
|
||||
#select
|
||||
| test.js:7:16:7:25 | payloadURL | test.js:5:21:5:44 | req.que ... rameter | test.js:7:16:7:25 | payloadURL | This command line depends on a $@. | test.js:5:21:5:44 | req.que ... rameter | user-provided value |
|
||||
| test.js:10:16:10:25 | payloadURL | test.js:5:21:5:44 | req.que ... rameter | test.js:10:16:10:25 | payloadURL | This command line depends on a $@. | test.js:5:21:5:44 | req.que ... rameter | user-provided value |
|
||||
| test.js:18:18:18:24 | payload | test.js:17:21:17:44 | req.que ... rameter | test.js:18:18:18:24 | payload | This command line depends on a $@. | test.js:17:21:17:44 | req.que ... rameter | user-provided value |
|
||||
| test.js:19:18:19:30 | payload + sth | test.js:17:21:17:44 | req.que ... rameter | test.js:19:18:19:30 | payload + sth | This command line depends on a $@. | test.js:17:21:17:44 | req.que ... rameter | user-provided value |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-094-dataURL/CodeInjection.ql
|
||||
@@ -0,0 +1,22 @@
|
||||
const { Worker } = require('node:worker_threads');
|
||||
var app = require('express')();
|
||||
|
||||
app.post('/path', async function (req, res) {
|
||||
const payload = req.query.queryParameter // like: payload = 'data:text/javascript,console.log("hello!");//'
|
||||
let payloadURL = new URL(payload + sth) // NOT OK
|
||||
new Worker(payloadURL);
|
||||
|
||||
payloadURL = new URL(payload + sth) // NOT OK
|
||||
new Worker(payloadURL);
|
||||
|
||||
payloadURL = new URL(sth + payload) // OK
|
||||
new Worker(payloadURL);
|
||||
});
|
||||
|
||||
app.post('/path2', async function (req, res) {
|
||||
const payload = req.query.queryParameter // like: payload = 'data:text/javascript,console.log("hello!");//'
|
||||
await import(payload) // NOT OK
|
||||
await import(payload + sth) // NOT OK
|
||||
await import(sth + payload) // OK
|
||||
});
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
nodes
|
||||
| test.js:5:9:5:28 | { EnvValue, EnvKey } |
|
||||
| test.js:5:9:5:39 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvValue |
|
||||
| test.js:5:11:5:18 | EnvValue |
|
||||
| test.js:5:21:5:26 | EnvKey |
|
||||
| test.js:5:32:5:39 | req.body |
|
||||
| test.js:5:32:5:39 | req.body |
|
||||
| test.js:6:15:6:20 | EnvKey |
|
||||
| test.js:6:15:6:20 | EnvKey |
|
||||
| test.js:6:25:6:32 | EnvValue |
|
||||
| test.js:6:25:6:32 | EnvValue |
|
||||
| test.js:7:15:7:20 | EnvKey |
|
||||
| test.js:7:15:7:20 | EnvKey |
|
||||
| test.js:7:25:7:32 | EnvValue |
|
||||
| test.js:7:25:7:32 | EnvValue |
|
||||
| test.js:13:9:13:28 | { EnvValue, EnvKey } |
|
||||
| test.js:13:9:13:39 | EnvKey |
|
||||
| test.js:13:9:13:39 | EnvValue |
|
||||
| test.js:13:11:13:18 | EnvValue |
|
||||
| test.js:13:21:13:26 | EnvKey |
|
||||
| test.js:13:32:13:39 | req.body |
|
||||
| test.js:13:32:13:39 | req.body |
|
||||
| test.js:15:15:15:20 | EnvKey |
|
||||
| test.js:15:15:15:20 | EnvKey |
|
||||
| test.js:16:26:16:33 | EnvValue |
|
||||
| test.js:16:26:16:33 | EnvValue |
|
||||
edges
|
||||
| test.js:5:9:5:28 | { EnvValue, EnvKey } | test.js:5:11:5:18 | EnvValue |
|
||||
| test.js:5:9:5:28 | { EnvValue, EnvKey } | test.js:5:21:5:26 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvKey | test.js:6:15:6:20 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvKey | test.js:6:15:6:20 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvKey | test.js:7:15:7:20 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvKey | test.js:7:15:7:20 | EnvKey |
|
||||
| test.js:5:9:5:39 | EnvValue | test.js:6:25:6:32 | EnvValue |
|
||||
| test.js:5:9:5:39 | EnvValue | test.js:6:25:6:32 | EnvValue |
|
||||
| test.js:5:9:5:39 | EnvValue | test.js:7:25:7:32 | EnvValue |
|
||||
| test.js:5:9:5:39 | EnvValue | test.js:7:25:7:32 | EnvValue |
|
||||
| test.js:5:11:5:18 | EnvValue | test.js:5:9:5:39 | EnvValue |
|
||||
| test.js:5:21:5:26 | EnvKey | test.js:5:9:5:39 | EnvKey |
|
||||
| test.js:5:32:5:39 | req.body | test.js:5:9:5:28 | { EnvValue, EnvKey } |
|
||||
| test.js:5:32:5:39 | req.body | test.js:5:9:5:28 | { EnvValue, EnvKey } |
|
||||
| test.js:13:9:13:28 | { EnvValue, EnvKey } | test.js:13:11:13:18 | EnvValue |
|
||||
| test.js:13:9:13:28 | { EnvValue, EnvKey } | test.js:13:21:13:26 | EnvKey |
|
||||
| test.js:13:9:13:39 | EnvKey | test.js:15:15:15:20 | EnvKey |
|
||||
| test.js:13:9:13:39 | EnvKey | test.js:15:15:15:20 | EnvKey |
|
||||
| test.js:13:9:13:39 | EnvValue | test.js:16:26:16:33 | EnvValue |
|
||||
| test.js:13:9:13:39 | EnvValue | test.js:16:26:16:33 | EnvValue |
|
||||
| test.js:13:11:13:18 | EnvValue | test.js:13:9:13:39 | EnvValue |
|
||||
| test.js:13:21:13:26 | EnvKey | test.js:13:9:13:39 | EnvKey |
|
||||
| test.js:13:32:13:39 | req.body | test.js:13:9:13:28 | { EnvValue, EnvKey } |
|
||||
| test.js:13:32:13:39 | req.body | test.js:13:9:13:28 | { EnvValue, EnvKey } |
|
||||
#select
|
||||
| test.js:6:15:6:20 | EnvKey | test.js:5:32:5:39 | req.body | test.js:6:15:6:20 | EnvKey | arbitrary environment variable assignment from this $@. | test.js:5:32:5:39 | req.body | user controllable source |
|
||||
| test.js:7:15:7:20 | EnvKey | test.js:5:32:5:39 | req.body | test.js:7:15:7:20 | EnvKey | arbitrary environment variable assignment from this $@. | test.js:5:32:5:39 | req.body | user controllable source |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-099/EnvValueAndKeyInjection.ql
|
||||
@@ -0,0 +1,19 @@
|
||||
const http = require('node:http');
|
||||
|
||||
|
||||
http.createServer((req, res) => {
|
||||
const { EnvValue, EnvKey } = req.body;
|
||||
process.env[EnvKey] = EnvValue; // NOT OK
|
||||
process.env[EnvKey] = EnvValue; // NOT OK
|
||||
|
||||
res.end('env has been injected!');
|
||||
});
|
||||
|
||||
http.createServer((req, res) => {
|
||||
const { EnvValue, EnvKey } = req.body;
|
||||
|
||||
process.env[EnvKey] = "constant" // OK
|
||||
process.env.constant = EnvValue // OK
|
||||
|
||||
res.end('env has been injected!');
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
nodes
|
||||
| test.js:4:9:4:20 | { EnvValue } |
|
||||
| test.js:4:9:4:31 | EnvValue |
|
||||
| test.js:4:11:4:18 | EnvValue |
|
||||
| test.js:4:24:4:31 | req.body |
|
||||
| test.js:4:24:4:31 | req.body |
|
||||
| test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:7:22:7:29 | EnvValue |
|
||||
| test.js:7:22:7:29 | EnvValue |
|
||||
edges
|
||||
| test.js:4:9:4:20 | { EnvValue } | test.js:4:11:4:18 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:5:35:5:42 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:6:23:6:30 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:7:22:7:29 | EnvValue |
|
||||
| test.js:4:9:4:31 | EnvValue | test.js:7:22:7:29 | EnvValue |
|
||||
| test.js:4:11:4:18 | EnvValue | test.js:4:9:4:31 | EnvValue |
|
||||
| test.js:4:24:4:31 | req.body | test.js:4:9:4:20 | { EnvValue } |
|
||||
| test.js:4:24:4:31 | req.body | test.js:4:9:4:20 | { EnvValue } |
|
||||
#select
|
||||
| test.js:5:35:5:42 | EnvValue | test.js:4:24:4:31 | req.body | test.js:5:35:5:42 | EnvValue | this environment variable assignment is $@. | test.js:4:24:4:31 | req.body | user controllable |
|
||||
| test.js:6:23:6:30 | EnvValue | test.js:4:24:4:31 | req.body | test.js:6:23:6:30 | EnvValue | this environment variable assignment is $@. | test.js:4:24:4:31 | req.body | user controllable |
|
||||
| test.js:7:22:7:29 | EnvValue | test.js:4:24:4:31 | req.body | test.js:7:22:7:29 | EnvValue | this environment variable assignment is $@. | test.js:4:24:4:31 | req.body | user controllable |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-099/EnvValueInjection.ql
|
||||
@@ -0,0 +1,10 @@
|
||||
const http = require('node:http');
|
||||
|
||||
http.createServer((req, res) => {
|
||||
const { EnvValue } = req.body;
|
||||
process.env["A_Critical_Env"] = EnvValue; // NOT OK
|
||||
process.env[AKey] = EnvValue; // NOT OK
|
||||
process.env.AKey = EnvValue; // NOT OK
|
||||
|
||||
res.end('env has been injected!');
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
const express = require('express')
|
||||
const jwtJsonwebtoken = require('jsonwebtoken');
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
function aJWT() {
|
||||
return "A JWT provided by user"
|
||||
}
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// BAD: no signature verification
|
||||
jwtJsonwebtoken.decode(UserToken) // NOT OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// BAD: no signature verification
|
||||
jwtJsonwebtoken.decode(UserToken) // NOT OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret(), { algorithms: ["HS256", "none"] }) // NOT OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// GOOD: with signature verification
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret()) // OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwtJsonwebtoken.decode(UserToken) // OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret()) // OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwtJsonwebtoken.decode(UserToken) // OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret(), { algorithms: ["HS256"] }) // OK
|
||||
})();
|
||||
@@ -0,0 +1,141 @@
|
||||
nodes
|
||||
| JsonWebToken.js:13:11:13:28 | UserToken |
|
||||
| JsonWebToken.js:13:23:13:28 | aJwt() |
|
||||
| JsonWebToken.js:13:23:13:28 | aJwt() |
|
||||
| JsonWebToken.js:16:28:16:36 | UserToken |
|
||||
| JsonWebToken.js:16:28:16:36 | UserToken |
|
||||
| JsonWebToken.js:20:11:20:28 | UserToken |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() |
|
||||
| JsonWebToken.js:23:28:23:36 | UserToken |
|
||||
| JsonWebToken.js:23:28:23:36 | UserToken |
|
||||
| JsonWebToken.js:24:28:24:36 | UserToken |
|
||||
| JsonWebToken.js:24:28:24:36 | UserToken |
|
||||
| JsonWebToken.js:28:11:28:28 | UserToken |
|
||||
| JsonWebToken.js:28:23:28:28 | aJwt() |
|
||||
| JsonWebToken.js:28:23:28:28 | aJwt() |
|
||||
| JsonWebToken.js:31:28:31:36 | UserToken |
|
||||
| JsonWebToken.js:31:28:31:36 | UserToken |
|
||||
| JsonWebToken.js:35:11:35:28 | UserToken |
|
||||
| JsonWebToken.js:35:23:35:28 | aJwt() |
|
||||
| JsonWebToken.js:35:23:35:28 | aJwt() |
|
||||
| JsonWebToken.js:38:28:38:36 | UserToken |
|
||||
| JsonWebToken.js:38:28:38:36 | UserToken |
|
||||
| JsonWebToken.js:39:28:39:36 | UserToken |
|
||||
| JsonWebToken.js:39:28:39:36 | UserToken |
|
||||
| JsonWebToken.js:43:11:43:28 | UserToken |
|
||||
| JsonWebToken.js:43:23:43:28 | aJwt() |
|
||||
| JsonWebToken.js:43:23:43:28 | aJwt() |
|
||||
| JsonWebToken.js:46:28:46:36 | UserToken |
|
||||
| JsonWebToken.js:46:28:46:36 | UserToken |
|
||||
| JsonWebToken.js:47:28:47:36 | UserToken |
|
||||
| JsonWebToken.js:47:28:47:36 | UserToken |
|
||||
| jose.js:12:11:12:28 | UserToken |
|
||||
| jose.js:12:23:12:28 | aJwt() |
|
||||
| jose.js:12:23:12:28 | aJwt() |
|
||||
| jose.js:15:20:15:28 | UserToken |
|
||||
| jose.js:15:20:15:28 | UserToken |
|
||||
| jose.js:19:11:19:28 | UserToken |
|
||||
| jose.js:19:23:19:28 | aJwt() |
|
||||
| jose.js:19:23:19:28 | aJwt() |
|
||||
| jose.js:22:20:22:28 | UserToken |
|
||||
| jose.js:22:20:22:28 | UserToken |
|
||||
| jose.js:23:26:23:34 | UserToken |
|
||||
| jose.js:23:26:23:34 | UserToken |
|
||||
| jose.js:27:11:27:28 | UserToken |
|
||||
| jose.js:27:23:27:28 | aJwt() |
|
||||
| jose.js:27:23:27:28 | aJwt() |
|
||||
| jose.js:30:26:30:34 | UserToken |
|
||||
| jose.js:30:26:30:34 | UserToken |
|
||||
| jwtDecode.js:13:11:13:28 | UserToken |
|
||||
| jwtDecode.js:13:23:13:28 | aJwt() |
|
||||
| jwtDecode.js:13:23:13:28 | aJwt() |
|
||||
| jwtDecode.js:17:16:17:24 | UserToken |
|
||||
| jwtDecode.js:17:16:17:24 | UserToken |
|
||||
| jwtSimple.js:13:11:13:28 | UserToken |
|
||||
| jwtSimple.js:13:23:13:28 | aJwt() |
|
||||
| jwtSimple.js:13:23:13:28 | aJwt() |
|
||||
| jwtSimple.js:16:23:16:31 | UserToken |
|
||||
| jwtSimple.js:16:23:16:31 | UserToken |
|
||||
| jwtSimple.js:20:11:20:28 | UserToken |
|
||||
| jwtSimple.js:20:23:20:28 | aJwt() |
|
||||
| jwtSimple.js:20:23:20:28 | aJwt() |
|
||||
| jwtSimple.js:23:23:23:31 | UserToken |
|
||||
| jwtSimple.js:23:23:23:31 | UserToken |
|
||||
| jwtSimple.js:24:23:24:31 | UserToken |
|
||||
| jwtSimple.js:24:23:24:31 | UserToken |
|
||||
| jwtSimple.js:28:11:28:28 | UserToken |
|
||||
| jwtSimple.js:28:23:28:28 | aJwt() |
|
||||
| jwtSimple.js:28:23:28:28 | aJwt() |
|
||||
| jwtSimple.js:31:23:31:31 | UserToken |
|
||||
| jwtSimple.js:31:23:31:31 | UserToken |
|
||||
| jwtSimple.js:32:23:32:31 | UserToken |
|
||||
| jwtSimple.js:32:23:32:31 | UserToken |
|
||||
edges
|
||||
| JsonWebToken.js:13:11:13:28 | UserToken | JsonWebToken.js:16:28:16:36 | UserToken |
|
||||
| JsonWebToken.js:13:11:13:28 | UserToken | JsonWebToken.js:16:28:16:36 | UserToken |
|
||||
| JsonWebToken.js:13:23:13:28 | aJwt() | JsonWebToken.js:13:11:13:28 | UserToken |
|
||||
| JsonWebToken.js:13:23:13:28 | aJwt() | JsonWebToken.js:13:11:13:28 | UserToken |
|
||||
| JsonWebToken.js:20:11:20:28 | UserToken | JsonWebToken.js:23:28:23:36 | UserToken |
|
||||
| JsonWebToken.js:20:11:20:28 | UserToken | JsonWebToken.js:23:28:23:36 | UserToken |
|
||||
| JsonWebToken.js:20:11:20:28 | UserToken | JsonWebToken.js:24:28:24:36 | UserToken |
|
||||
| JsonWebToken.js:20:11:20:28 | UserToken | JsonWebToken.js:24:28:24:36 | UserToken |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:20:11:20:28 | UserToken |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:20:11:20:28 | UserToken |
|
||||
| JsonWebToken.js:28:11:28:28 | UserToken | JsonWebToken.js:31:28:31:36 | UserToken |
|
||||
| JsonWebToken.js:28:11:28:28 | UserToken | JsonWebToken.js:31:28:31:36 | UserToken |
|
||||
| JsonWebToken.js:28:23:28:28 | aJwt() | JsonWebToken.js:28:11:28:28 | UserToken |
|
||||
| JsonWebToken.js:28:23:28:28 | aJwt() | JsonWebToken.js:28:11:28:28 | UserToken |
|
||||
| JsonWebToken.js:35:11:35:28 | UserToken | JsonWebToken.js:38:28:38:36 | UserToken |
|
||||
| JsonWebToken.js:35:11:35:28 | UserToken | JsonWebToken.js:38:28:38:36 | UserToken |
|
||||
| JsonWebToken.js:35:11:35:28 | UserToken | JsonWebToken.js:39:28:39:36 | UserToken |
|
||||
| JsonWebToken.js:35:11:35:28 | UserToken | JsonWebToken.js:39:28:39:36 | UserToken |
|
||||
| JsonWebToken.js:35:23:35:28 | aJwt() | JsonWebToken.js:35:11:35:28 | UserToken |
|
||||
| JsonWebToken.js:35:23:35:28 | aJwt() | JsonWebToken.js:35:11:35:28 | UserToken |
|
||||
| JsonWebToken.js:43:11:43:28 | UserToken | JsonWebToken.js:46:28:46:36 | UserToken |
|
||||
| JsonWebToken.js:43:11:43:28 | UserToken | JsonWebToken.js:46:28:46:36 | UserToken |
|
||||
| JsonWebToken.js:43:11:43:28 | UserToken | JsonWebToken.js:47:28:47:36 | UserToken |
|
||||
| JsonWebToken.js:43:11:43:28 | UserToken | JsonWebToken.js:47:28:47:36 | UserToken |
|
||||
| JsonWebToken.js:43:23:43:28 | aJwt() | JsonWebToken.js:43:11:43:28 | UserToken |
|
||||
| JsonWebToken.js:43:23:43:28 | aJwt() | JsonWebToken.js:43:11:43:28 | UserToken |
|
||||
| jose.js:12:11:12:28 | UserToken | jose.js:15:20:15:28 | UserToken |
|
||||
| jose.js:12:11:12:28 | UserToken | jose.js:15:20:15:28 | UserToken |
|
||||
| jose.js:12:23:12:28 | aJwt() | jose.js:12:11:12:28 | UserToken |
|
||||
| jose.js:12:23:12:28 | aJwt() | jose.js:12:11:12:28 | UserToken |
|
||||
| jose.js:19:11:19:28 | UserToken | jose.js:22:20:22:28 | UserToken |
|
||||
| jose.js:19:11:19:28 | UserToken | jose.js:22:20:22:28 | UserToken |
|
||||
| jose.js:19:11:19:28 | UserToken | jose.js:23:26:23:34 | UserToken |
|
||||
| jose.js:19:11:19:28 | UserToken | jose.js:23:26:23:34 | UserToken |
|
||||
| jose.js:19:23:19:28 | aJwt() | jose.js:19:11:19:28 | UserToken |
|
||||
| jose.js:19:23:19:28 | aJwt() | jose.js:19:11:19:28 | UserToken |
|
||||
| jose.js:27:11:27:28 | UserToken | jose.js:30:26:30:34 | UserToken |
|
||||
| jose.js:27:11:27:28 | UserToken | jose.js:30:26:30:34 | UserToken |
|
||||
| jose.js:27:23:27:28 | aJwt() | jose.js:27:11:27:28 | UserToken |
|
||||
| jose.js:27:23:27:28 | aJwt() | jose.js:27:11:27:28 | UserToken |
|
||||
| jwtDecode.js:13:11:13:28 | UserToken | jwtDecode.js:17:16:17:24 | UserToken |
|
||||
| jwtDecode.js:13:11:13:28 | UserToken | jwtDecode.js:17:16:17:24 | UserToken |
|
||||
| jwtDecode.js:13:23:13:28 | aJwt() | jwtDecode.js:13:11:13:28 | UserToken |
|
||||
| jwtDecode.js:13:23:13:28 | aJwt() | jwtDecode.js:13:11:13:28 | UserToken |
|
||||
| jwtSimple.js:13:11:13:28 | UserToken | jwtSimple.js:16:23:16:31 | UserToken |
|
||||
| jwtSimple.js:13:11:13:28 | UserToken | jwtSimple.js:16:23:16:31 | UserToken |
|
||||
| jwtSimple.js:13:23:13:28 | aJwt() | jwtSimple.js:13:11:13:28 | UserToken |
|
||||
| jwtSimple.js:13:23:13:28 | aJwt() | jwtSimple.js:13:11:13:28 | UserToken |
|
||||
| jwtSimple.js:20:11:20:28 | UserToken | jwtSimple.js:23:23:23:31 | UserToken |
|
||||
| jwtSimple.js:20:11:20:28 | UserToken | jwtSimple.js:23:23:23:31 | UserToken |
|
||||
| jwtSimple.js:20:11:20:28 | UserToken | jwtSimple.js:24:23:24:31 | UserToken |
|
||||
| jwtSimple.js:20:11:20:28 | UserToken | jwtSimple.js:24:23:24:31 | UserToken |
|
||||
| jwtSimple.js:20:23:20:28 | aJwt() | jwtSimple.js:20:11:20:28 | UserToken |
|
||||
| jwtSimple.js:20:23:20:28 | aJwt() | jwtSimple.js:20:11:20:28 | UserToken |
|
||||
| jwtSimple.js:28:11:28:28 | UserToken | jwtSimple.js:31:23:31:31 | UserToken |
|
||||
| jwtSimple.js:28:11:28:28 | UserToken | jwtSimple.js:31:23:31:31 | UserToken |
|
||||
| jwtSimple.js:28:11:28:28 | UserToken | jwtSimple.js:32:23:32:31 | UserToken |
|
||||
| jwtSimple.js:28:11:28:28 | UserToken | jwtSimple.js:32:23:32:31 | UserToken |
|
||||
| jwtSimple.js:28:23:28:28 | aJwt() | jwtSimple.js:28:11:28:28 | UserToken |
|
||||
| jwtSimple.js:28:23:28:28 | aJwt() | jwtSimple.js:28:11:28:28 | UserToken |
|
||||
#select
|
||||
| JsonWebToken.js:13:23:13:28 | aJwt() | JsonWebToken.js:13:23:13:28 | aJwt() | JsonWebToken.js:16:28:16:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:16:28:16:36 | UserToken | without signature verification |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:23:28:23:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:23:28:23:36 | UserToken | without signature verification |
|
||||
| JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:20:23:20:28 | aJwt() | JsonWebToken.js:24:28:24:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:24:28:24:36 | UserToken | without signature verification |
|
||||
| jose.js:12:23:12:28 | aJwt() | jose.js:12:23:12:28 | aJwt() | jose.js:15:20:15:28 | UserToken | Decoding JWT $@. | jose.js:15:20:15:28 | UserToken | without signature verification |
|
||||
| jwtDecode.js:13:23:13:28 | aJwt() | jwtDecode.js:13:23:13:28 | aJwt() | jwtDecode.js:17:16:17:24 | UserToken | Decoding JWT $@. | jwtDecode.js:17:16:17:24 | UserToken | without signature verification |
|
||||
| jwtSimple.js:13:23:13:28 | aJwt() | jwtSimple.js:13:23:13:28 | aJwt() | jwtSimple.js:16:23:16:31 | UserToken | Decoding JWT $@. | jwtSimple.js:16:23:16:31 | UserToken | without signature verification |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-347/decodeJwtWithoutVerificationLocalSource.ql
|
||||
@@ -0,0 +1,31 @@
|
||||
const jose = require('jose')
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
function aJWT() {
|
||||
return "A JWT provided by user"
|
||||
}
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// no signature verification
|
||||
jose.decodeJwt(UserToken) // NOT OK
|
||||
})();
|
||||
|
||||
(async function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// first without signature verification then with signature verification for same UserToken
|
||||
jose.decodeJwt(UserToken) // OK
|
||||
await jose.jwtVerify(UserToken, new TextEncoder().encode(getSecret())) // OK
|
||||
})();
|
||||
|
||||
(async function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// with signature verification
|
||||
await jose.jwtVerify(UserToken, new TextEncoder().encode(getSecret())) // OK
|
||||
})();
|
||||
@@ -0,0 +1,18 @@
|
||||
const express = require('express')
|
||||
const jwt_decode = require('jwt-decode');
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
function aJWT() {
|
||||
return "A JWT provided by user"
|
||||
}
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// jwt-decode
|
||||
// no signature verification
|
||||
jwt_decode(UserToken) // NOT OK
|
||||
})();
|
||||
@@ -0,0 +1,33 @@
|
||||
const express = require('express')
|
||||
const jwt_simple = require('jwt-simple');
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
function aJWT() {
|
||||
return "A JWT provided by user"
|
||||
}
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// BAD: no signature verification
|
||||
jwt_simple.decode(UserToken, getSecret(), true); // NOT OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// GOOD: all with with signature verification
|
||||
jwt_simple.decode(UserToken, getSecret(), false); // OK
|
||||
jwt_simple.decode(UserToken, getSecret()); // OK
|
||||
})();
|
||||
|
||||
(function () {
|
||||
const UserToken = aJwt()
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwt_simple.decode(UserToken, getSecret(), true); // OK
|
||||
jwt_simple.decode(UserToken, getSecret()); // OK
|
||||
})();
|
||||
@@ -0,0 +1,49 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
const jwtJsonwebtoken = require('jsonwebtoken');
|
||||
const port = 3000
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
app.get('/jwtJsonwebtoken1', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// BAD: no signature verification
|
||||
jwtJsonwebtoken.decode(UserToken) // NOT OK
|
||||
})
|
||||
|
||||
app.get('/jwtJsonwebtoken2', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// BAD: no signature verification
|
||||
jwtJsonwebtoken.decode(UserToken) // NOT OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret(), { algorithms: ["HS256", "none"] }) // NOT OK
|
||||
})
|
||||
|
||||
app.get('/jwtJsonwebtoken3', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// GOOD: with signature verification
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret()) // OK
|
||||
})
|
||||
|
||||
app.get('/jwtJsonwebtoken4', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwtJsonwebtoken.decode(UserToken) // OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret()) // OK
|
||||
})
|
||||
|
||||
app.get('/jwtJsonwebtoken5', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwtJsonwebtoken.decode(UserToken) // OK
|
||||
jwtJsonwebtoken.verify(UserToken, getSecret(), { algorithms: ["HS256"] }) // OK
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`)
|
||||
})
|
||||
@@ -0,0 +1,161 @@
|
||||
nodes
|
||||
| JsonWebToken.js:10:11:10:47 | UserToken |
|
||||
| JsonWebToken.js:10:23:10:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:10:23:10:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:13:28:13:36 | UserToken |
|
||||
| JsonWebToken.js:13:28:13:36 | UserToken |
|
||||
| JsonWebToken.js:17:11:17:47 | UserToken |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:20:28:20:36 | UserToken |
|
||||
| JsonWebToken.js:20:28:20:36 | UserToken |
|
||||
| JsonWebToken.js:21:28:21:36 | UserToken |
|
||||
| JsonWebToken.js:21:28:21:36 | UserToken |
|
||||
| JsonWebToken.js:25:11:25:47 | UserToken |
|
||||
| JsonWebToken.js:25:23:25:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:25:23:25:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:28:28:28:36 | UserToken |
|
||||
| JsonWebToken.js:28:28:28:36 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:35:28:35:36 | UserToken |
|
||||
| JsonWebToken.js:35:28:35:36 | UserToken |
|
||||
| JsonWebToken.js:36:28:36:36 | UserToken |
|
||||
| JsonWebToken.js:36:28:36:36 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization |
|
||||
| JsonWebToken.js:43:28:43:36 | UserToken |
|
||||
| JsonWebToken.js:43:28:43:36 | UserToken |
|
||||
| JsonWebToken.js:44:28:44:36 | UserToken |
|
||||
| JsonWebToken.js:44:28:44:36 | UserToken |
|
||||
| jose.js:11:11:11:47 | UserToken |
|
||||
| jose.js:11:23:11:47 | req.hea ... ization |
|
||||
| jose.js:11:23:11:47 | req.hea ... ization |
|
||||
| jose.js:13:20:13:28 | UserToken |
|
||||
| jose.js:13:20:13:28 | UserToken |
|
||||
| jose.js:18:11:18:47 | UserToken |
|
||||
| jose.js:18:23:18:47 | req.hea ... ization |
|
||||
| jose.js:18:23:18:47 | req.hea ... ization |
|
||||
| jose.js:20:26:20:34 | UserToken |
|
||||
| jose.js:20:26:20:34 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization |
|
||||
| jose.js:26:20:26:28 | UserToken |
|
||||
| jose.js:26:20:26:28 | UserToken |
|
||||
| jose.js:27:26:27:34 | UserToken |
|
||||
| jose.js:27:26:27:34 | UserToken |
|
||||
| jwtDecode.js:11:11:11:47 | UserToken |
|
||||
| jwtDecode.js:11:23:11:47 | req.hea ... ization |
|
||||
| jwtDecode.js:11:23:11:47 | req.hea ... ization |
|
||||
| jwtDecode.js:15:16:15:24 | UserToken |
|
||||
| jwtDecode.js:15:16:15:24 | UserToken |
|
||||
| jwtSimple.js:10:11:10:47 | UserToken |
|
||||
| jwtSimple.js:10:23:10:47 | req.hea ... ization |
|
||||
| jwtSimple.js:10:23:10:47 | req.hea ... ization |
|
||||
| jwtSimple.js:13:23:13:31 | UserToken |
|
||||
| jwtSimple.js:13:23:13:31 | UserToken |
|
||||
| jwtSimple.js:17:11:17:47 | UserToken |
|
||||
| jwtSimple.js:17:23:17:47 | req.hea ... ization |
|
||||
| jwtSimple.js:17:23:17:47 | req.hea ... ization |
|
||||
| jwtSimple.js:20:23:20:31 | UserToken |
|
||||
| jwtSimple.js:20:23:20:31 | UserToken |
|
||||
| jwtSimple.js:21:23:21:31 | UserToken |
|
||||
| jwtSimple.js:21:23:21:31 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization |
|
||||
| jwtSimple.js:28:23:28:31 | UserToken |
|
||||
| jwtSimple.js:28:23:28:31 | UserToken |
|
||||
| jwtSimple.js:29:23:29:31 | UserToken |
|
||||
| jwtSimple.js:29:23:29:31 | UserToken |
|
||||
edges
|
||||
| JsonWebToken.js:10:11:10:47 | UserToken | JsonWebToken.js:13:28:13:36 | UserToken |
|
||||
| JsonWebToken.js:10:11:10:47 | UserToken | JsonWebToken.js:13:28:13:36 | UserToken |
|
||||
| JsonWebToken.js:10:23:10:47 | req.hea ... ization | JsonWebToken.js:10:11:10:47 | UserToken |
|
||||
| JsonWebToken.js:10:23:10:47 | req.hea ... ization | JsonWebToken.js:10:11:10:47 | UserToken |
|
||||
| JsonWebToken.js:17:11:17:47 | UserToken | JsonWebToken.js:20:28:20:36 | UserToken |
|
||||
| JsonWebToken.js:17:11:17:47 | UserToken | JsonWebToken.js:20:28:20:36 | UserToken |
|
||||
| JsonWebToken.js:17:11:17:47 | UserToken | JsonWebToken.js:21:28:21:36 | UserToken |
|
||||
| JsonWebToken.js:17:11:17:47 | UserToken | JsonWebToken.js:21:28:21:36 | UserToken |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:17:11:17:47 | UserToken |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:17:11:17:47 | UserToken |
|
||||
| JsonWebToken.js:25:11:25:47 | UserToken | JsonWebToken.js:28:28:28:36 | UserToken |
|
||||
| JsonWebToken.js:25:11:25:47 | UserToken | JsonWebToken.js:28:28:28:36 | UserToken |
|
||||
| JsonWebToken.js:25:23:25:47 | req.hea ... ization | JsonWebToken.js:25:11:25:47 | UserToken |
|
||||
| JsonWebToken.js:25:23:25:47 | req.hea ... ization | JsonWebToken.js:25:11:25:47 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken | JsonWebToken.js:35:28:35:36 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken | JsonWebToken.js:35:28:35:36 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken | JsonWebToken.js:36:28:36:36 | UserToken |
|
||||
| JsonWebToken.js:32:11:32:47 | UserToken | JsonWebToken.js:36:28:36:36 | UserToken |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization | JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization | JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization | JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:32:23:32:47 | req.hea ... ization | JsonWebToken.js:32:11:32:47 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken | JsonWebToken.js:43:28:43:36 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken | JsonWebToken.js:43:28:43:36 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken | JsonWebToken.js:44:28:44:36 | UserToken |
|
||||
| JsonWebToken.js:40:11:40:47 | UserToken | JsonWebToken.js:44:28:44:36 | UserToken |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization | JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization | JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization | JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| JsonWebToken.js:40:23:40:47 | req.hea ... ization | JsonWebToken.js:40:11:40:47 | UserToken |
|
||||
| jose.js:11:11:11:47 | UserToken | jose.js:13:20:13:28 | UserToken |
|
||||
| jose.js:11:11:11:47 | UserToken | jose.js:13:20:13:28 | UserToken |
|
||||
| jose.js:11:23:11:47 | req.hea ... ization | jose.js:11:11:11:47 | UserToken |
|
||||
| jose.js:11:23:11:47 | req.hea ... ization | jose.js:11:11:11:47 | UserToken |
|
||||
| jose.js:18:11:18:47 | UserToken | jose.js:20:26:20:34 | UserToken |
|
||||
| jose.js:18:11:18:47 | UserToken | jose.js:20:26:20:34 | UserToken |
|
||||
| jose.js:18:23:18:47 | req.hea ... ization | jose.js:18:11:18:47 | UserToken |
|
||||
| jose.js:18:23:18:47 | req.hea ... ization | jose.js:18:11:18:47 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken | jose.js:26:20:26:28 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken | jose.js:26:20:26:28 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken | jose.js:27:26:27:34 | UserToken |
|
||||
| jose.js:24:11:24:47 | UserToken | jose.js:27:26:27:34 | UserToken |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization | jose.js:24:11:24:47 | UserToken |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization | jose.js:24:11:24:47 | UserToken |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization | jose.js:24:11:24:47 | UserToken |
|
||||
| jose.js:24:23:24:47 | req.hea ... ization | jose.js:24:11:24:47 | UserToken |
|
||||
| jwtDecode.js:11:11:11:47 | UserToken | jwtDecode.js:15:16:15:24 | UserToken |
|
||||
| jwtDecode.js:11:11:11:47 | UserToken | jwtDecode.js:15:16:15:24 | UserToken |
|
||||
| jwtDecode.js:11:23:11:47 | req.hea ... ization | jwtDecode.js:11:11:11:47 | UserToken |
|
||||
| jwtDecode.js:11:23:11:47 | req.hea ... ization | jwtDecode.js:11:11:11:47 | UserToken |
|
||||
| jwtSimple.js:10:11:10:47 | UserToken | jwtSimple.js:13:23:13:31 | UserToken |
|
||||
| jwtSimple.js:10:11:10:47 | UserToken | jwtSimple.js:13:23:13:31 | UserToken |
|
||||
| jwtSimple.js:10:23:10:47 | req.hea ... ization | jwtSimple.js:10:11:10:47 | UserToken |
|
||||
| jwtSimple.js:10:23:10:47 | req.hea ... ization | jwtSimple.js:10:11:10:47 | UserToken |
|
||||
| jwtSimple.js:17:11:17:47 | UserToken | jwtSimple.js:20:23:20:31 | UserToken |
|
||||
| jwtSimple.js:17:11:17:47 | UserToken | jwtSimple.js:20:23:20:31 | UserToken |
|
||||
| jwtSimple.js:17:11:17:47 | UserToken | jwtSimple.js:21:23:21:31 | UserToken |
|
||||
| jwtSimple.js:17:11:17:47 | UserToken | jwtSimple.js:21:23:21:31 | UserToken |
|
||||
| jwtSimple.js:17:23:17:47 | req.hea ... ization | jwtSimple.js:17:11:17:47 | UserToken |
|
||||
| jwtSimple.js:17:23:17:47 | req.hea ... ization | jwtSimple.js:17:11:17:47 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken | jwtSimple.js:28:23:28:31 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken | jwtSimple.js:28:23:28:31 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken | jwtSimple.js:29:23:29:31 | UserToken |
|
||||
| jwtSimple.js:25:11:25:47 | UserToken | jwtSimple.js:29:23:29:31 | UserToken |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization | jwtSimple.js:25:11:25:47 | UserToken |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization | jwtSimple.js:25:11:25:47 | UserToken |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization | jwtSimple.js:25:11:25:47 | UserToken |
|
||||
| jwtSimple.js:25:23:25:47 | req.hea ... ization | jwtSimple.js:25:11:25:47 | UserToken |
|
||||
#select
|
||||
| JsonWebToken.js:10:23:10:47 | req.hea ... ization | JsonWebToken.js:10:23:10:47 | req.hea ... ization | JsonWebToken.js:13:28:13:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:13:28:13:36 | UserToken | without signature verification |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:20:28:20:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:20:28:20:36 | UserToken | without signature verification |
|
||||
| JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:17:23:17:47 | req.hea ... ization | JsonWebToken.js:21:28:21:36 | UserToken | Decoding JWT $@. | JsonWebToken.js:21:28:21:36 | UserToken | without signature verification |
|
||||
| jose.js:11:23:11:47 | req.hea ... ization | jose.js:11:23:11:47 | req.hea ... ization | jose.js:13:20:13:28 | UserToken | Decoding JWT $@. | jose.js:13:20:13:28 | UserToken | without signature verification |
|
||||
| jwtDecode.js:11:23:11:47 | req.hea ... ization | jwtDecode.js:11:23:11:47 | req.hea ... ization | jwtDecode.js:15:16:15:24 | UserToken | Decoding JWT $@. | jwtDecode.js:15:16:15:24 | UserToken | without signature verification |
|
||||
| jwtSimple.js:10:23:10:47 | req.hea ... ization | jwtSimple.js:10:23:10:47 | req.hea ... ization | jwtSimple.js:13:23:13:31 | UserToken | Decoding JWT $@. | jwtSimple.js:13:23:13:31 | UserToken | without signature verification |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-347/decodeJwtWithoutVerification.ql
|
||||
@@ -0,0 +1,32 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
const jose = require('jose')
|
||||
const port = 3000
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
app.get('/jose1', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
// no signature verification
|
||||
jose.decodeJwt(UserToken) // NOT OK
|
||||
})
|
||||
|
||||
|
||||
app.get('/jose2', async (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
// with signature verification
|
||||
await jose.jwtVerify(UserToken, new TextEncoder().encode(getSecret())) // OK
|
||||
})
|
||||
|
||||
app.get('/jose3', async (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
// first without signature verification then with signature verification for same UserToken
|
||||
jose.decodeJwt(UserToken) // OK
|
||||
await jose.jwtVerify(UserToken, new TextEncoder().encode(getSecret())) // OK
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`)
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
const jwt_decode = require('jwt-decode');
|
||||
const port = 3000
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
|
||||
app.get('/jwtDecode', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// jwt-decode
|
||||
// no signature verification
|
||||
jwt_decode(UserToken) // NOT OK
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`)
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
const jwt_simple = require('jwt-simple');
|
||||
const port = 3000
|
||||
|
||||
function getSecret() {
|
||||
return "A Safe generated random key"
|
||||
}
|
||||
app.get('/jwtSimple1', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// no signature verification
|
||||
jwt_simple.decode(UserToken, getSecret(), true); // NOT OK
|
||||
})
|
||||
|
||||
app.get('/jwtSimple2', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// GOOD: all with with signature verification
|
||||
jwt_simple.decode(UserToken, getSecret(), false); // OK
|
||||
jwt_simple.decode(UserToken, getSecret()); // OK
|
||||
})
|
||||
|
||||
app.get('/jwtSimple3', (req, res) => {
|
||||
const UserToken = req.headers.authorization;
|
||||
|
||||
// GOOD: first without signature verification then with signature verification for same UserToken
|
||||
jwt_simple.decode(UserToken, getSecret(), true); // OK
|
||||
jwt_simple.decode(UserToken, getSecret()); // OK
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`)
|
||||
})
|
||||
Reference in New Issue
Block a user