@@ -47,6 +47,20 @@ private predicate areLibrariesCompatible(
4747 ( client = LibraryNames:: ws ( ) or client = LibraryNames:: websocket ( ) )
4848}
4949
50+ /** Treats `WebSocket` as an entry point for API graphs. */
51+ private class WebSocketEntryPoint extends API:: EntryPoint {
52+ WebSocketEntryPoint ( ) { this = "global.WebSocket" }
53+
54+ override DataFlow:: SourceNode getASource ( ) { result = DataFlow:: globalVarRef ( "WebSocket" ) }
55+ }
56+
57+ /** Treats `SockJS` as an entry point for API graphs. */
58+ private class SockJSEntryPoint extends API:: EntryPoint {
59+ SockJSEntryPoint ( ) { this = "global.SockJS" }
60+
61+ override DataFlow:: SourceNode getASource ( ) { result = DataFlow:: globalVarRef ( "SockJS" ) }
62+ }
63+
5064/**
5165 * Provides classes that model WebSockets clients.
5266 */
@@ -56,7 +70,7 @@ module ClientWebSocket {
5670 /**
5771 * A class that can be used to instantiate a WebSocket instance.
5872 */
59- class SocketClass extends DataFlow:: SourceNode {
73+ deprecated class SocketClass extends DataFlow:: SourceNode {
6074 LibraryName library ; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
6175
6276 SocketClass ( ) {
@@ -78,13 +92,38 @@ module ClientWebSocket {
7892 LibraryName getLibrary ( ) { result = library }
7993 }
8094
95+ /**
96+ * A class that can be used to instantiate a WebSocket instance.
97+ */
98+ class WebSocketClass extends API:: Node {
99+ LibraryName library ; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
100+
101+ WebSocketClass ( ) {
102+ this = any ( WebSocketEntryPoint e ) .getANode ( ) and library = websocket ( )
103+ or
104+ this = API:: moduleImport ( "ws" ) and library = ws ( )
105+ or
106+ // the sockjs-client library:https://www.npmjs.com/package/sockjs-client
107+ library = sockjs ( ) and
108+ (
109+ this = API:: moduleImport ( "sockjs-client" ) or
110+ this = any ( SockJSEntryPoint e ) .getANode ( )
111+ )
112+ }
113+
114+ /**
115+ * Gets the WebSocket library name.
116+ */
117+ LibraryName getLibrary ( ) { result = library }
118+ }
119+
81120 /**
82121 * A client WebSocket instance.
83122 */
84- class ClientSocket extends EventEmitter:: Range , DataFlow :: NewNode , ClientRequest:: Range {
85- SocketClass socketClass ;
123+ class ClientSocket extends EventEmitter:: Range , API :: NewNode , ClientRequest:: Range {
124+ WebSocketClass socketClass ;
86125
87- ClientSocket ( ) { this = socketClass .getAnInstantiation ( ) }
126+ ClientSocket ( ) { this = socketClass .getAnInvocation ( ) }
88127
89128 /**
90129 * Gets the WebSocket library name.
@@ -115,10 +154,10 @@ module ClientWebSocket {
115154 /**
116155 * A message sent from a WebSocket client.
117156 */
118- class SendNode extends EventDispatch:: Range , DataFlow :: CallNode {
157+ class SendNode extends EventDispatch:: Range , API :: CallNode {
119158 override ClientSocket emitter ;
120159
121- SendNode ( ) { this = emitter .getAMemberCall ( "send" ) }
160+ SendNode ( ) { this = emitter .getReturn ( ) . getMember ( "send" ) . getACall ( ) }
122161
123162 override string getChannel ( ) { result = channelName ( ) }
124163
@@ -145,8 +184,8 @@ module ClientWebSocket {
145184 private DataFlow:: FunctionNode getAMessageHandler (
146185 ClientWebSocket:: ClientSocket emitter , string methodName
147186 ) {
148- exists ( DataFlow :: CallNode call |
149- call = emitter .getAMemberCall ( methodName ) and
187+ exists ( API :: CallNode call |
188+ call = emitter .getReturn ( ) . getMember ( methodName ) . getACall ( ) and
150189 call .getArgument ( 0 ) .mayHaveStringValue ( "message" ) and
151190 result = call .getCallback ( 1 )
152191 )
@@ -161,7 +200,13 @@ module ClientWebSocket {
161200 WebSocketReceiveNode ( ) {
162201 this = getAMessageHandler ( emitter , "addEventListener" )
163202 or
164- this = emitter .getAPropertyWrite ( "onmessage" ) .getRhs ( )
203+ this = emitter .getReturn ( ) .getMember ( "onmessage" ) .getAValueReachingSink ( )
204+ or
205+ exists ( DataFlow:: MethodCallNode bindCall |
206+ bindCall = emitter .getReturn ( ) .getMember ( "onmessage" ) .getAValueReachingSink ( ) and
207+ bindCall .getMethodName ( ) = "bind" and
208+ this = bindCall .getReceiver ( ) .getAFunctionValue ( )
209+ )
165210 }
166211
167212 override DataFlow:: Node getReceivedItem ( int i ) {
@@ -192,19 +237,30 @@ module ServerWebSocket {
192237 /**
193238 * Gets a server created by a library named `library`.
194239 */
195- DataFlow:: SourceNode getAServer ( LibraryName library ) {
240+ deprecated DataFlow:: SourceNode getAServer ( LibraryName library ) {
196241 library = ws ( ) and
197242 result = DataFlow:: moduleImport ( "ws" ) .getAConstructorInvocation ( "Server" )
198243 or
199244 library = sockjs ( ) and
200245 result = DataFlow:: moduleImport ( "sockjs" ) .getAMemberCall ( "createServer" )
201246 }
202247
248+ /**
249+ * Gets a server created by a library named `library`.
250+ */
251+ API:: InvokeNode getAServerInvocation ( LibraryName library ) {
252+ library = ws ( ) and
253+ result = API:: moduleImport ( "ws" ) .getMember ( "Server" ) .getAnInvocation ( )
254+ or
255+ library = sockjs ( ) and
256+ result = API:: moduleImport ( "sockjs" ) .getMember ( "createServer" ) .getAnInvocation ( )
257+ }
258+
203259 /**
204260 * Gets a `socket.on("connection", (msg, req) => {})` call.
205261 */
206262 private DataFlow:: CallNode getAConnectionCall ( LibraryName library ) {
207- result = getAServer ( library ) .getAMemberCall ( EventEmitter:: on ( ) ) and
263+ result = getAServerInvocation ( library ) .getReturn ( ) . getMember ( EventEmitter:: on ( ) ) . getACall ( ) and
208264 result .getArgument ( 0 ) .mayHaveStringValue ( "connection" )
209265 }
210266
@@ -324,15 +380,18 @@ module ServerWebSocket {
324380 result = this .getCallback ( 1 ) .getParameter ( 0 )
325381 }
326382 }
383+ }
327384
328- /**
329- * A data flow node representing data received from a client, viewed as remote user input.
330- */
331- private class ReceivedItemAsRemoteFlow extends RemoteFlowSource {
332- ReceivedItemAsRemoteFlow ( ) { this = any ( ReceiveNode rercv ) .getReceivedItem ( _) }
385+ /**
386+ * A data flow node representing data received from a client or server, viewed as remote user input.
387+ */
388+ private class ReceivedItemAsRemoteFlow extends RemoteFlowSource {
389+ ReceivedItemAsRemoteFlow ( ) {
390+ this = any ( ClientWebSocket:: ReceiveNode rercv ) .getReceivedItem ( _) or
391+ this = any ( ServerWebSocket:: ReceiveNode rercv ) .getReceivedItem ( _)
392+ }
333393
334- override string getSourceType ( ) { result = "WebSocket client data" }
394+ override string getSourceType ( ) { result = "WebSocket transmitted data" }
335395
336- override predicate isUserControlledObject ( ) { any ( ) }
337- }
396+ override predicate isUserControlledObject ( ) { any ( ) }
338397}
0 commit comments