mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
Merge branch 'amammad-js-JWT' of https://github.com/amammad/codeql into amammad-js-JWT
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);
|
||||
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import {
|
||||
BaseEntity, Brackets, DataSource, JoinColumn, NotBrackets
|
||||
, OneToOne, Entity, PrimaryGeneratedColumn, Column, SelectQueryBuilder, InsertQueryBuilder
|
||||
} from "typeorm";
|
||||
|
||||
@Entity()
|
||||
export class UserActiveRecord extends BaseEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
static findByName(firstName: string, lastName: string) {
|
||||
return this.createQueryBuilder("user")
|
||||
.where("user.firstName = " + firstName) // test: SQLInjectionPoint
|
||||
.andWhere("user.lastName = " + lastName) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
}
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Profile {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
gender: string
|
||||
@Column()
|
||||
photo: string
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
name: string
|
||||
@OneToOne(() => Profile)
|
||||
@JoinColumn()
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User2 {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: "database.sqlite",
|
||||
synchronize: true,
|
||||
logging: false,
|
||||
entities: [User, User2, Profile, UserActiveRecord],
|
||||
migrations: [],
|
||||
subscribers: [],
|
||||
})
|
||||
|
||||
function makePaginationQuery<T>(q: SelectQueryBuilder<T>): SelectQueryBuilder<T> {
|
||||
return q;
|
||||
}
|
||||
|
||||
AppDataSource.initialize().then(async () => {
|
||||
const BadInput = "A user controllable Remote Source like `' 1=1 --` "
|
||||
|
||||
// Active record
|
||||
await UserActiveRecord.findByName(BadInput, "Saw")
|
||||
|
||||
// data mapper
|
||||
const selectQueryBuilder = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User").select());
|
||||
selectQueryBuilder.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const selectQueryBuilder2 = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User"));
|
||||
selectQueryBuilder2.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const insertQueryBuilder: InsertQueryBuilder<User2> = AppDataSource
|
||||
.createQueryBuilder(User2, "User2").insert();
|
||||
insertQueryBuilder.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
}).execute().then(result => {
|
||||
console.log(result)
|
||||
|
||||
|
||||
})
|
||||
|
||||
AppDataSource
|
||||
.createQueryBuilder(User2, "User")
|
||||
.insert()
|
||||
.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
})
|
||||
.orUpdate(
|
||||
[BadInput, BadInput], // test: SQLInjectionPoint
|
||||
[BadInput], // test: SQLInjectionPoint
|
||||
)
|
||||
.getQueryAndParameters()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("user2")
|
||||
.update(User2)
|
||||
.set({ firstName: () => BadInput, lastName: "Saw2", age: 12 }) // test: SQLInjectionPoint
|
||||
.where(BadInput,) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder('user2')
|
||||
.delete()
|
||||
.from(User2)
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
|
||||
const queryRunner = AppDataSource.createQueryRunner()
|
||||
await queryRunner.query(BadInput) // test: SQLInjectionPoint
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder(User2, "User")
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.where(BadInput).execute() // test: SQLInjectionPoint
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.innerJoin("User.profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.leftJoinAndMapOne("User.profile", "profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.where((qb) => {
|
||||
const subQuery = qb
|
||||
.subQuery()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "user2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.getQuery()
|
||||
return "User2.id IN " + subQuery
|
||||
})
|
||||
.setParameter("registered", true)
|
||||
.getMany()
|
||||
|
||||
|
||||
// Using repository
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("User2").where("User2.id =:kind" + BadInput, { kind: 1 }).getMany()
|
||||
|
||||
// Using DataSource
|
||||
await AppDataSource
|
||||
.createQueryBuilder()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "User2")
|
||||
.where(BadInput, { id: 1 }) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
|
||||
// Using entity manager
|
||||
await AppDataSource.manager
|
||||
.createQueryBuilder(User2, "User2").where("User2.id =:kind" + BadInput, { kind: '1' }).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.leftJoinAndSelect("user.photos", "photo", BadInput).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").groupBy("User2.id").having(BadInput).getMany() // test: SQLInjectionPoint
|
||||
// orderBy
|
||||
// it is a little bit restrictive, e.g. sqlite don't support it at all
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").where(BadInput, { // test: SQLInjectionPoint
|
||||
firstName: "Timber",
|
||||
})
|
||||
.where(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
)
|
||||
.orderBy(BadInput).orWhere(BadInput).getMany() // test: SQLInjectionPoint
|
||||
|
||||
// relation
|
||||
AppDataSource.createQueryBuilder().relation(User, "name")
|
||||
.of(User)
|
||||
.select().where(BadInput).getMany().then(results => { // test: SQLInjectionPoint
|
||||
console.log(results)
|
||||
})
|
||||
|
||||
// Brackets
|
||||
await AppDataSource.createQueryBuilder(User2, "User2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
).andWhere(
|
||||
new NotBrackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput) // test: SQLInjectionPoint
|
||||
}),
|
||||
).getMany()
|
||||
}).catch(error => console.log(error))
|
||||
32
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
32
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
@@ -0,0 +1,32 @@
|
||||
passingPositiveTests
|
||||
| PASSED | SQLInjectionPoint | test.ts:19:54:19:79 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:20:55:20:80 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:82:70:82:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:88:70:88:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:97:41:97:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:111:41:111:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:115:37:115:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:116:27:116:52 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:122:74:122:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:123:29:123:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:129:28:129:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:134:41:134:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:138:29:138:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:139:38:139:63 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:143:61:143:86 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:149:80:149:105 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:159:37:159:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:161:36:161:61 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:175:29:175:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:177:39:177:64 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:182:108:182:133 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:185:74:185:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:187:94:187:119 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:191:65:191:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:196:57:196:82 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:199:58:199:83 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:204:65:204:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:210:28:210:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:213:56:213:81 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:217:56:217:81 | // test ... onPoint |
|
||||
failingPositiveTests
|
||||
34
javascript/ql/test/experimental/TypeOrm/tests.ql
Normal file
34
javascript/ql/test/experimental/TypeOrm/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.SQL
|
||||
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "SQLInjectionPoint" and
|
||||
exists(SQL::SqlString n | t.inNode(n))
|
||||
}
|
||||
|
||||
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "SQLInjectionPoint" and
|
||||
not exists(SQL::SqlString n | t.inNode(n))
|
||||
}
|
||||
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"es5",
|
||||
"es6"
|
||||
],
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./build",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user