Visitar URL original
plugins/destination/clickhouse: SQL injection in table queries, nil dereference in equalTTLs, context.Background() used instead of caller context · Issue #23169 · cloudquery/cloudquery · GitHub
Skip to content

plugins/destination/clickhouse: SQL injection in table queries, nil dereference in equalTTLs, context.Background() used instead of caller context #23169

Description

@praneshnikhar

ClickHouse: SQL injection, nil dereference, and wrong context in destination plugin

Bug 1: SQL injection in queries/table.go

Files: plugins/destination/clickhouse/queries/table.go:58-63

Problem: Database and table names are interpolated directly into SQL query strings using fmt.Sprintf with '%s' quoting, which doesn't prevent SQL injection if the names contain single quotes or escape characters.

Vulnerable queries:

func GetPartitionKeyAndSortingKeyQuery(database, table string) string {
    return fmt.Sprintf(`SELECT partition_key, sorting_key FROM system.tables WHERE database = '%s' AND name = '%s'`, database, table)
}

func GetTTLQuery(database, table string) string {
    return fmt.Sprintf(`SHOW CREATE TABLE "%s"."%s"`, database, table)
}

Fix: Use util.SanitizeID() to properly escape identifiers:

return fmt.Sprintf(`SELECT partition_key, sorting_key FROM system.tables WHERE database = %s AND name = %s`, util.SanitizeID(database), util.SanitizeID(table))
return fmt.Sprintf("SHOW CREATE TABLE %s.%s", util.SanitizeID(database), util.SanitizeID(table))

Bug 2: Nil pointer dereference in equalTTLs (client/table.go)

File: plugins/destination/clickhouse/client/table.go:72

Problem: The *uint8 result from retryQueryRowAndScan is dereferenced (*result == 1) without a nil check. If the query returns NULL (e.g., on a table with no TTL), this panics.

Current code:

var result *uint8
err := retryQueryRowAndScan(ctx, c.logger, c.conn, sql, []any{}, []any{&result})
if err != nil {
    return false, err
}
return *result == 1, nil  // panic if result is nil

Bug 3: Wrong context in equalTTLs (client/table.go)

File: plugins/destination/clickhouse/client/table.go:72 (pre-fix)

Problem: retryQueryRowAndScan was called with context.Background() instead of the caller's context. This means the TTL comparison query cannot be cancelled or respect timeouts set by the caller.

Current code (pre-fix):

err := retryQueryRowAndScan(context.Background(), c.logger, c.conn, sql, []any{}, []any{&result})

Reproduction

  1. SQL injection: Create a plugin config with a table named foo'; DROP TABLE system.tables; -- and run a sync with ClickHouse destination.
  2. Nil dereference: Sync a table that has no TTL set but the migration code checks TTL. The equalTTLs query returns NULL → *result panics.
  3. Wrong context: Timeout or cancel a long sync — the TTL comparison continues with context.Background() and cannot be cancelled.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions