Skip to content

Commit bb97829

Browse files
committed
add a model for the ClientRequest new require("net").Socket()
1 parent d5097d8 commit bb97829

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,53 @@ module ClientRequest {
389389
}
390390
}
391391

392+
/**
393+
* Gets an instantiation `socket` of `require("net").Socket` type tracked using `t`.
394+
*/
395+
private DataFlow::SourceNode netSocketInstantiation(
396+
DataFlow::TypeTracker t, DataFlow::NewNode socket
397+
) {
398+
t.start() and
399+
socket = DataFlow::moduleMember("net", "Socket").getAnInstantiation() and
400+
result = socket
401+
or
402+
exists(DataFlow::TypeTracker t2 | result = netSocketInstantiation(t2, socket).track(t2, t))
403+
}
404+
405+
/**
406+
* A model of a request made using `(new require("net").Socket()).connect(args);`.
407+
*/
408+
class NetSocketRequest extends ClientRequest::Range {
409+
DataFlow::NewNode socket;
410+
411+
NetSocketRequest() {
412+
this = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMethodCall("connect")
413+
}
414+
415+
override DataFlow::Node getUrl() {
416+
result = getArgument([0, 1]) // there are multiple overrides of `connect`, and the URL can be in the first or second argument.
417+
}
418+
419+
override DataFlow::Node getHost() { result = getOptionArgument(0, "host") }
420+
421+
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
422+
responseType = "text" and
423+
promise = false and
424+
exists(DataFlow::CallNode call |
425+
call = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMemberCall("on") and
426+
call.getArgument(0).mayHaveStringValue("data") and
427+
result = call.getABoundCallbackParameter(1, 0)
428+
)
429+
}
430+
431+
override DataFlow::Node getADataNode() {
432+
exists(DataFlow::CallNode call |
433+
call = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMemberCall("write") and
434+
result = call.getArgument(0)
435+
)
436+
}
437+
}
438+
392439
/**
393440
* A model of a URL request made using the `superagent` library.
394441
*/

javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ test_ClientRequest
6666
| tst.js:200:2:200:21 | $.get("example.php") |
6767
| tst.js:202:5:208:7 | $.ajax( ... }}) |
6868
| tst.js:210:2:210:21 | $.get("example.php") |
69+
| tst.js:219:5:219:41 | data.so ... Host"}) |
6970
test_getADataNode
7071
| tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data |
7172
| tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 |
@@ -95,11 +96,13 @@ test_getADataNode
9596
| tst.js:179:2:179:60 | $.getJS ... a ) {}) | tst.js:179:31:179:38 | "MyData" |
9697
| tst.js:183:2:183:60 | $.post( ... ) { }) | tst.js:183:28:183:37 | "PostData" |
9798
| tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | tst.js:190:11:190:20 | "AjaxData" |
99+
| tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:223:23:223:30 | "foobar" |
98100
test_getHost
99101
| tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host |
100102
| tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host |
101103
| tst.js:91:5:91:34 | got(rel ... host}) | tst.js:91:29:91:32 | host |
102104
| tst.js:93:5:93:35 | net.req ... host }) | tst.js:93:29:93:32 | host |
105+
| tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:32:219:39 | "myHost" |
103106
test_getUrl
104107
| tst.js:11:5:11:16 | request(url) | tst.js:11:13:11:15 | url |
105108
| tst.js:13:5:13:20 | request.get(url) | tst.js:13:17:13:19 | url |
@@ -173,6 +176,7 @@ test_getUrl
173176
| tst.js:200:2:200:21 | $.get("example.php") | tst.js:200:8:200:20 | "example.php" |
174177
| tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:203:10:203:22 | "example.php" |
175178
| tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:8:210:20 | "example.php" |
179+
| tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:25:219:40 | {host: "myHost"} |
176180
test_getAResponseDataNode
177181
| tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true |
178182
| tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true |
@@ -233,3 +237,4 @@ test_getAResponseDataNode
233237
| tst.js:200:2:200:21 | $.get("example.php") | tst.js:200:37:200:44 | response | | false |
234238
| tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:207:21:207:36 | err.responseText | json | false |
235239
| tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:55:210:70 | xhr.responseText | | false |
240+
| tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:221:29:221:32 | data | text | false |

javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,16 @@ import {ClientRequest, net} from 'electron';
209209

210210
$.get("example.php").fail(function(xhr) {console.log(xhr.responseText)});
211211
});
212+
213+
const net = require("net");
214+
(function () {
215+
var data = {
216+
socket: new net.Socket()
217+
}
218+
219+
data.socket.connect({host: "myHost"});
220+
221+
data.socket.on("data", (data) => {});
222+
223+
data.socket.write("foobar");
224+
})();

0 commit comments

Comments
 (0)