Dagster Database I/O Manager SQL Injection via Dynamic Partition Keys (CVE-2026-41490)
by Romain Deperne · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-41490 (GHSA-mjw2-v2hm-wj34)
- Category
- web
- Affected product
- Dagster database I/O manager integrations: dagster-duckdb, dagster-snowflake, dagster-gcp (BigQuery), dagster-deltalake, dagster-snowflake-polars
- Affected versions
- <= 1.12.20
- Disclosed
- 2026-07-05
- Patch status
- patched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-06 |
| Author / Researcher | Romain Deperne |
| CVE / Advisory | CVE-2026-41490 (GHSA-mjw2-v2hm-wj34) |
| Category | web |
| Severity | High |
| CVSS Score | ~8.x (AV:N/AC:L/PR:L/UI:N, C:H/I:H/A:H per source) |
| Status | PoC |
| Tags | dagster, sql-injection, graphql, duckdb, snowflake, bigquery, data-pipeline, dynamic-partitions |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Dagster database I/O manager integrations: dagster-duckdb, dagster-snowflake, dagster-gcp (BigQuery), dagster-deltalake, dagster-snowflake-polars |
| Versions Affected | <= 1.12.20 |
| Language / Platform | Python (Dagster), backing SQL warehouses (DuckDB/Snowflake/BigQuery/DeltaLake) |
| Authentication Required | No (default dagster-webserver GraphQL API is unauthenticated) |
| Network Access Required | Yes |
Summary
All five Dagster database I/O-manager packages share a copy-pasted helper, _static_where_clause, that builds SQL WHERE/DELETE clauses by f-string-interpolating partition key values with no escaping. For statically defined partitions this is safe because the developer controls the values, but assets using DynamicPartitionsDefinition accept partition keys set at runtime through the addDynamicPartition GraphQL mutation — which is unauthenticated by default in dagster-webserver. An attacker can register a malicious partition key containing SQL syntax, then trigger a run against it via launchRun, causing the injected string to flow verbatim into both read (SELECT) and cleanup (DELETE) queries against the backing data warehouse. The PoC demonstrates the vulnerable helper directly, runs a live DuckDB UNION-based exfiltration and destructive DROP TABLE against a seeded database, and prints the exact GraphQL mutations an attacker would send against a real Dagster deployment.
Vulnerability Details
Root Cause
_static_where_clause (duplicated across dagster-duckdb, dagster-snowflake, dagster-gcp, dagster-deltalake, and dagster-snowflake-polars) builds SQL by wrapping partition key values in an f-string (f"'{partition}'") with no escaping or parameterization; because DynamicPartitionsDefinition keys are attacker-settable at runtime via an unauthenticated GraphQL mutation, this “safe for static partitions” pattern becomes an injectable, externally-controlled SQL string.
Attack Vector
- Attacker reaches the (unauthenticated by default) Dagster webserver GraphQL API on the network.
- Attacker calls
addDynamicPartition(..., partitionKey: "') UNION SELECT username, password_hash FROM secret_table; --")to register a malicious partition key. - Attacker calls
launchRun(...)targeting an asset that uses that dynamic partition with a vulnerable I/O manager. - The I/O manager builds
SELECT/DELETEqueries via_static_where_clause, embedding the malicious key unescaped. - The resulting SQL injection executes against the backing warehouse (DuckDB/Snowflake/BigQuery/DeltaLake), enabling arbitrary data read or destructive writes.
Impact
Unauthenticated (in default deployments) SQL injection against the data warehouse that Dagster orchestrates, enabling arbitrary read of unrelated tables and destructive operations (e.g. DROP TABLE) on the organization’s most sensitive data store.
Environment / Lab Setup
Target: Dagster asset using DynamicPartitionsDefinition + a vulnerable I/O manager (duckdb/snowflake/bigquery/deltalake/snowflake-polars), <= 1.12.20
Attacker: Python 3 + duckdb (minimal PoC); full chain additionally needs dagster, dagster-duckdb, pandas, and a reachable dagster-webserver GraphQL endpoint
Proof of Concept
PoC Script
See
poc_partition_sqli.pyin this folder.
| |
The script first reproduces the vulnerable _static_where_clause logic directly to show benign vs. malicious partition keys producing injected SQL; it then runs a live DuckDB demonstration — creating seeded user_data and secret_credentials tables, executing a UNION-based query that exfiltrates credentials through the injected partition key, and attempting a destructive DROP TABLE via the same code path. Finally it prints the exact addDynamicPartition and launchRun GraphQL mutation payloads an attacker would send against a real Dagster webserver.
Detection & Indicators of Compromise
Signs of compromise:
- Dynamic partition keys in Dagster’s metadata DB containing quotes,
UNION, or SQL comment sequences - Unexpected reads of unrelated tables (e.g. credential/secret tables) correlated with Dagster run launches
- Dropped or truncated tables in the backing warehouse with no corresponding legitimate pipeline change
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade to a patched Dagster release once available and require authentication on the dagster-webserver GraphQL API; monitor GHSA-mjw2-v2hm-wj34 for the official fixed version |
| Interim mitigation | Use parameterized queries / proper identifier and literal quoting instead of f-string interpolation in custom I/O managers, disable/restrict unauthenticated GraphQL access, and validate dynamic partition keys against an allowlist pattern |
References
Notes
Mirrored from https://github.com/romain-deperne/CVE-2026-41490 on 2026-07-05.
| |