Apr 20, 2026·6 min read·3 visits
Dagster I/O managers fail to sanitize dynamic partition keys, enabling SQL injection via unescaped string literals. Upgrading to Dagster 1.13.1 and integration packages 0.29.1 resolves the issue, or users can apply a manual runtime monkey patch.
A high-severity SQL injection vulnerability in Dagster's database I/O manager integrations allows users with dynamic partition creation privileges to execute arbitrary SQL commands. This flaw affects the DuckDB, Snowflake, BigQuery, and DeltaLake integrations due to improper sanitization of dynamic partition keys.
The Dagster orchestration platform relies on Database I/O Manager Integrations to handle the storage and retrieval of data assets. A critical flaw exists in how these managers process dynamic partition keys across multiple database backends. This vulnerability affects the DuckDB, Snowflake, BigQuery (dagster-gcp), and DeltaLake integrations.
The vulnerability is classified as CWE-89 (SQL Injection) and carries a High severity CVSS score of 8.3. It occurs within the logic responsible for filtering database tables based on dynamic partition definitions. When an asset utilizes dynamic partitions, the I/O manager dynamically constructs a SQL WHERE clause to target specific data segments.
The core issue stems from the platform interpolating partition key values directly into these SQL query strings. Because the system does not apply adequate sanitization or utilize parameterized queries for these keys, an attacker can manipulate the resulting SQL command. Static and time-window partitions do not utilize this vulnerable code path and remain unaffected.
The root cause of this vulnerability lies in the implementation of the _static_where_clause generation within the affected I/O managers. Dagster constructs query strings by taking user-supplied partition keys and inserting them into an IN clause. This string concatenation operates without neutralizing SQL control characters.
In standard database interactions, user-supplied data must either be bound using parameterized queries or properly escaped before inclusion in a query string. The vulnerable Dagster I/O managers construct the partition list by simply wrapping the string representation of each partition key in single quotes. The framework implicitly trusts the partition key value to be safe.
When a partition key contains a single quote ('), it prematurely terminates the string literal within the generated SQL command. The subsequent characters in the partition key are then parsed by the database engine as executable SQL syntax. This enables an attacker to append arbitrary logical operators, subqueries, or chained commands.
The vulnerability exists in the lack of escaping during the generation of the partition string list. In the vulnerable implementation, the logic iterates over the provided partitions and interpolates them directly into a format string. The lack of a character replacement operation allows the ' character to break out of the SQL literal context.
The patched implementation, which is also provided by the maintainers as a manual workaround, introduces a critical sanitization step. The fix applies a standard SQL string escaping technique by duplicating single quotes. This ensures that the database parses the input strictly as string data rather than syntax.
# Patched implementation demonstrating the fix
def _safe_static_where_clause(table_partition):
# The .replace("'", "''") neutralizes the string literal terminator
partitions = ", ".join(
"'" + str(p).replace("'", "''") + "'" for p in table_partition.partitions
)
return f"{table_partition.partition_expr} in ({partitions})"By chaining .replace("'", "''") to the string representation of the partition key, any attacker-supplied single quote is converted into an escaped quote. If an attacker inputs ' OR 1=1 --, the resulting string becomes '' OR 1=1 --, which the database interprets as a literal string value rather than an evaluation statement.
Exploiting this vulnerability requires specific prerequisites within the target Dagster environment. The attacker must possess the Add Dynamic Partitions permission. In Dagster Open Source (OSS) deployments, this permission is generally granted to any user or system with access to the API.
The attack vector involves submitting a malicious dynamic partition key through the Dagster API or UI. Instead of providing a legitimate partition identifier, the attacker supplies a payload designed to manipulate the SQL WHERE clause. A common test payload such as ' OR 1=1 -- effectively bypasses the partition filter.
Once the malicious partition key is registered, any operation that triggers the I/O manager to read or write that partition will execute the injected payload. The attacker can structure the payload to exfiltrate data via error-based SQL injection, or execute administrative commands depending on the backend database dialect.
The impact of this SQL injection is dictated by the privileges assigned to the database credentials used by the Dagster I/O manager. The injected SQL commands execute with the same authorization scope as the orchestration platform itself. In most configurations, these credentials possess extensive read, write, and delete permissions across the data warehouse.
In Dagster OSS environments, the lack of granular Role-Based Access Control (RBAC) exacerbates the risk. Any user with API access can trigger the vulnerability, leading to unauthorized data exposure or destructive modification. This makes multi-tenant or loosely controlled OSS environments highly susceptible to internal threat actors or compromised adjacent services.
For Dagster+ (the enterprise offering), the default configurations restrict partition creation to users with the 'Editor' role. Since Editors generally already possess code and database access, the direct risk is mitigated. However, environments utilizing custom RBAC roles where users can manage partitions but are otherwise restricted from the database face a clear privilege escalation vector.
The definitive resolution for this vulnerability is upgrading the affected software packages to their patched versions. Organizations must update the dagster core package to version 1.13.1 or later. Furthermore, the associated database integration libraries (dagster-duckdb, dagster-snowflake, dagster-gcp, and dagster-deltalake) must be updated to version 0.29.1 or later.
If immediate patching is unfeasible, a runtime monkey-patch workaround must be applied. Administrators can inject a safe override function at the top of their definitions.py file. This intercepts the vulnerable method within the integration libraries before it is utilized by the runtime environment.
# Workaround for dagster-gcp (BigQuery)
from dagster_gcp.bigquery import io_manager as bq_io_manager
def _safe_static_where_clause(table_partition):
partitions = ", ".join("'" + str(p).replace("'", "''") + "'" for p in table_partition.partitions)
return f"{table_partition.partition_expr} in ({partitions})"
bq_io_manager._static_where_clause = _safe_static_where_clauseThis exact monkey-patching pattern must be replicated for whichever specific I/O manager is active in the deployment (e.g., modifying snowflake_io_manager._static_where_clause for Snowflake environments). Once applied and the Dagster instance is restarted, the sanitization logic will successfully neutralize SQL injection attempts.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
dagster Dagster | >= 1.1.21, < 1.13.1 | 1.13.1 |
dagster-duckdb Dagster | >= 0.17.21, < 0.29.1 | 0.29.1 |
dagster-snowflake Dagster | >= 0.17.21, < 0.29.1 | 0.29.1 |
dagster-gcp Dagster | >= 0.17.21, < 0.29.1 | 0.29.1 |
dagster-deltalake Dagster | < 0.29.1 | 0.29.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-89 |
| CVSS Score | 8.3 (High) |
| Attack Vector | Network (API/UI) |
| Authentication Required | Low (Requires API Access) |
| Impact Context | I/O Manager Database Scope |
| Patch Status | Available (1.13.1 / 0.29.1) |
The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command.