@@ -11,35 +11,49 @@ private import experimental.semmle.python.Concepts
1111private import semmle.python.ApiGraphs
1212
1313private module NoSQL {
14- /** API Nodes returning `Mongo` instances. */
14+ // API Nodes returning `Mongo` instances.
15+ /** Gets a reference to `pymongo.MongoClient` */
1516 private API:: Node pyMongo ( ) {
1617 result = API:: moduleImport ( "pymongo" ) .getMember ( "MongoClient" ) .getReturn ( )
1718 }
1819
20+ /** Gets a reference to `flask_pymongo.PyMongo` */
1921 private API:: Node flask_PyMongo ( ) {
2022 result = API:: moduleImport ( "flask_pymongo" ) .getMember ( "PyMongo" ) .getReturn ( )
2123 }
2224
25+ /** Gets a reference to `mongoengine` */
2326 private API:: Node mongoEngine ( ) { result = API:: moduleImport ( "mongoengine" ) }
2427
28+ /** Gets a reference to `flask_mongoengine.MongoEngine` */
2529 private API:: Node flask_MongoEngine ( ) {
2630 result = API:: moduleImport ( "flask_mongoengine" ) .getMember ( "MongoEngine" ) .getReturn ( )
2731 }
2832
29- /** Gets a reference to a initialized `Mongo` instance. */
33+ /**
34+ * Gets a reference to a initialized `Mongo` instance.
35+ * See `pyMongo()`, `flask_PyMongo()`
36+ */
3037 private API:: Node mongoInstance ( ) {
3138 result = pyMongo ( ) or
3239 result = flask_PyMongo ( )
3340 }
3441
35- /** Gets a reference to a initialized `Mongo` DB instance. */
42+ /**
43+ * Gets a reference to a initialized `Mongo` DB instance.
44+ * See `mongoEngine()`, `flask_MongoEngine()`
45+ */
3646 private API:: Node mongoDBInstance ( ) {
3747 result = mongoEngine ( ) .getMember ( [ "get_db" , "connect" ] ) .getReturn ( ) or
3848 result = mongoEngine ( ) .getMember ( "connection" ) .getMember ( [ "get_db" , "connect" ] ) .getReturn ( ) or
3949 result = flask_MongoEngine ( ) .getMember ( "get_db" ) .getReturn ( )
4050 }
4151
42- /** Gets a reference to a `Mongo` DB use. */
52+ /**
53+ * Gets a reference to a `Mongo` DB use.
54+ *
55+ * See `mongoInstance()`, `mongoDBInstance()`.
56+ */
4357 private DataFlow:: LocalSourceNode mongoDB ( DataFlow:: TypeTracker t ) {
4458 t .start ( ) and
4559 (
@@ -56,10 +70,24 @@ private module NoSQL {
5670 exists ( DataFlow:: TypeTracker t2 | result = mongoDB ( t2 ) .track ( t2 , t ) )
5771 }
5872
59- /** Gets a reference to a `Mongo` DB use. */
73+ /**
74+ * Gets a reference to a `Mongo` DB use.
75+ *
76+ * ```py
77+ * from flask_pymongo import PyMongo
78+ * mongo = PyMongo(app)
79+ * mongo.db.user.find({'name': safe_search})
80+ * ```
81+ *
82+ * `mongo.db` would be a `use` of a `Mongo` instance, and so the result.
83+ */
6084 private DataFlow:: Node mongoDB ( ) { mongoDB ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
6185
62- /** Gets a reference to a `Mongo` collection use. */
86+ /**
87+ * Gets a reference to a `Mongo` collection use.
88+ *
89+ * See `mongoDB()`.
90+ */
6391 private DataFlow:: LocalSourceNode mongoCollection ( DataFlow:: TypeTracker t ) {
6492 t .start ( ) and
6593 (
@@ -73,7 +101,17 @@ private module NoSQL {
73101 exists ( DataFlow:: TypeTracker t2 | result = mongoCollection ( t2 ) .track ( t2 , t ) )
74102 }
75103
76- /** Gets a reference to a `Mongo` collection use. */
104+ /**
105+ * Gets a reference to a `Mongo` collection use.
106+ *
107+ * ```py
108+ * from flask_pymongo import PyMongo
109+ * mongo = PyMongo(app)
110+ * mongo.db.user.find({'name': safe_search})
111+ * ```
112+ *
113+ * `mongo.db.user` would be a `use` of a `Mongo` collection, and so the result.
114+ */
77115 private DataFlow:: Node mongoCollection ( ) {
78116 mongoCollection ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result )
79117 }
@@ -88,19 +126,54 @@ private module NoSQL {
88126 }
89127 }
90128
91- /** Gets a reference to a `Mongo` collection method. */
129+ /**
130+ * Gets a reference to a `Mongo` collection method.
131+ *
132+ * ```py
133+ * from flask_pymongo import PyMongo
134+ * mongo = PyMongo(app)
135+ * mongo.db.user.find({'name': safe_search})
136+ * ```
137+ *
138+ * `mongo.db.user.find` would be a collection method, and so the result.
139+ */
92140 private DataFlow:: Node mongoCollectionMethod ( ) {
93- mongoCollection ( ) in [ result .( DataFlow:: AttrRead ) , result . ( DataFlow :: AttrRead ) . getObject ( ) ] and
141+ mongoCollection ( ) = result .( DataFlow:: AttrRead ) . getObject ( ) and
94142 result .( DataFlow:: AttrRead ) .getAttributeName ( ) instanceof MongoCollectionMethodNames
95143 }
96144
97- /** Gets a reference to a `Mongo` collection method call */
145+ /**
146+ * Gets a reference to a `Mongo` collection method call
147+ *
148+ * ```py
149+ * from flask_pymongo import PyMongo
150+ * mongo = PyMongo(app)
151+ * mongo.db.user.find({'name': safe_search})
152+ * ```
153+ *
154+ * `mongo.db.user.find({'name': safe_search})` would be a collection method call, and so the result.
155+ */
98156 private class MongoCollectionCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
99157 MongoCollectionCall ( ) { this .getFunction ( ) = mongoCollectionMethod ( ) }
100158
101159 override DataFlow:: Node getQuery ( ) { result = this .getArg ( 0 ) }
102160 }
103161
162+ /**
163+ * Gets a reference to a call from a class whose base is a reference to `mongoEngine()` or `flask_MongoEngine()`'s
164+ * `Document` or `EmbeddedDocument` objects and its attribute is `objects`.
165+ *
166+ * ```py
167+ * from flask_mongoengine import MongoEngine
168+ * db = MongoEngine(app)
169+ * class Movie(db.Document):
170+ * title = db.StringField(required=True)
171+ *
172+ * Movie.objects(__raw__=json_search)
173+ * ```
174+ *
175+ * `Movie.objects(__raw__=json_search)` would be the result.
176+ */
104177 private class MongoEngineObjectsCall extends DataFlow:: CallCfgNode , NoSQLQuery:: Range {
105178 MongoEngineObjectsCall ( ) {
106179 this =
@@ -114,6 +187,7 @@ private module NoSQL {
114187 override DataFlow:: Node getQuery ( ) { result = this .getArgByName ( _) }
115188 }
116189
190+ /** Gets a reference to `mongosanitizer.sanitizer.sanitize` */
117191 private class MongoSanitizerCall extends DataFlow:: CallCfgNode , NoSQLSanitizer:: Range {
118192 MongoSanitizerCall ( ) {
119193 this =
0 commit comments