Escape candidates search filters#407
Conversation
Greptile SummaryThis PR escapes user-controlled text before it is interpolated into PostgREST
Confidence Score: 3/5Not safe to merge as-is: the agents query builder has the same unescaped filter interpolation that this PR set out to fix, and the new array-literal escape function over-escapes LIKE wildcard characters that are not meaningful in the contains-operator context. The candidates path is correctly patched and well tested, but src/lib/queries/agents.ts needs the same escaping treatment applied to candidates.ts; src/lib/security/sanitize.ts needs the array-literal escape function to be decoupled from LIKE-wildcard escaping. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User input: q or tags] --> B{Filter type?}
B -- text search --> C[escapePostgrestSearchValue\nescapes backslash pct star underscore comma dot parens]
B -- tag filter --> D[escapePostgrestArrayLiteralValue\ncalls escapePostgrestSearchValue then escapes quotes and braces]
C --> E["query.or('full_name.ilike.%escaped%,...')"]
D --> F["query.or('skills.cs.{escaped},...')"]
E --> G[PostgREST API]
F --> G
G --> H[PostgreSQL]
D --> W["WARNING: pct star underscore also escaped\nnot needed for cs contains operator"]
Reviews (1): Last reviewed commit: "Escape candidates search filters" | Re-trigger Greptile |
| export function escapePostgrestArrayLiteralValue(value: string): string { | ||
| return escapePostgrestSearchValue(value).replace(/["{}]/g, (char) => `\\${char}`); | ||
| } |
There was a problem hiding this comment.
LIKE-wildcard escaping incorrectly applied to array-literal values
escapePostgrestArrayLiteralValue delegates first to escapePostgrestSearchValue, which escapes %, _, and * as LIKE wildcard characters. Those characters have no special meaning inside a PostgreSQL double-quoted array element used with the cs (contains) operator — PostgreSQL stores them literally and matches them by equality. Escaping them inserts a literal backslash into the stored comparison value, so a tag named 100%off would be queried as 100\%off and silently fail to match any row. Only " and \ need to be escaped for the PostgreSQL array literal layer; ,, ., (, ), %, _, * are PostgREST filter-syntax and LIKE concerns that don't apply to the cs value.
| export function escapePostgrestArrayLiteralValue(value: string): string { | ||
| return escapePostgrestSearchValue(value).replace(/["{}]/g, (char) => `\\${char}`); | ||
| } |
There was a problem hiding this comment.
escapePostgrestArrayLiteralValue has no direct unit tests in sanitize.test.ts
The new function is exported from sanitize.ts but sanitize.test.ts only imports and tests escapePostgrestSearchValue, sanitizeUrlParam, and sanitizeSearchParams. Coverage currently exists only through the integration-level candidates.test.ts. Adding a unit test alongside the existing escapePostgrestSearchValue block (e.g., covering backslash, quote, and brace combinations) would make it easier to iterate on the function in isolation.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Fixes #406.
Changes:
Validation: