From b1790f351863971f1f4933779814c77c9748861a Mon Sep 17 00:00:00 2001 From: lawrence3699 Date: Sun, 5 Apr 2026 08:50:53 +1000 Subject: [PATCH] fix(table): escape LIKE wildcards in $contains filter values The $contains filter operator builds an ILIKE pattern but does not escape LIKE wildcard characters (%, _) in user-provided values. This causes incorrect, over-broad query results when the search value contains these characters. For example, filtering with { name: { $contains: "100%" } } matches any row where name contains "100" followed by anything, not just the literal "100%". Escape %, _, and \ in the value before interpolating into the ILIKE pattern so that they match literally. --- apps/sim/lib/table/sql.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/sim/lib/table/sql.ts b/apps/sim/lib/table/sql.ts index e21d6c6896..2fea3559b2 100644 --- a/apps/sim/lib/table/sql.ts +++ b/apps/sim/lib/table/sql.ts @@ -322,10 +322,15 @@ function buildComparisonClause( return sql`(${sql.raw(`${tableName}.data->>'${escapedField}'`)})::numeric ${sql.raw(operator)} ${value}` } +/** Escapes LIKE/ILIKE wildcard characters so they match literally */ +function escapeLikePattern(value: string): string { + return value.replace(/[\\%_]/g, '\\$&') +} + /** Builds case-insensitive pattern match: `data->>'field' ILIKE '%value%'` */ function buildContainsClause(tableName: string, field: string, value: string): SQL { const escapedField = field.replace(/'/g, "''") - return sql`${sql.raw(`${tableName}.data->>'${escapedField}'`)} ILIKE ${`%${value}%`}` + return sql`${sql.raw(`${tableName}.data->>'${escapedField}'`)} ILIKE ${`%${escapeLikePattern(value)}%`}` } /**