Skip to content

Commit 1535da1

Browse files
committed
fix(clickhouse): restrict DROP PARTITION to literal values to prevent SQL injection
1 parent efe8414 commit 1535da1

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

  • apps/sim/app/api/tools/clickhouse

apps/sim/app/api/tools/clickhouse/utils.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,23 @@ function validateExpression(expression: string, label: string): void {
389389
}
390390
}
391391

392+
/**
393+
* Validates a partition value for `DROP PARTITION`. ClickHouse partition values
394+
* are literals (signed numbers or single-quoted strings) or a parenthesised tuple
395+
* of such literals, so anything else is rejected — barewords like `ALL`, function
396+
* calls, operators, and extra tokens that could broaden the statement beyond
397+
* dropping a single partition.
398+
*/
399+
function validatePartitionExpression(partition: string): void {
400+
const partitionPattern =
401+
/^\(?\s*(?:'(?:[^'\\]|\\.)*'|-?\d+(?:\.\d+)?)(?:\s*,\s*(?:'(?:[^'\\]|\\.)*'|-?\d+(?:\.\d+)?))*\s*\)?$/
402+
if (!partitionPattern.test(partition.trim())) {
403+
throw new Error(
404+
"Partition must be a literal value or a tuple of literals (number or single-quoted string), e.g. 202401, '2024-01', or (2024, 'EU')"
405+
)
406+
}
407+
}
408+
392409
export function executeClickHouseListDatabases(
393410
config: ClickHouseConnectionConfig
394411
): Promise<ClickHouseRowsResult> {
@@ -609,7 +626,7 @@ export async function executeClickHouseDropPartition(
609626
table: string,
610627
partition: string
611628
): Promise<void> {
612-
validateExpression(partition, 'Partition')
629+
validatePartitionExpression(partition)
613630
await clickhouseRequest(
614631
config,
615632
`ALTER TABLE ${sanitizeIdentifier(table)} DROP PARTITION ${partition.trim()}`

0 commit comments

Comments
 (0)