Skip to content

Commit 6fb047a

Browse files
authored
Merge pull request github#3451 from erik-krogh/fstreamWrite
Approved by esbena
2 parents ee84832 + 83d34b9 commit 6fb047a

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

change-notes/1.25/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## General improvements
44

55
* Support for the following frameworks and libraries has been improved:
6+
- [fstream](https://www.npmjs.com/package/fstream)
67
- [jGrowl](https://github.com/stanlemon/jGrowl)
78
- [jQuery](https://jquery.com/)
89

javascript/ql/src/semmle/javascript/frameworks/Files.qll

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,14 @@ private module FStream {
151151
/**
152152
* Gets a reference to a method in the `fstream` library.
153153
*/
154-
private DataFlow::SourceNode getAnFStreamProperty() {
154+
private DataFlow::SourceNode getAnFStreamProperty(boolean writer) {
155155
exists(DataFlow::SourceNode mod, string readOrWrite, string subMod |
156156
mod = DataFlow::moduleImport("fstream") and
157-
(readOrWrite = "Reader" or readOrWrite = "Writer") and
157+
(
158+
readOrWrite = "Reader" and writer = false
159+
or
160+
readOrWrite = "Writer" and writer = true
161+
) and
158162
(subMod = "File" or subMod = "Dir" or subMod = "Link" or subMod = "Proxy")
159163
|
160164
result = mod.getAPropertyRead(readOrWrite) or
@@ -167,7 +171,9 @@ private module FStream {
167171
* An invocation of a method defined in the `fstream` library.
168172
*/
169173
private class FStream extends FileSystemAccess, DataFlow::InvokeNode {
170-
FStream() { this = getAnFStreamProperty().getAnInvocation() }
174+
boolean writer;
175+
176+
FStream() { this = getAnFStreamProperty(writer).getAnInvocation() }
171177

172178
override DataFlow::Node getAPathArgument() {
173179
result = getOptionArgument(0, "path")
@@ -176,6 +182,24 @@ private module FStream {
176182
result = getArgument(0)
177183
}
178184
}
185+
186+
/**
187+
* An invocation of an `fstream` method that writes to a file.
188+
*/
189+
private class FStreamWriter extends FileSystemWriteAccess, FStream {
190+
FStreamWriter() { writer = true }
191+
192+
override DataFlow::Node getADataNode() { none() }
193+
}
194+
195+
/**
196+
* An invocation of an `fstream` method that reads a file.
197+
*/
198+
private class FStreamReader extends FileSystemReadAccess, FStream {
199+
FStreamReader() { writer = false }
200+
201+
override DataFlow::Node getADataNode() { none() }
202+
}
179203
}
180204

181205
/**

javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlip.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ nodes
1616
| ZipSlipBad.js:7:22:7:31 | entry.path |
1717
| ZipSlipBad.js:8:37:8:44 | fileName |
1818
| ZipSlipBad.js:8:37:8:44 | fileName |
19+
| ZipSlipBad.js:15:11:15:31 | fileName |
20+
| ZipSlipBad.js:15:22:15:31 | entry.path |
21+
| ZipSlipBad.js:15:22:15:31 | entry.path |
22+
| ZipSlipBad.js:16:30:16:37 | fileName |
23+
| ZipSlipBad.js:16:30:16:37 | fileName |
1924
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName |
2025
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path |
2126
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path |
@@ -33,6 +38,10 @@ edges
3338
| ZipSlipBad.js:7:11:7:31 | fileName | ZipSlipBad.js:8:37:8:44 | fileName |
3439
| ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:7:11:7:31 | fileName |
3540
| ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:7:11:7:31 | fileName |
41+
| ZipSlipBad.js:15:11:15:31 | fileName | ZipSlipBad.js:16:30:16:37 | fileName |
42+
| ZipSlipBad.js:15:11:15:31 | fileName | ZipSlipBad.js:16:30:16:37 | fileName |
43+
| ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:15:11:15:31 | fileName |
44+
| ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:15:11:15:31 | fileName |
3645
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName | ZipSlipBadUnzipper.js:8:37:8:44 | fileName |
3746
| ZipSlipBadUnzipper.js:7:9:7:29 | fileName | ZipSlipBadUnzipper.js:8:37:8:44 | fileName |
3847
| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:7:9:7:29 | fileName |
@@ -42,4 +51,5 @@ edges
4251
| TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | TarSlipBad.js:6:36:6:46 | header.name | item path |
4352
| ZipSlipBad2.js:6:22:6:29 | fileName | ZipSlipBad2.js:5:37:5:46 | entry.path | ZipSlipBad2.js:6:22:6:29 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad2.js:5:37:5:46 | entry.path | item path |
4453
| ZipSlipBad.js:8:37:8:44 | fileName | ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:7:22:7:31 | entry.path | item path |
54+
| ZipSlipBad.js:16:30:16:37 | fileName | ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:16:30:16:37 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:15:22:15:31 | entry.path | item path |
4555
| ZipSlipBadUnzipper.js:8:37:8:44 | fileName | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | item path |

javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlipBad.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ fs.createReadStream('archive.zip')
77
const fileName = entry.path;
88
entry.pipe(fs.createWriteStream(fileName));
99
});
10+
11+
var Writer = require('fstream').Writer;
12+
fs.createReadStream('archive.zip')
13+
.pipe(unzip.Parse())
14+
.on('entry', entry => {
15+
const fileName = entry.path;
16+
entry.pipe(Writer({path: fileName}));
17+
});

0 commit comments

Comments
 (0)