diff --git a/.server-changes/fix-realtime-tags-sql-escape.md b/.server-changes/fix-realtime-tags-sql-escape.md new file mode 100644 index 0000000000..04b81669ec --- /dev/null +++ b/.server-changes/fix-realtime-tags-sql-escape.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: fix +--- + +Hardened realtime run filtering so special characters in tags cannot interfere with the query. diff --git a/apps/webapp/app/services/realtimeClient.server.ts b/apps/webapp/app/services/realtimeClient.server.ts index 9797eeebf4..8ec0c5aba1 100644 --- a/apps/webapp/app/services/realtimeClient.server.ts +++ b/apps/webapp/app/services/realtimeClient.server.ts @@ -171,7 +171,10 @@ export class RealtimeClient { const whereClauses: string[] = [`"runtimeEnvironmentId"='${environment.id}'`]; if (params.tags) { - whereClauses.push(`"runTags" @> ARRAY[${params.tags.map((t) => `'${t}'`).join(",")}]`); + // Escape single quotes so user-provided tags cannot break out of the + // ARRAY literal (Electric WHERE clause is string-interpolated). + const escapedTags = params.tags.map((t) => `'${t.replace(/'/g, "''")}'`).join(","); + whereClauses.push(`"runTags" @> ARRAY[${escapedTags}]`); } const createdAtFilter = await this.#calculateCreatedAtFilter(url, params.createdAt);