Skip to content

Commit 082967a

Browse files
committed
add EventEmitter models for net.createServer() and respjs.
1 parent a2e54b1 commit 082967a

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,4 +962,88 @@ module NodeJSLib {
962962

963963
override EventRegistration::Range getAReceiver() { emitter.getBaseEmitter() = result.getEmitter().(NodeJSEventEmitter).getBaseEmitter() }
964964
}
965+
966+
/**
967+
* An instance of net.createServer(), which creates a new TCP/IPC server.
968+
*/
969+
private class NodeJSNetServer extends DataFlow::SourceNode {
970+
NodeJSNetServer() { this = DataFlow::moduleMember("net", "createServer").getAnInvocation() }
971+
972+
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
973+
t.start() and result = this
974+
or
975+
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
976+
}
977+
978+
/**
979+
* Gets a reference to this server.
980+
*/
981+
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
982+
}
983+
984+
/**
985+
* A connection opened on a NodeJS net server.
986+
*/
987+
private class NodeJSNetServerConnection extends EventEmitter::Range {
988+
NodeJSNetServer server;
989+
990+
NodeJSNetServerConnection() {
991+
exists(DataFlow::MethodCallNode call |
992+
call = server.ref().getAMethodCall("on") and
993+
call.getArgument(0).mayHaveStringValue("connection")
994+
|
995+
this = call.getCallback(1).getParameter(0)
996+
)
997+
}
998+
999+
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
1000+
}
1001+
1002+
/**
1003+
* A registration of an event handler on a NodeJS net server instance.
1004+
*/
1005+
private class NodeJSNetServerRegistration extends EventRegistration::DefaultEventRegistration,
1006+
DataFlow::MethodCallNode {
1007+
override NodeJSNetServerConnection emitter;
1008+
1009+
NodeJSNetServerRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
1010+
}
1011+
1012+
/**
1013+
* A data flow node representing data received from a client to a NodeJS net server, viewed as remote user input.
1014+
*/
1015+
private class NodeJSNetServerItemAsRemoteFlow extends RemoteFlowSource {
1016+
NodeJSNetServerRegistration reg;
1017+
1018+
NodeJSNetServerItemAsRemoteFlow() { this = reg.getReceivedItem(_) }
1019+
1020+
override string getSourceType() { result = "NodeJS server" }
1021+
}
1022+
1023+
/**
1024+
* An instantiation of the `respjs` library, which is an EventEmitter.
1025+
*/
1026+
private class RespJS extends NodeJSEventEmitter {
1027+
RespJS() {
1028+
this = DataFlow::moduleImport("respjs").getAnInstantiation()
1029+
}
1030+
}
1031+
1032+
/**
1033+
* A event dispatch that serializes the input data and emits the result on the "data" channel.
1034+
*/
1035+
private class RespWrite extends EventDispatch::DefaultEventDispatch,
1036+
DataFlow::MethodCallNode {
1037+
override RespJS emitter;
1038+
1039+
RespWrite() { this = emitter.ref().getAMethodCall("write") }
1040+
1041+
override string getChannel() {
1042+
result = "data"
1043+
}
1044+
1045+
override DataFlow::Node getSentItem(int i) {
1046+
i = 0 and result = this.getArgument(i)
1047+
}
1048+
}
9651049
}

0 commit comments

Comments
 (0)