严重性: 高 (CVSS 8.x — AV:N/AC:L/PR:L/UI:N + C:H/I:H/A:H)
CWE: CWE-89 — SQL注入
影响范围: dagster 数据库 I/O 管理器集成 — dagster-duckdb, dagster-snowflake, dagster-gcp (BigQuery), dagster-deltalake, dagster-snowflake-polars (≤ 1.12.20)
安全公告: GHSA-mjw2-v2hm-wj34
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-41490
致谢: Romain Deperne
每个 Dagster 数据库 I/O 管理器都通过 f-string 插值将分区键值直接插入 SQL 来构建其 WHERE 子句。当资产使用 DynamicPartitionsDefinition 时,分区键可以在运行时通过 GraphQL API(addDynamicPartition)设置——该 API 在默认的 Web 服务器部署中未经认证。恶意分区键会未经转义地流入 SELECT(加载)和 DELETE(清理)查询中,从而导致对后端数据仓库(Snowflake、BigQuery、DuckDB、DeltaLake 等)的 SQL 注入。
同一个辅助函数 _static_where_clause 被复制粘贴到了五个 I/O 管理器包中。每个包都这样做:
def _static_where_clause(table_partition):
partitions = ", ".join(f"'{partition}'" for partition in table_partition.partitions)
return f"""{table_partition.partition_expr} in ({partitions})"""
partition 被包裹在单引号中,没有进行转义。问题在于 partition 是否可能受攻击者控制。对于静态分区,它是由开发者定义的——不感兴趣。对于 DynamicPartitionsDefinition,键会存储在 Dagster 的元数据数据库中,并通过 addDynamicPartition GraphQL 变异在运行时添加。在默认的 dagster-webserver 部署中,GraphQL 未经认证,因此网络上的攻击者可以端到端地提供分区键。
我确认了链的两端:GraphQL 变异接受任意键字符串且无验证,并且该键通过 context.asset_partition_keys 原样到达 _static_where_clause。
addDynamicPartition(... partitionKey: "') UNION SELECT username, password_hash FROM secret_table; --")launchRun(...) 针对该分区SELECT/DELETE ... WHERE col in ('') UNION SELECT ... ; --')加载和清理路径都会使用它:
query = f"SELECT {col_str} FROM {schema}.{table} WHERE\n" + _partition_where_clause(...) # 读取
query = f"DELETE FROM {schema}.{table} WHERE\n" + _partition_where_clause(...) # 写入
分区键被视为可信的开发者常量,但 DynamicPartitionsDefinition 将其变成了运行时、外部可设置的输入。对于静态键“安全”的 f-string 插值在此转变为针对动态键的注入。修复:使用参数化查询 / 正确的标识符和字面量引用,而不是 f-string。
poc/poc_partition_sqli.py — 展示了脆弱的 _static_where_clause 对于良性键和恶意键的输出,针对一个已填充的数据库运行实时的 DuckDB UNION 型数据泄露 + DROP TABLE,并打印出攻击者发送的精确 addDynamicPartition / launchRun GraphQL 载荷。
pip install duckdb # 最小依赖;完整链:dagster dagster-duckdb pandas
python3 poc/poc_partition_sqli.py
对 Dagster 编排的数据仓库进行未经认证(默认配置)的 SQL 注入——任意读取其他表以及破坏性写入。Dagster 位于数据平台的中心,因此攻击会触及堆栈中最敏感的存储。
通过 GitHub 安全公告负责任地披露。概念验证在修复后发布。
| 包 | 文件 |
|---|
| dagster-duckdb | io_manager.py:340-342 |
| dagster-snowflake | snowflake_io_manager.py:434-436 |
| dagster-gcp (BigQuery) | bigquery/io_manager.py:472-474 |
| dagster-deltalake | io_manager.py:265-267 |
| dagster-snowflake-polars | snowflake_polars_type_handler.py:74 |