Skip to content

Commit 61e60de

Browse files
committed
JS: Model readline as a stdin threat-model source
Technically not always true, but my assumption is that +90% of the time that's what it will be used for, so while we could be more precise by adding a taint-step from the `input` part of the construction, I'm not sure it's worth it in this case. Furthermore, doing so would break with the current way we model threat-model sources, and how sources are generally modeled in JS... so for a very pretty setup it would require changing all the other `file` threat-model sources to start at the constructors such as `fs.createReadStream()` and have taint-propagation steps towards the actual use (like we do in Python)... I couldn't see an easy path forwards for doing this while keeping the Concepts integration, so I opted for the simpler solution here.
1 parent eca8bf5 commit 61e60de

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.model.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ extensions:
88
- ['fs', 'Member[promises].Member[readFile].ReturnValue.Member[then].Argument[0].Parameter[0]', 'file']
99
- ['global', 'Member[process].Member[stdin].Member[read].ReturnValue', 'stdin']
1010
- ['global', 'Member[process].Member[stdin].Member[on,addListener].WithStringArgument[0=data].Argument[1].Parameter[0]', 'stdin']
11+
- ['readline', 'Member[createInterface].ReturnValue.Member[question].Argument[1].Parameter[0]', 'stdin']
12+
- ['readline', 'Member[createInterface].ReturnValue.Member[on,addListener].WithStringArgument[0=line].Argument[1].Parameter[0]', 'stdin']

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ SINK(data); // $ hasFlow
8484
// using readline
8585
const readline = require('readline');
8686
const rl_file = readline.createInterface({
87-
input: fs.createReadStream('file.txt') // $ MISSING: threat-source=file
87+
input: fs.createReadStream('file.txt')
8888
});
89-
rl_file.on("line", (line) => {
90-
SINK(line); // $ MISSING: hasFlow
89+
rl_file.on("line", (line) => { // $ SPURIOUS: threat-source=stdin MISSING: threat-source=file
90+
SINK(line); // $ hasFlow
9191
});
9292

9393

@@ -104,17 +104,17 @@ SINK(stdin_line); // $ hasFlow
104104
// Accessing stdin using readline
105105
const readline = require('readline');
106106
const rl_stdin = readline.createInterface({
107-
input: process.stdin // $ MISSING: threat-source=stdin
107+
input: process.stdin
108108
});
109-
rl_stdin.question('<question>', (answer) => {
110-
SINK(answer); // $ MISSING: hasFlow
109+
rl_stdin.question('<question>', (answer) => { // $ threat-source=stdin
110+
SINK(answer); // $ hasFlow
111111
});
112112

113-
function handler(answer) {
114-
SINK(answer); // $ MISSING: hasFlow
113+
function handler(answer) { // $ threat-source=stdin
114+
SINK(answer); // $ hasFlow
115115
}
116116
rl_stdin.question('<question>', handler);
117117

118-
rl_stdin.on("line", (line) => {
119-
SINK(line); // $ MISSING: hasFlow
118+
rl_stdin.on("line", (line) => { // $ threat-source=stdin
119+
SINK(line); // $ hasFlow
120120
});

0 commit comments

Comments
 (0)