Skip to content

Commit 68c6831

Browse files
committed
Polish documentation, mongoCollectionMethod() and update .expected
1 parent 3fd1129 commit 68c6831

File tree

2 files changed

+104
-64
lines changed

2 files changed

+104
-64
lines changed

python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,49 @@ private import experimental.semmle.python.Concepts
1111
private import semmle.python.ApiGraphs
1212

1313
private 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

Comments
 (0)