Skip to content

Commit 361861c

Browse files
committed
Add limits to Query ClickHouse
1 parent 6e2081f commit 361861c

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

apps/webapp/app/env.server.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,13 @@ const EnvironmentSchema = z
11751175
CLICKHOUSE_LOG_LEVEL: z.enum(["log", "error", "warn", "info", "debug"]).default("info"),
11761176
CLICKHOUSE_COMPRESSION_REQUEST: z.string().default("1"),
11771177

1178+
// Query page ClickHouse limits (for TSQL queries)
1179+
QUERY_CLICKHOUSE_MAX_EXECUTION_TIME: z.coerce.number().int().default(60),
1180+
QUERY_CLICKHOUSE_MAX_MEMORY_USAGE: z.coerce.number().int().default(1_073_741_824), // 1GB in bytes
1181+
QUERY_CLICKHOUSE_MAX_AST_ELEMENTS: z.coerce.number().int().default(4_000_000),
1182+
QUERY_CLICKHOUSE_MAX_EXPANDED_AST_ELEMENTS: z.coerce.number().int().default(4_000_000),
1183+
QUERY_CLICKHOUSE_MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY: z.coerce.number().int().default(0),
1184+
11781185
EVENTS_CLICKHOUSE_URL: z
11791186
.string()
11801187
.optional()

apps/webapp/app/services/queryService.server.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
executeTSQL,
3+
type ClickHouseSettings,
34
type ExecuteTSQLOptions,
45
type FieldMappings,
56
type TSQLQueryResult,
@@ -21,6 +22,33 @@ const scopeToEnum = {
2122
environment: "ENVIRONMENT",
2223
} as const;
2324

25+
/**
26+
* Default ClickHouse settings for query protection
27+
* Based on PostHog's HogQL settings to prevent expensive queries
28+
*/
29+
function getDefaultClickhouseSettings(): ClickHouseSettings {
30+
return {
31+
// Query execution limits
32+
max_execution_time: env.QUERY_CLICKHOUSE_MAX_EXECUTION_TIME,
33+
timeout_overflow_mode: "throw",
34+
max_memory_usage: String(env.QUERY_CLICKHOUSE_MAX_MEMORY_USAGE),
35+
36+
// AST complexity limits to prevent extremely complex queries
37+
max_ast_elements: String(env.QUERY_CLICKHOUSE_MAX_AST_ELEMENTS),
38+
max_expanded_ast_elements: String(env.QUERY_CLICKHOUSE_MAX_EXPANDED_AST_ELEMENTS),
39+
40+
// Memory management for GROUP BY operations
41+
max_bytes_before_external_group_by: String(
42+
env.QUERY_CLICKHOUSE_MAX_BYTES_BEFORE_EXTERNAL_GROUP_BY
43+
),
44+
45+
// Safety settings
46+
allow_experimental_object_type: 1,
47+
format_csv_allow_double_quotes: 0,
48+
readonly: "1", // Ensure queries are read-only
49+
};
50+
}
51+
2452
export type ExecuteQueryOptions<TOut extends z.ZodSchema> = Omit<
2553
ExecuteTSQLOptions<TOut>,
2654
"tableSchema" | "organizationId" | "projectId" | "environmentId" | "fieldMappings"
@@ -89,6 +117,10 @@ export async function executeQuery<TOut extends z.ZodSchema>(
89117
...baseOptions,
90118
...tenantOptions,
91119
fieldMappings,
120+
clickhouseSettings: {
121+
...getDefaultClickhouseSettings(),
122+
...baseOptions.clickhouseSettings, // Allow caller overrides if needed
123+
},
92124
});
93125

94126
// If query succeeded and history options provided, save to history

internal-packages/clickhouse/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ClickHouseSettings } from "@clickhouse/client";
1+
import type { ClickHouseSettings } from "@clickhouse/client";
2+
export type { ClickHouseSettings };
23
import { ClickhouseClient } from "./client/client.js";
34
import { ClickhouseReader, ClickhouseWriter } from "./client/types.js";
45
import { NoopClient } from "./client/noop.js";

0 commit comments

Comments
 (0)