@@ -21,42 +21,91 @@ private module MongoDB {
2121 /**
2222 * Gets an access to `mongodb.MongoClient`.
2323 */
24- DataFlow:: SourceNode getAMongoClient ( ) { result = mongodb ( ) .getAPropertyRead ( "MongoClient" ) }
24+ private DataFlow:: SourceNode getAMongoClient ( DataFlow:: TypeTracker t ) {
25+ t .start ( ) and
26+ result = mongodb ( ) .getAPropertyRead ( "MongoClient" )
27+ or
28+ exists ( DataFlow:: TypeTracker t2 | result = getAMongoClient ( t2 ) .track ( t2 , t ) )
29+ }
30+
31+ /**
32+ * Gets an access to `mongodb.MongoClient`.
33+ */
34+ DataFlow:: SourceNode getAMongoClient ( ) { result = getAMongoClient ( DataFlow:: TypeTracker:: end ( ) ) }
35+
36+ /** Gets a data flow node that leads to a `connect` callback. */
37+ private DataFlow:: SourceNode getAMongoDbCallback ( DataFlow:: TypeBackTracker t ) {
38+ t .start ( ) and
39+ result = getAMongoClient ( ) .getAMemberCall ( "connect" ) .getArgument ( 1 ) .getALocalSource ( )
40+ or
41+ exists ( DataFlow:: TypeBackTracker t2 | result = getAMongoDbCallback ( t2 ) .backtrack ( t2 , t ) )
42+ }
43+
44+ /** Gets a data flow node that leads to a `connect` callback. */
45+ private DataFlow:: FunctionNode getAMongoDbCallback ( ) {
46+ result = getAMongoDbCallback ( DataFlow:: TypeBackTracker:: end ( ) )
47+ }
2548
2649 /**
2750 * Gets an expression that may refer to a MongoDB database connection.
2851 */
29- DataFlow:: SourceNode getAMongoDb ( ) {
30- result = getAMongoClient ( ) .getAMemberCall ( "connect" ) .getCallback ( 1 ) .getParameter ( 1 )
52+ private DataFlow:: SourceNode getAMongoDb ( DataFlow:: TypeTracker t ) {
53+ t .start ( ) and
54+ result = getAMongoDbCallback ( ) .getParameter ( 1 )
55+ or
56+ exists ( DataFlow:: TypeTracker t2 | result = getAMongoDb ( t2 ) .track ( t2 , t ) )
3157 }
3258
3359 /**
34- * An expression that may hold a MongoDB collection.
60+ * Gets an expression that may refer to a MongoDB database connection.
61+ */
62+ DataFlow:: SourceNode getAMongoDb ( ) { result = getAMongoDb ( DataFlow:: TypeTracker:: end ( ) ) }
63+
64+ /**
65+ * A data flow node that may hold a MongoDB collection.
3566 */
36- abstract class Collection extends Expr { }
67+ abstract class Collection extends DataFlow :: SourceNode { }
3768
3869 /**
3970 * A collection resulting from calling `Db.collection(...)`.
4071 */
4172 private class CollectionFromDb extends Collection {
4273 CollectionFromDb ( ) {
43- exists ( DataFlow:: CallNode collection |
44- collection = getAMongoDb ( ) .getAMethodCall ( "collection" )
45- |
46- collection .flowsToExpr ( this )
47- or
48- collection .getCallback ( 1 ) .getParameter ( 0 ) .flowsToExpr ( this )
49- )
74+ this = getAMongoDb ( ) .getAMethodCall ( "collection" )
75+ or
76+ this = getAMongoDb ( ) .getAMethodCall ( "collection" ) .getCallback ( 1 ) .getParameter ( 0 )
5077 }
5178 }
5279
80+ /**
81+ * A collection based on the type `mongodb.Collection`.
82+ *
83+ * Note that this also covers `mongoose` models since they are subtypes
84+ * of `mongodb.Collection`.
85+ */
86+ private class CollectionFromType extends Collection {
87+ CollectionFromType ( ) {
88+ hasUnderlyingType ( "mongodb" , "Collection" )
89+ }
90+ }
91+
92+ /** Gets a data flow node referring to a MongoDB collection. */
93+ private DataFlow:: SourceNode getACollection ( DataFlow:: TypeTracker t ) {
94+ t .start ( ) and
95+ result instanceof Collection
96+ or
97+ exists ( DataFlow:: TypeTracker t2 | result = getACollection ( t2 ) .track ( t2 , t ) )
98+ }
99+
100+ /** Gets a data flow node referring to a MongoDB collection. */
101+ DataFlow:: SourceNode getACollection ( ) { result = getACollection ( DataFlow:: TypeTracker:: end ( ) ) }
102+
53103 /** A call to a MongoDB query method. */
54- private class QueryCall extends DatabaseAccess , DataFlow:: ValueNode {
55- override MethodCallExpr astNode ;
104+ private class QueryCall extends DatabaseAccess , DataFlow:: MethodCallNode {
56105 int queryArgIdx ;
57106
58107 QueryCall ( ) {
59- exists ( string m | asExpr ( ) .( MethodCallExpr ) . calls ( any ( Collection c ) , m ) |
108+ exists ( string m | this = getACollection ( ) .getAMethodCall ( m ) |
60109 m = "aggregate" and queryArgIdx = 0
61110 or
62111 m = "count" and queryArgIdx = 0
@@ -91,9 +140,7 @@ private module MongoDB {
91140 )
92141 }
93142
94- override DataFlow:: Node getAQueryArgument ( ) {
95- result = DataFlow:: valueNode ( astNode .getArgument ( queryArgIdx ) )
96- }
143+ override DataFlow:: Node getAQueryArgument ( ) { result = getArgument ( queryArgIdx ) }
97144 }
98145
99146 /**
@@ -116,15 +163,15 @@ private module Mongoose {
116163 /**
117164 * Gets a call to `mongoose.createConnection`.
118165 */
119- MethodCallExpr createConnection ( ) {
120- result = getAMongooseInstance ( ) .getAMemberCall ( "createConnection" ) . asExpr ( )
166+ DataFlow :: CallNode createConnection ( ) {
167+ result = getAMongooseInstance ( ) .getAMemberCall ( "createConnection" )
121168 }
122169
123170 /**
124171 * A Mongoose collection object.
125172 */
126173 class Model extends MongoDB:: Collection {
127- Model ( ) { getAMongooseInstance ( ) .getAMemberCall ( "model" ) . flowsToExpr ( this ) }
174+ Model ( ) { this = getAMongooseInstance ( ) .getAMemberCall ( "model" ) }
128175 }
129176
130177 /**
@@ -134,7 +181,7 @@ private module Mongoose {
134181 string kind ;
135182
136183 Credentials ( ) {
137- exists ( string prop | createConnection ( ) .hasOptionArgument ( 3 , prop , this ) |
184+ exists ( string prop | this = createConnection ( ) .getOptionArgument ( 3 , prop ) . asExpr ( ) |
138185 prop = "user" and kind = "user name"
139186 or
140187 prop = "pass" and kind = "password"
0 commit comments