Skip to content

Commit 4adb0c7

Browse files
authored
Merge pull request #6589 from RasmusWL/promote-sqlalchemy
Python: Promote modeling of SQLAlchemy
2 parents 4a16be2 + f8e6ba6 commit 4adb0c7

31 files changed

+1186
-170
lines changed

docs/codeql/support/reusables/frameworks.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ Python built-in support
176176
mysqlclient, Database
177177
psycopg2, Database
178178
sqlite3, Database
179+
Flask-SQLAlchemy, Database ORM
179180
peewee, Database ORM
181+
SQLAlchemy, Database ORM
180182
cryptography, Cryptography library
181183
pycryptodome, Cryptography library
182184
pycryptodomex, Cryptography library
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added modeling of SQL execution in the `Flask-SQLAlchemy` PyPI package, resulting in additional sinks for the SQL Injection query (`py/sql-injection`).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added modeling of SQL execution in the `SQLAlchemy` PyPI package, resulting in additional sinks for the SQL Injection query (`py/sql-injection`). This modeling was originally [submitted as a contribution by @mrthankyou](https://github.com/github/codeql/pull/5680).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Introduced a new query _SQLAlchemy TextClause built from user-controlled sources_ (`py/sqlalchemy-textclause-injection`) to alert if user-input is added to a TextClause from SQLAlchemy, since that can lead to SQL injection.

python/ql/lib/semmle/python/Frameworks.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@ private import semmle.python.frameworks.Dill
1313
private import semmle.python.frameworks.Django
1414
private import semmle.python.frameworks.Fabric
1515
private import semmle.python.frameworks.Flask
16+
private import semmle.python.frameworks.FlaskSqlAlchemy
1617
private import semmle.python.frameworks.Idna
1718
private import semmle.python.frameworks.Invoke
1819
private import semmle.python.frameworks.Jmespath
1920
private import semmle.python.frameworks.MarkupSafe
2021
private import semmle.python.frameworks.Multidict
2122
private import semmle.python.frameworks.Mysql
2223
private import semmle.python.frameworks.MySQLdb
24+
private import semmle.python.frameworks.Peewee
2325
private import semmle.python.frameworks.Psycopg2
2426
private import semmle.python.frameworks.PyMySQL
2527
private import semmle.python.frameworks.Rsa
2628
private import semmle.python.frameworks.Simplejson
29+
private import semmle.python.frameworks.SqlAlchemy
2730
private import semmle.python.frameworks.Stdlib
2831
private import semmle.python.frameworks.Tornado
29-
private import semmle.python.frameworks.Peewee
3032
private import semmle.python.frameworks.Twisted
3133
private import semmle.python.frameworks.Ujson
3234
private import semmle.python.frameworks.Yaml
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `Flask-SQLAlchemy` PyPI package
3+
* (imported by `flask_sqlalchemy`).
4+
* See
5+
* - https://pypi.org/project/Flask-SQLAlchemy/
6+
* - https://flask-sqlalchemy.palletsprojects.com/en/2.x/
7+
*/
8+
9+
private import python
10+
private import semmle.python.dataflow.new.DataFlow
11+
private import semmle.python.dataflow.new.TaintTracking
12+
private import semmle.python.ApiGraphs
13+
private import semmle.python.Concepts
14+
private import semmle.python.frameworks.SqlAlchemy
15+
16+
/**
17+
* INTERNAL: Do not use.
18+
*
19+
* Provides models for the `Flask-SQLAlchemy` PyPI package (imported by `flask_sqlalchemy`).
20+
* See
21+
* - https://pypi.org/project/Flask-SQLAlchemy/
22+
* - https://flask-sqlalchemy.palletsprojects.com/en/2.x/
23+
*/
24+
private module FlaskSqlAlchemy {
25+
/** Gets an instance of `flask_sqlalchemy.SQLAlchemy` */
26+
private API::Node dbInstance() {
27+
result = API::moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn()
28+
}
29+
30+
/** A call to the `text` method on a DB. */
31+
private class DbTextCall extends SqlAlchemy::TextClause::TextClauseConstruction {
32+
DbTextCall() { this = dbInstance().getMember("text").getACall() }
33+
}
34+
35+
/** Access on a DB resulting in an Engine */
36+
private class DbEngine extends SqlAlchemy::Engine::InstanceSource {
37+
DbEngine() {
38+
this = dbInstance().getMember("engine").getAUse()
39+
or
40+
this = dbInstance().getMember("get_engine").getACall()
41+
}
42+
}
43+
44+
/** Access on a DB resulting in a Session */
45+
private class DbSession extends SqlAlchemy::Session::InstanceSource {
46+
DbSession() {
47+
this = dbInstance().getMember("session").getAUse()
48+
or
49+
this = dbInstance().getMember("create_session").getReturn().getACall()
50+
or
51+
this = dbInstance().getMember("create_session").getReturn().getMember("begin").getACall()
52+
or
53+
this = dbInstance().getMember("create_scoped_session").getACall()
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)