@@ -47,6 +47,20 @@ private predicate areLibrariesCompatible(
47
47
( client = LibraryNames:: ws ( ) or client = LibraryNames:: websocket ( ) )
48
48
}
49
49
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
+
50
64
/**
51
65
* Provides classes that model WebSockets clients.
52
66
*/
@@ -56,7 +70,7 @@ module ClientWebSocket {
56
70
/**
57
71
* A class that can be used to instantiate a WebSocket instance.
58
72
*/
59
- class SocketClass extends DataFlow:: SourceNode {
73
+ deprecated class SocketClass extends DataFlow:: SourceNode {
60
74
LibraryName library ; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
61
75
62
76
SocketClass ( ) {
@@ -78,13 +92,38 @@ module ClientWebSocket {
78
92
LibraryName getLibrary ( ) { result = library }
79
93
}
80
94
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
+
81
120
/**
82
121
* A client WebSocket instance.
83
122
*/
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 ;
86
125
87
- ClientSocket ( ) { this = socketClass .getAnInstantiation ( ) }
126
+ ClientSocket ( ) { this = socketClass .getAnInvocation ( ) }
88
127
89
128
/**
90
129
* Gets the WebSocket library name.
@@ -115,10 +154,10 @@ module ClientWebSocket {
115
154
/**
116
155
* A message sent from a WebSocket client.
117
156
*/
118
- class SendNode extends EventDispatch:: Range , DataFlow :: CallNode {
157
+ class SendNode extends EventDispatch:: Range , API :: CallNode {
119
158
override ClientSocket emitter ;
120
159
121
- SendNode ( ) { this = emitter .getAMemberCall ( "send" ) }
160
+ SendNode ( ) { this = emitter .getReturn ( ) . getMember ( "send" ) . getACall ( ) }
122
161
123
162
override string getChannel ( ) { result = channelName ( ) }
124
163
@@ -145,8 +184,8 @@ module ClientWebSocket {
145
184
private DataFlow:: FunctionNode getAMessageHandler (
146
185
ClientWebSocket:: ClientSocket emitter , string methodName
147
186
) {
148
- exists ( DataFlow :: CallNode call |
149
- call = emitter .getAMemberCall ( methodName ) and
187
+ exists ( API :: CallNode call |
188
+ call = emitter .getReturn ( ) . getMember ( methodName ) . getACall ( ) and
150
189
call .getArgument ( 0 ) .mayHaveStringValue ( "message" ) and
151
190
result = call .getCallback ( 1 )
152
191
)
@@ -161,7 +200,13 @@ module ClientWebSocket {
161
200
WebSocketReceiveNode ( ) {
162
201
this = getAMessageHandler ( emitter , "addEventListener" )
163
202
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
+ )
165
210
}
166
211
167
212
override DataFlow:: Node getReceivedItem ( int i ) {
@@ -192,19 +237,30 @@ module ServerWebSocket {
192
237
/**
193
238
* Gets a server created by a library named `library`.
194
239
*/
195
- DataFlow:: SourceNode getAServer ( LibraryName library ) {
240
+ deprecated DataFlow:: SourceNode getAServer ( LibraryName library ) {
196
241
library = ws ( ) and
197
242
result = DataFlow:: moduleImport ( "ws" ) .getAConstructorInvocation ( "Server" )
198
243
or
199
244
library = sockjs ( ) and
200
245
result = DataFlow:: moduleImport ( "sockjs" ) .getAMemberCall ( "createServer" )
201
246
}
202
247
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
+
203
259
/**
204
260
* Gets a `socket.on("connection", (msg, req) => {})` call.
205
261
*/
206
262
private DataFlow:: CallNode getAConnectionCall ( LibraryName library ) {
207
- result = getAServer ( library ) .getAMemberCall ( EventEmitter:: on ( ) ) and
263
+ result = getAServerInvocation ( library ) .getReturn ( ) . getMember ( EventEmitter:: on ( ) ) . getACall ( ) and
208
264
result .getArgument ( 0 ) .mayHaveStringValue ( "connection" )
209
265
}
210
266
@@ -324,15 +380,18 @@ module ServerWebSocket {
324
380
result = this .getCallback ( 1 ) .getParameter ( 0 )
325
381
}
326
382
}
383
+ }
327
384
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
+ }
333
393
334
- override string getSourceType ( ) { result = "WebSocket client data" }
394
+ override string getSourceType ( ) { result = "WebSocket transmitted data" }
335
395
336
- override predicate isUserControlledObject ( ) { any ( ) }
337
- }
396
+ override predicate isUserControlledObject ( ) { any ( ) }
338
397
}
0 commit comments