Skip to content

Commit 11ac699

Browse files
author
jtabsbm
committed
Add SQL injection models for the duckdb Python package
duckdb (~10M downloads/month) implements PEP 249 but had no CodeQL models, so string-built SQL passed to duckdb.execute()/sql()/executemany() was not flagged by the SqlInjection query suite. This adds: - DuckdbPEP249: models duckdb as a PEP 249 module (connect/cursor/ execute/executemany sinks via the existing PEP249 machinery) - ModuleLevelExecuteCall: models the module-level duckdb.sql(), duckdb.execute() and duckdb.executemany() convenience wrappers as SqlExecution calls (getSql from arg 0 or the 'query' keyword) - Frameworks.qll registration and supported-frameworks docs entry Pattern follows the merged hdbcli models (PR #19444). Signed-off-by: jtabsbm <317336566@users.noreply.github.com>
1 parent 3aecce9 commit 11ac699

4 files changed

Lines changed: 54 additions & 0 deletions

File tree

docs/codeql/reusables/supported-frameworks.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog <https://github.co
256256
cassandra-driver, Database
257257
clickhouse-driver, Database
258258
cx_Oracle, Database
259+
duckdb, Database
259260
hdbcli, Database
260261
mysql-connector, Database
261262
mysql-connector-python, Database

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ private import semmle.python.frameworks.Cx_Oracle
2828
private import semmle.python.frameworks.data.ModelsAsData
2929
private import semmle.python.frameworks.Dill
3030
private import semmle.python.frameworks.Django
31+
private import semmle.python.frameworks.Duckdb
3132
private import semmle.python.frameworks.Fabric
3233
private import semmle.python.frameworks.FastApi
3334
private import semmle.python.frameworks.Flask
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `duckdb` PyPI package.
3+
* See
4+
* - https://duckdb.org/docs/stable/clients/python/overview
5+
* - https://pypi.org/project/duckdb/
6+
*/
7+
8+
private import python
9+
private import semmle.python.dataflow.new.DataFlow
10+
private import semmle.python.dataflow.new.RemoteFlowSources
11+
private import semmle.python.Concepts
12+
private import semmle.python.ApiGraphs
13+
private import semmle.python.frameworks.PEP249
14+
15+
/**
16+
* Provides models for the `duckdb` PyPI package.
17+
* See
18+
* - https://duckdb.org/docs/stable/clients/python/overview
19+
* - https://pypi.org/project/duckdb/
20+
*/
21+
private module Duckdb {
22+
/**
23+
* A model of `duckdb` as a module that implements PEP 249, providing ways to execute SQL statements
24+
* against a database.
25+
*/
26+
class DuckdbPEP249 extends PEP249::PEP249ModuleApiNode {
27+
DuckdbPEP249() { this = API::moduleImport("duckdb") }
28+
}
29+
30+
/**
31+
* A call to one of the module level functions `duckdb.sql`, `duckdb.execute` or
32+
* `duckdb.executemany`, all of which immediately execute a SQL statement on the
33+
* default connection.
34+
*
35+
* See https://duckdb.org/docs/stable/clients/python/overview
36+
*/
37+
class ModuleLevelExecuteCall extends SqlExecution::Range, API::CallNode {
38+
ModuleLevelExecuteCall() {
39+
this = API::moduleImport("duckdb").getMember(["sql", "execute", "executemany"]).getACall()
40+
}
41+
42+
override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("query")] }
43+
}
44+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## Change notes
2+
3+
Add SQL injection models for the `duckdb` PyPI package. `duckdb` implements the
4+
Python DB-API 2.0 (PEP 249): `duckdb.connect()`, `connection.cursor()`,
5+
`cursor.execute()`, `cursor.executemany()` are now modeled as SQL execution
6+
sinks, and the module-level convenience wrappers `duckdb.sql()`,
7+
`duckdb.execute()` and `duckdb.executemany()` are additionally modeled as
8+
`SqlExecution` calls.

0 commit comments

Comments
 (0)