Skip to content

Commit 2b6c27e

Browse files
committed
JS: Add initial file threat-model support
However, as indicated by the `MISSING` annotations, we could do better.
1 parent 3656864 commit 2b6c27e

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

javascript/ql/lib/semmle/javascript/Concepts.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@ abstract class FileSystemReadAccess extends FileSystemAccess {
122122
abstract DataFlow::Node getADataNode();
123123
}
124124

125+
/**
126+
* A FileSystemReadAccess seen as a ThreatModelSource.
127+
*/
128+
private class FileSystemReadAccessAsThreatModelSource extends ThreatModelSource::Range {
129+
FileSystemReadAccessAsThreatModelSource() {
130+
this = any(FileSystemReadAccess access).getADataNode()
131+
}
132+
133+
override string getThreatModel() { result = "file" }
134+
135+
override string getSourceType() { result = "FileSystemReadAccess" }
136+
}
137+
125138
/**
126139
* A data flow node that writes data to the file system.
127140
*/

javascript/ql/test/library-tests/threat-models/sources/sources.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,37 @@ connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
5555
SINK(results[0]); // $ hasFlow
5656
SINK(results[0].solution); // $ hasFlow
5757
});
58+
59+
// ------ reading from file ------
60+
61+
// Accessing file contents using fs
62+
const fs = require('fs');
63+
fs.readFile('file.txt', 'utf8', (err, data) => { // $ MISSING: threat-source=file
64+
SINK(data); // $ MISSING: hasFlow
65+
});
66+
67+
// Accessing file contents using fs.readFileSync
68+
const fileContent = fs.readFileSync('file.txt', 'utf8'); // $ threat-source=file
69+
SINK(fileContent); // $ hasFlow
70+
71+
// Accessing file contents using fs.promises
72+
fs.promises.readFile('file.txt', 'utf8').then((data) => { // $ MISSING: threat-source=file
73+
SINK(data); // $ MISSING: hasFlow
74+
});
75+
76+
// Accessing file contents using fs.createReadStream
77+
const readStream = fs.createReadStream('file.txt');
78+
readStream.on('data', (chunk) => { // $ threat-source=file
79+
SINK(chunk); // $ hasFlow
80+
});
81+
const data = readStream.read(); // $ threat-source=file
82+
SINK(data); // $ hasFlow
83+
84+
// using readline
85+
const readline = require('readline');
86+
const rl_file = readline.createInterface({
87+
input: fs.createReadStream('file.txt') // $ MISSING: threat-source=file
88+
});
89+
rl_file.on("line", (line) => {
90+
SINK(line); // $ MISSING: hasFlow
91+
});

0 commit comments

Comments
 (0)