@@ -261,28 +261,74 @@ module ClientRequest {
261
261
}
262
262
263
263
/**
264
- * A model of a URL request made using an implementation of the `fetch` API .
264
+ * Provides predicates for working with `fetch` and its platform-specific instances as a single module .
265
265
*/
266
- class FetchUrlRequest extends ClientRequest:: Range {
267
- DataFlow:: Node url ;
268
-
269
- FetchUrlRequest ( ) {
270
- this = NodeJSLib:: Fetch:: moduleImport ( ) and
271
- url = getArgument ( 0 )
266
+ module Fetch {
267
+ /**
268
+ * Gets a node that refers to `fetch`, or an import of one of its platform-specific instances.
269
+ */
270
+ DataFlow:: SourceNode moduleImport ( ) {
271
+ result = DataFlow:: moduleImport ( [ "node-fetch" , "cross-fetch" , "isomorphic-fetch" ] )
272
+ or
273
+ result = DataFlow:: globalVarRef ( "fetch" ) // https://fetch.spec.whatwg.org/#fetch-api
272
274
}
273
275
274
- override DataFlow:: Node getUrl ( ) { result = url }
276
+ /**
277
+ * Gets an instance of the `Headers` class.
278
+ */
279
+ private DataFlow:: NewNode header ( ) {
280
+ result = moduleImport ( ) .getAConstructorInvocation ( "Headers" )
281
+ or
282
+ result = DataFlow:: globalVarRef ( "Headers" ) .getAnInstantiation ( ) // https://fetch.spec.whatwg.org/#headers-class
283
+ }
275
284
276
- override DataFlow:: Node getHost ( ) { none ( ) }
285
+ /** An expression that is used as a credential in fetch-request. */
286
+ private class FetchAuthorization extends CredentialsExpr {
287
+ FetchAuthorization ( ) {
288
+ exists ( DataFlow:: Node headerObject |
289
+ headerObject = header ( ) .getArgument ( 0 )
290
+ or
291
+ headerObject = moduleImport ( ) .getACall ( ) .getOptionArgument ( 1 , "headers" )
292
+ |
293
+ this = headerObject .getALocalSource ( ) .getAPropertyWrite ( "Authorization" ) .getRhs ( ) .asExpr ( )
294
+ )
295
+ or
296
+ exists ( DataFlow:: MethodCallNode appendCall |
297
+ appendCall = header ( ) .getAMethodCall ( [ "append" , "set" ] ) and
298
+ appendCall .getArgument ( 0 ) .mayHaveStringValue ( "Authorization" ) and
299
+ this = appendCall .getArgument ( 1 ) .asExpr ( )
300
+ )
301
+ }
277
302
278
- override DataFlow:: Node getADataNode ( ) {
279
- exists ( string name | name = "headers" or name = "body" | result = getOptionArgument ( 1 , name ) )
303
+ override string getCredentialsKind ( ) { result = "authorization headers" }
280
304
}
281
305
282
- override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
283
- responseType = "fetch.response" and
284
- promise = true and
285
- result = this
306
+ /**
307
+ * A model of a URL request made using an implementation of the `fetch` API.
308
+ */
309
+ class FetchUrlRequest extends ClientRequest:: Range {
310
+ DataFlow:: Node url ;
311
+
312
+ FetchUrlRequest ( ) {
313
+ this = moduleImport ( ) .getACall ( ) and
314
+ url = getArgument ( 0 )
315
+ }
316
+
317
+ override DataFlow:: Node getUrl ( ) { result = url }
318
+
319
+ override DataFlow:: Node getHost ( ) { none ( ) }
320
+
321
+ override DataFlow:: Node getADataNode ( ) {
322
+ exists ( string name | name = "headers" or name = "body" |
323
+ result = getOptionArgument ( 1 , name )
324
+ )
325
+ }
326
+
327
+ override DataFlow:: Node getAResponseDataNode ( string responseType , boolean promise ) {
328
+ responseType = "fetch.response" and
329
+ promise = true and
330
+ result = this
331
+ }
286
332
}
287
333
}
288
334
0 commit comments