Skip to content

Commit f1e71e2

Browse files
committed
Add SqlAlchemy module
1 parent 4be183c commit f1e71e2

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the 'SqlAlchemy' package.
3+
* See https://pypi.org/project/SQLAlchemy/.
4+
*/
5+
6+
private import python
7+
private import semmle.python.dataflow.new.DataFlow
8+
private import semmle.python.dataflow.new.TaintTracking
9+
private import semmle.python.ApiGraphs
10+
11+
12+
private module SqlAlchemy {
13+
private class SqlAlchemySessionInstance extends API::Node {
14+
SqlAlchemySessionInstance() {
15+
this in [
16+
API::moduleImport("sqlalchemy.orm").getMember("Session").getReturn(),
17+
API::moduleImport("sqlalchemy.orm").getMember("sessionmaker").getReturn().getReturn()
18+
]
19+
}
20+
21+
override string toString() { result = "Use of SqlAlchemy Session instance method" }
22+
}
23+
24+
private class SqlAlchemyEngineInstance extends API::Node {
25+
SqlAlchemyEngineInstance() {
26+
this = API::moduleImport("sqlalchemy").getMember("create_engine").getReturn()
27+
}
28+
29+
override string toString() { result = "Use of SqlAlchemy Engine instance method" }
30+
}
31+
32+
private class SqlAlchemyQueryInstance extends API::Node {
33+
SqlAlchemyQueryInstance() {
34+
this instanceof SqlAlchemySessionInstance and
35+
this = this.getMember("query").getReturn()
36+
}
37+
38+
override string toString() { result = "Use of SqlAlchemy Query instance method" }
39+
}
40+
41+
private class SqlAlchemyExecuteCall extends DataFlow::CallCfgNode, SqlExecution::Range {
42+
SqlAlchemyExecuteCall() {
43+
exists(SqlAlchemySessionInstance sessionInstance, SqlAlchemyEngineInstance engineInstance |
44+
this = sessionInstance.getMember("execute").getACall() or
45+
this = engineInstance.getMember("connect").getReturn().getMember("execute").getACall() or
46+
this = engineInstance.getMember("begin").getReturn().getMember("execute").getACall()
47+
)
48+
}
49+
50+
override DataFlow::Node getSql() { result = this.getArg(0) }
51+
}
52+
53+
private class SqlAlchemyScalarCall extends DataFlow::CallCfgNode, SqlExecution::Range {
54+
SqlAlchemyScalarCall() {
55+
exists(SqlAlchemySessionInstance sessionInstance |
56+
this = sessionInstance.getMember("scalar").getACall()
57+
)
58+
}
59+
60+
override DataFlow::Node getSql() { result = this.getArg(0) }
61+
}
62+
63+
private class SqlAlchemyQueryCall extends DataFlow::CallCfgNode, SqlExecution::Range {
64+
SqlAlchemyQueryCall() {
65+
exists(SqlAlchemyQueryInstance queryInstance | this = queryInstance.getAMember().getACall())
66+
}
67+
68+
override DataFlow::Node getSql() { result = this.getArg(0) }
69+
}
70+
}

0 commit comments

Comments
 (0)