mirror of
https://github.com/github/codeql.git
synced 2026-05-22 23:27:09 +02:00
173 lines
4.9 KiB
Plaintext
173 lines
4.9 KiB
Plaintext
/**
|
|
* Provides classes for working with NoSQL libraries.
|
|
*/
|
|
|
|
import javascript
|
|
|
|
/** Provices classes for modelling NoSQL query sinks. */
|
|
module NoSql {
|
|
/** An expression that is interpreted as a NoSQL query. */
|
|
abstract class Query extends Expr {
|
|
/** Gets an expression that is interpreted as a code operator in this query. */
|
|
DataFlow::Node getACodeOperator() { none() }
|
|
}
|
|
}
|
|
|
|
/** DEPRECATED: Alias for NoSql */
|
|
deprecated module NoSQL = NoSql;
|
|
|
|
/**
|
|
* Provides classes modeling the MongoDB library.
|
|
*/
|
|
private module MongoDB {
|
|
/**
|
|
* Gets an import of MongoDB.
|
|
*/
|
|
DataFlow::ModuleImportNode mongodb() { result.getPath() = "mongodb" }
|
|
|
|
/**
|
|
* Gets an access to `mongodb.MongoClient`.
|
|
*/
|
|
private DataFlow::SourceNode getAMongoClient(DataFlow::TypeTracker t) {
|
|
t.start() and
|
|
result = mongodb().getAPropertyRead("MongoClient")
|
|
or
|
|
exists(DataFlow::TypeTracker t2 | result = getAMongoClient(t2).track(t2, t))
|
|
}
|
|
|
|
/**
|
|
* Gets an access to `mongodb.MongoClient`.
|
|
*/
|
|
DataFlow::SourceNode getAMongoClient() { result = getAMongoClient(DataFlow::TypeTracker::end()) }
|
|
|
|
/** Gets a data flow node that leads to a `connect` callback. */
|
|
private DataFlow::SourceNode getAMongoDbCallback(DataFlow::TypeBackTracker t) {
|
|
t.start() and
|
|
result = getAMongoClient().getAMemberCall("connect").getArgument(1).getALocalSource()
|
|
or
|
|
exists(DataFlow::TypeBackTracker t2 | result = getAMongoDbCallback(t2).backtrack(t2, t))
|
|
}
|
|
|
|
/** Gets a data flow node that leads to a `connect` callback. */
|
|
private DataFlow::FunctionNode getAMongoDbCallback() {
|
|
result = getAMongoDbCallback(DataFlow::TypeBackTracker::end())
|
|
}
|
|
|
|
/**
|
|
* Gets an expression that may refer to a MongoDB database connection.
|
|
*/
|
|
private DataFlow::SourceNode getAMongoDb(DataFlow::TypeTracker t) {
|
|
t.start() and
|
|
result = getAMongoDbCallback().getParameter(1)
|
|
or
|
|
exists(DataFlow::TypeTracker t2 | result = getAMongoDb(t2).track(t2, t))
|
|
}
|
|
|
|
/**
|
|
* Gets an expression that may refer to a MongoDB database connection.
|
|
*/
|
|
DataFlow::SourceNode getAMongoDb() { result = getAMongoDb(DataFlow::TypeTracker::end()) }
|
|
|
|
/**
|
|
* A data flow node that may hold a MongoDB collection.
|
|
*/
|
|
abstract class Collection extends DataFlow::SourceNode { }
|
|
|
|
/**
|
|
* A collection resulting from calling `Db.collection(...)`.
|
|
*/
|
|
private class CollectionFromDb extends Collection {
|
|
CollectionFromDb() {
|
|
this = getAMongoDb().getAMethodCall("collection")
|
|
or
|
|
this = getAMongoDb().getAMethodCall("collection").getCallback(1).getParameter(0)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A collection based on the type `mongodb.Collection`.
|
|
*
|
|
* Note that this also covers `mongoose` models since they are subtypes
|
|
* of `mongodb.Collection`.
|
|
*/
|
|
private class CollectionFromType extends Collection {
|
|
CollectionFromType() { hasUnderlyingType("mongodb", "Collection") }
|
|
}
|
|
|
|
/** Gets a data flow node referring to a MongoDB collection. */
|
|
private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) {
|
|
t.start() and
|
|
result instanceof Collection
|
|
or
|
|
exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t))
|
|
}
|
|
|
|
/** Gets a data flow node referring to a MongoDB collection. */
|
|
DataFlow::SourceNode getACollection() { result = getACollection(DataFlow::TypeTracker::end()) }
|
|
|
|
/** A call to a MongoDB query method. */
|
|
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
|
int queryArgIdx;
|
|
|
|
QueryCall() {
|
|
exists(string m | this = getACollection().getAMethodCall(m) |
|
|
m = "count" and queryArgIdx = 0
|
|
or
|
|
m = "distinct" and queryArgIdx = 1
|
|
or
|
|
m = "find" and queryArgIdx = 0
|
|
)
|
|
}
|
|
|
|
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
|
|
}
|
|
|
|
/**
|
|
* An expression that is interpreted as a MongoDB query.
|
|
*/
|
|
class Query extends NoSql::Query {
|
|
Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Provides classes modeling the Mongoose library.
|
|
*/
|
|
private module Mongoose {
|
|
/**
|
|
* Gets an import of Mongoose.
|
|
*/
|
|
DataFlow::ModuleImportNode getAMongooseInstance() { result.getPath() = "mongoose" }
|
|
|
|
/**
|
|
* Gets a call to `mongoose.createConnection`.
|
|
*/
|
|
DataFlow::CallNode createConnection() {
|
|
result = getAMongooseInstance().getAMemberCall("createConnection")
|
|
}
|
|
|
|
/**
|
|
* A Mongoose collection object.
|
|
*/
|
|
class Model extends MongoDB::Collection {
|
|
Model() { this = getAMongooseInstance().getAMemberCall("model") }
|
|
}
|
|
|
|
/**
|
|
* An expression passed to `mongoose.createConnection` to supply credentials.
|
|
*/
|
|
class Credentials extends CredentialsExpr {
|
|
string kind;
|
|
|
|
Credentials() {
|
|
exists(string prop | this = createConnection().getOptionArgument(3, prop).asExpr() |
|
|
prop = "user" and kind = "user name"
|
|
or
|
|
prop = "pass" and kind = "password"
|
|
)
|
|
}
|
|
|
|
override string getCredentialsKind() { result = kind }
|
|
}
|
|
}
|