@@ -390,7 +390,7 @@ module Express {
390
390
}
391
391
392
392
/** An Express response source. */
393
- abstract private class ResponseSource extends HTTP:: Servers:: ResponseSource { }
393
+ abstract class ResponseSource extends HTTP:: Servers:: ResponseSource { }
394
394
395
395
/**
396
396
* An Express response source, that is, the response parameter of a
@@ -421,7 +421,7 @@ module Express {
421
421
}
422
422
423
423
/** An Express request source. */
424
- abstract private class RequestSource extends HTTP:: Servers:: RequestSource { }
424
+ abstract class RequestSource extends HTTP:: Servers:: RequestSource { }
425
425
426
426
/**
427
427
* An Express request source, that is, the request parameter of a
@@ -465,73 +465,98 @@ module Express {
465
465
* Gets a reference to the "query" object from a request-object originating from route-handler `rh`.
466
466
*/
467
467
DataFlow:: SourceNode getAQueryObjectReference ( DataFlow:: TypeTracker t , RouteHandler rh ) {
468
- t .startInProp ( "query" ) and
469
- result = rh .getARequestSource ( )
470
- or
471
- exists ( DataFlow:: TypeTracker t2 | result = getAQueryObjectReference ( t2 , rh ) .track ( t2 , t ) )
468
+ result = queryRef ( rh .getARequestSource ( ) , t )
472
469
}
473
470
474
471
/**
475
472
* Gets a reference to the "params" object from a request-object originating from route-handler `rh`.
476
473
*/
477
474
DataFlow:: SourceNode getAParamsObjectReference ( DataFlow:: TypeTracker t , RouteHandler rh ) {
478
- t .startInProp ( "params" ) and
479
- result = rh .getARequestSource ( )
475
+ result = paramsRef ( rh .getARequestSource ( ) , t )
476
+ }
477
+
478
+ /** The input parameter to an `app.param()` route handler. */
479
+ private class ParamHandlerInputAccess extends HTTP:: RequestInputAccess {
480
+ RouteHandler rh ;
481
+
482
+ ParamHandlerInputAccess ( ) {
483
+ exists ( RouteSetup setup | rh = setup .getARouteHandler ( ) |
484
+ this = DataFlow:: parameterNode ( rh .getRouteHandlerParameter ( "parameter" ) )
485
+ )
486
+ }
487
+
488
+ override HTTP:: RouteHandler getRouteHandler ( ) { result = rh }
489
+
490
+ override string getKind ( ) { result = "parameter" }
491
+ }
492
+
493
+ /** Gets a data flow node referring to `req.query`. */
494
+ private DataFlow:: SourceNode queryRef ( RequestSource req , DataFlow:: TypeTracker t ) {
495
+ t .start ( ) and
496
+ result = req .ref ( ) .getAPropertyRead ( "query" )
497
+ or
498
+ exists ( DataFlow:: TypeTracker t2 | result = queryRef ( req , t2 ) .track ( t2 , t ) )
499
+ }
500
+
501
+ /** Gets a data flow node referring to `req.query`. */
502
+ private DataFlow:: SourceNode queryRef ( RequestSource req ) {
503
+ result = queryRef ( req , DataFlow:: TypeTracker:: end ( ) )
504
+ }
505
+
506
+ /** Gets a data flow node referring to `req.params`. */
507
+ private DataFlow:: SourceNode paramsRef ( RequestSource req , DataFlow:: TypeTracker t ) {
508
+ t .start ( ) and
509
+ result = req .ref ( ) .getAPropertyRead ( "params" )
480
510
or
481
- exists ( DataFlow:: TypeTracker t2 | result = getAParamsObjectReference ( t2 , rh ) .track ( t2 , t ) )
511
+ exists ( DataFlow:: TypeTracker t2 | result = paramsRef ( req , t2 ) .track ( t2 , t ) )
512
+ }
513
+
514
+ /** Gets a data flow node referring to `req.params`. */
515
+ private DataFlow:: SourceNode paramsRef ( RequestSource req ) {
516
+ result = paramsRef ( req , DataFlow:: TypeTracker:: end ( ) )
482
517
}
483
518
484
519
/**
485
520
* An access to a user-controlled Express request input.
486
521
*/
487
522
class RequestInputAccess extends HTTP:: RequestInputAccess {
488
- RouteHandler rh ;
523
+ RequestSource request ;
489
524
string kind ;
490
525
491
526
RequestInputAccess ( ) {
492
527
kind = "parameter" and
493
- this =
494
- [
495
- getAQueryObjectReference ( DataFlow:: TypeTracker:: end ( ) , rh ) ,
496
- getAParamsObjectReference ( DataFlow:: TypeTracker:: end ( ) , rh )
497
- ] .getAPropertyRead ( )
528
+ this = [ queryRef ( request ) , paramsRef ( request ) ] .getAPropertyRead ( )
498
529
or
499
- exists ( DataFlow:: SourceNode request | request = rh . getARequestSource ( ) .ref ( ) |
530
+ exists ( DataFlow:: SourceNode ref | ref = request .ref ( ) |
500
531
kind = "parameter" and
501
- this = request .getAMethodCall ( "param" )
532
+ this = ref .getAMethodCall ( "param" )
502
533
or
503
534
// `req.originalUrl`
504
535
kind = "url" and
505
- this = request .getAPropertyRead ( "originalUrl" )
536
+ this = ref .getAPropertyRead ( "originalUrl" )
506
537
or
507
538
// `req.cookies`
508
539
kind = "cookie" and
509
- this = request .getAPropertyRead ( "cookies" )
540
+ this = ref .getAPropertyRead ( "cookies" )
510
541
or
511
542
// `req.files`, treated the same as `req.body`.
512
543
// `express-fileupload` uses .files, and `multer` uses .files or .file
513
544
kind = "body" and
514
- this = request .getAPropertyRead ( [ "files" , "file" ] )
515
- )
516
- or
517
- kind = "body" and
518
- this .asExpr ( ) = rh .getARequestBodyAccess ( )
519
- or
520
- // `value` in `router.param('foo', (req, res, next, value) => { ... })`
521
- kind = "parameter" and
522
- exists ( RouteSetup setup | rh = setup .getARouteHandler ( ) |
523
- this = DataFlow:: parameterNode ( rh .getRouteHandlerParameter ( "parameter" ) )
545
+ this = ref .getAPropertyRead ( [ "files" , "file" ] )
546
+ or
547
+ kind = "body" and
548
+ this = ref .getAPropertyRead ( "body" )
524
549
)
525
550
}
526
551
527
- override RouteHandler getRouteHandler ( ) { result = rh }
552
+ override RouteHandler getRouteHandler ( ) { result = request . getRouteHandler ( ) }
528
553
529
554
override string getKind ( ) { result = kind }
530
555
531
556
override predicate isUserControlledObject ( ) {
532
557
kind = "body" and
533
558
exists ( ExpressLibraries:: BodyParser bodyParser , RouteHandlerExpr expr |
534
- expr .getBody ( ) = rh and
559
+ expr .getBody ( ) = request . getRouteHandler ( ) and
535
560
bodyParser .producesUserControlledObjects ( ) and
536
561
bodyParser .flowsToExpr ( expr .getAMatchingAncestor ( ) )
537
562
)
@@ -542,43 +567,26 @@ module Express {
542
567
forall ( ExpressLibraries:: BodyParser bodyParser | bodyParser .producesUserControlledObjects ( ) )
543
568
or
544
569
kind = "parameter" and
545
- exists ( DataFlow:: Node request | request = DataFlow:: valueNode ( rh .getARequestExpr ( ) ) |
546
- this .( DataFlow:: MethodCallNode ) .calls ( request , "param" )
547
- )
570
+ this = request .ref ( ) .getAMethodCall ( "param" )
548
571
or
549
572
// `req.query.name`
550
573
kind = "parameter" and
551
- this = getAQueryObjectReference ( DataFlow :: TypeTracker :: end ( ) , rh ) .getAPropertyRead ( )
574
+ this = queryRef ( request ) .getAPropertyRead ( )
552
575
}
553
576
}
554
577
555
578
/**
556
579
* An access to a header on an Express request.
557
580
*/
558
581
private class RequestHeaderAccess extends HTTP:: RequestHeaderAccess {
559
- RouteHandler rh ;
582
+ RequestSource request ;
560
583
561
584
RequestHeaderAccess ( ) {
562
- exists ( DataFlow:: Node request | request = DataFlow:: valueNode ( rh .getARequestExpr ( ) ) |
563
- exists ( string methodName |
564
- // `req.get(...)` or `req.header(...)`
565
- this .( DataFlow:: MethodCallNode ) .calls ( request , methodName )
566
- |
567
- methodName = "get" or
568
- methodName = "header"
569
- )
570
- or
571
- exists ( DataFlow:: PropRead headers |
572
- // `req.headers.name`
573
- headers .accesses ( request , "headers" ) and
574
- this = headers .getAPropertyRead ( )
575
- )
576
- or
577
- exists ( string propName | propName = "host" or propName = "hostname" |
578
- // `req.host` and `req.hostname` are derived from headers
579
- this .( DataFlow:: PropRead ) .accesses ( request , propName )
580
- )
581
- )
585
+ this = request .ref ( ) .getAMethodCall ( [ "get" , "header" ] )
586
+ or
587
+ this = request .ref ( ) .getAPropertyRead ( "headers" ) .getAPropertyRead ( )
588
+ or
589
+ this = request .ref ( ) .getAPropertyRead ( [ "host" , "hostname" ] )
582
590
}
583
591
584
592
override string getAHeaderName ( ) {
@@ -591,22 +599,15 @@ module Express {
591
599
)
592
600
}
593
601
594
- override RouteHandler getRouteHandler ( ) { result = rh }
602
+ override RouteHandler getRouteHandler ( ) { result = request . getRouteHandler ( ) }
595
603
596
604
override string getKind ( ) { result = "header" }
597
605
}
598
606
599
607
/**
600
608
* HTTP headers created by Express calls
601
609
*/
602
- abstract private class ExplicitHeader extends HTTP:: ExplicitHeaderDefinition {
603
- Expr response ;
604
-
605
- /**
606
- * Gets the response expression that this header is set on.
607
- */
608
- Expr getResponse ( ) { result = response }
609
- }
610
+ abstract private class ExplicitHeader extends HTTP:: ExplicitHeaderDefinition { }
610
611
611
612
/**
612
613
* Holds if `e` is an HTTP request object.
@@ -635,16 +636,13 @@ module Express {
635
636
* An invocation of the `redirect` method of an HTTP response object.
636
637
*/
637
638
private class RedirectInvocation extends HTTP:: RedirectInvocation , MethodCallExpr {
638
- RouteHandler rh ;
639
+ ResponseSource response ;
639
640
640
- RedirectInvocation ( ) {
641
- getReceiver ( ) = rh .getAResponseExpr ( ) and
642
- getMethodName ( ) = "redirect"
643
- }
641
+ RedirectInvocation ( ) { this = response .ref ( ) .getAMethodCall ( "redirect" ) .asExpr ( ) }
644
642
645
643
override Expr getUrlArgument ( ) { result = getLastArgument ( ) }
646
644
647
- override RouteHandler getRouteHandler ( ) { result = rh }
645
+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
648
646
}
649
647
650
648
/**
@@ -662,21 +660,18 @@ module Express {
662
660
* An invocation of the `set` or `header` method on an HTTP response object that
663
661
* sets multiple headers.
664
662
*/
665
- class SetMultipleHeaders extends ExplicitHeader , DataFlow:: ValueNode {
666
- override MethodCallExpr astNode ;
667
- RouteHandler rh ;
663
+ class SetMultipleHeaders extends ExplicitHeader , DataFlow:: MethodCallNode {
664
+ ResponseSource response ;
668
665
669
666
SetMultipleHeaders ( ) {
670
- astNode .getReceiver ( ) = rh .getAResponseExpr ( ) and
671
- response = astNode .getReceiver ( ) and
672
- astNode .getMethodName ( ) = any ( string n | n = "set" or n = "header" ) and
673
- astNode .getNumArgument ( ) = 1
667
+ this = response .ref ( ) .getAMethodCall ( [ "set" , "header" ] ) and
668
+ getNumArgument ( ) = 1
674
669
}
675
670
676
671
/**
677
672
* Gets a reference to the multiple headers object that is to be set.
678
673
*/
679
- private DataFlow:: SourceNode getAHeaderSource ( ) { result .flowsToExpr ( astNode . getArgument ( 0 ) ) }
674
+ private DataFlow:: SourceNode getAHeaderSource ( ) { result .flowsTo ( getArgument ( 0 ) ) }
680
675
681
676
override predicate definesExplicitly ( string headerName , Expr headerValue ) {
682
677
exists ( string header |
@@ -685,7 +680,7 @@ module Express {
685
680
)
686
681
}
687
682
688
- override RouteHandler getRouteHandler ( ) { result = rh }
683
+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
689
684
690
685
override Expr getNameExpr ( ) {
691
686
exists ( DataFlow:: PropWrite write | getAHeaderSource ( ) .getAPropertyWrite ( ) = write |
@@ -705,31 +700,26 @@ module Express {
705
700
* An argument passed to the `send` or `end` method of an HTTP response object.
706
701
*/
707
702
private class ResponseSendArgument extends HTTP:: ResponseSendArgument {
708
- RouteHandler rh ;
703
+ ResponseSource response ;
709
704
710
- ResponseSendArgument ( ) {
711
- exists ( MethodCallExpr mce |
712
- mce .calls ( rh .getAResponseExpr ( ) , "send" ) and
713
- this = mce .getArgument ( 0 )
714
- )
715
- }
705
+ ResponseSendArgument ( ) { this = response .ref ( ) .getAMethodCall ( "send" ) .getArgument ( 0 ) .asExpr ( ) }
716
706
717
- override RouteHandler getRouteHandler ( ) { result = rh }
707
+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
718
708
}
719
709
720
710
/**
721
711
* An invocation of the `cookie` method on an HTTP response object.
722
712
*/
723
713
class SetCookie extends HTTP:: CookieDefinition , MethodCallExpr {
724
- RouteHandler rh ;
714
+ ResponseSource response ;
725
715
726
- SetCookie ( ) { calls ( rh . getAResponseExpr ( ) , "cookie" ) }
716
+ SetCookie ( ) { this = response . ref ( ) . getAMethodCall ( "cookie" ) . asExpr ( ) }
727
717
728
718
override Expr getNameArgument ( ) { result = getArgument ( 0 ) }
729
719
730
720
override Expr getValueArgument ( ) { result = getArgument ( 1 ) }
731
721
732
- override RouteHandler getRouteHandler ( ) { result = rh }
722
+ override RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
733
723
}
734
724
735
725
/**
@@ -750,19 +740,19 @@ module Express {
750
740
* An object passed to the `render` method of an HTTP response object.
751
741
*/
752
742
class TemplateObjectInput extends DataFlow:: Node {
753
- RouteHandler rh ;
743
+ ResponseSource response ;
754
744
755
745
TemplateObjectInput ( ) {
756
746
exists ( DataFlow:: MethodCallNode render |
757
- render . calls ( rh . getAResponseExpr ( ) . flow ( ) , "render" ) and
747
+ render = response . ref ( ) . getAMethodCall ( "render" ) and
758
748
this = render .getArgument ( 1 )
759
749
)
760
750
}
761
751
762
752
/**
763
753
* Gets the route handler that uses this object.
764
754
*/
765
- RouteHandler getRouteHandler ( ) { result = rh }
755
+ RouteHandler getRouteHandler ( ) { result = response . getRouteHandler ( ) }
766
756
}
767
757
768
758
/**
0 commit comments