Skip to content

Commit 35b8220

Browse files
committed
Complete PromQL escaping across all 150+ interpolation sites, add statement_timeout
Continuation of the quality framework application: Reporter (postgres_reports.py): - Apply _escape_promql_label() to ALL 150+ PromQL label interpolation sites across 20+ functions (A003, A004, A007, H001, H002, H004, D004, F001, F004, F005, G001, K-series, M-series, N001) - Add _esc alias at function scope for every method that builds PromQL - Make _escape_promql_label defensive with str() coercion for edge cases Flask backend (app.py): - Apply escape_promql_label() to remaining 2 filter-building sites (table metrics and table size detail endpoints) CLI (init.ts): - Add connectionTimeoutMillis: 10_000 to connectWithSslFallback() (central connection function used by checkup, prepare-db, etc.) - Add SET statement_timeout = '30s' after connection to prevent runaway queries across all CLI database operations All 429 reporter tests pass with no regressions. https://claude.ai/code/session_01TKKnEc2Yn2zM64bwCJ2UaX
1 parent b7cb2f3 commit 35b8220

File tree

3 files changed

+110
-85
lines changed

3 files changed

+110
-85
lines changed

cli/lib/init.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ export async function connectWithSslFallback(
127127
verbose?: boolean
128128
): Promise<{ client: PgClient; usedSsl: boolean }> {
129129
const tryConnect = async (config: PgClientConfig): Promise<PgClient> => {
130-
const client = new ClientClass(config);
130+
const client = new ClientClass({ ...config, connectionTimeoutMillis: 10_000 } as any);
131131
await client.connect();
132+
// Set a default statement timeout to prevent runaway queries
133+
await client.query("SET statement_timeout = '30s'");
132134
return client;
133135
};
134136

monitoring_flask_backend/app.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -703,20 +703,21 @@ def get_btree_bloat_csv():
703703
tblname = request.args.get('tblname')
704704
idxname = request.args.get('idxname')
705705

706-
# Build label filters
706+
# Build label filters (escape values to prevent PromQL injection)
707+
_esc = escape_promql_label
707708
filters = []
708709
if cluster_name:
709-
filters.append(f'cluster="{cluster_name}"')
710+
filters.append(f'cluster="{_esc(cluster_name)}"')
710711
if node_name:
711-
filters.append(f'node_name="{node_name}"')
712+
filters.append(f'node_name="{_esc(node_name)}"')
712713
if schemaname:
713-
filters.append(f'schemaname="{schemaname}"')
714+
filters.append(f'schemaname="{_esc(schemaname)}"')
714715
if tblname:
715-
filters.append(f'tblname="{tblname}"')
716+
filters.append(f'tblname="{_esc(tblname)}"')
716717
if idxname:
717-
filters.append(f'idxname="{idxname}"')
718+
filters.append(f'idxname="{_esc(idxname)}"')
718719
if db_name:
719-
filters.append(f'datname="{db_name}"')
720+
filters.append(f'datname="{_esc(db_name)}"')
720721

721722
filter_str = '{' + ','.join(filters) + '}' if filters else ''
722723

@@ -841,19 +842,20 @@ def get_table_info_csv():
841842
except ValueError:
842843
end_dt = datetime.fromisoformat(time_end.replace('Z', '+00:00'))
843844

844-
# Build label filters
845+
# Build label filters (escape values to prevent PromQL injection)
846+
_esc = escape_promql_label
845847
filters = []
846848
if cluster_name:
847-
filters.append(f'cluster="{cluster_name}"')
849+
filters.append(f'cluster="{_esc(cluster_name)}"')
848850
if node_name:
849-
filters.append(f'node_name="{node_name}"')
851+
filters.append(f'node_name="{_esc(node_name)}"')
850852
if schemaname:
851853
# Support regex pattern matching with =~
852-
filters.append(f'schemaname=~"{schemaname}"')
854+
filters.append(f'schemaname=~"{_esc(schemaname)}"')
853855
if tblname:
854-
filters.append(f'tblname="{tblname}"')
856+
filters.append(f'tblname="{_esc(tblname)}"')
855857
if db_name:
856-
filters.append(f'datname="{db_name}"')
858+
filters.append(f'datname="{_esc(db_name)}"')
857859

858860
filter_str = '{' + ','.join(filters) + '}' if filters else ''
859861

0 commit comments

Comments
 (0)