Skip to content

fix(realtime): escape quotes and backslashes in in filter values#1506

Merged
spydon merged 3 commits into
supabase:mainfrom
AndroidPoet:fix/realtime-in-filter-escape
Jul 2, 2026
Merged

fix(realtime): escape quotes and backslashes in in filter values#1506
spydon merged 3 commits into
supabase:mainfrom
AndroidPoet:fix/realtime-in-filter-escape

Conversation

@AndroidPoet

Copy link
Copy Markdown
Contributor

What

PostgresChangeFilter.toString() builds the in filter by quoting each value, but never escapes the value first. A value containing a double quote or backslash produces a malformed filter:

PostgresChangeFilter(
  type: PostgresChangeFilterType.inFilter,
  column: 'name',
  value: ['a"b'],
).toString();
// name=in.("a"b")  <-- the inner " breaks the quoted element

This escapes \ and " inside each element before quoting, so the value stays a single well-formed token.

Why

The realtime in filter had the same missing-escaping bug that was fixed for postgrest in #1481 (_cleanFilterArray), but the realtime copy in types.dart was never updated:

return '$column=in.(${value.map((s) => '"$s"').join(',')})';

Any subscription filtering on a list whose values contain " or \ sends a broken filter to the Realtime server. The fix mirrors the PostgREST/PostgreSQL array quoting used by PostgrestFilterBuilder:

final escaped = '$s'.replaceAll(r'\', r'\\').replaceAll('"', r'\"');
return '"$escaped"';

Not a breaking change

Values without " or \ render exactly as before (in.("active","pending")), and non-in filters are untouched. Only previously-malformed output changes.

Tests

Added packages/realtime_client/test/postgres_change_filter_test.dart: asserts ['a"b\c'] renders as name=in.("a\"b\\c"), that plain values are unchanged, and that non-in filters are unaffected. The escaping test fails on the old code (Actual: name=in.("a"b\c")) and passes with the fix. dart format and dart analyze --fatal-warnings are clean.

PostgresChangeFilter.toString() quoted each `in` filter value without
escaping it, so a value containing a double quote or backslash (e.g.
`a"b`) produced a malformed filter like `in.("a"b")`. Escape `\` and
`"` inside each element before quoting, matching the PostgREST array
quoting used by PostgrestFilterBuilder.
@AndroidPoet AndroidPoet requested a review from a team as a code owner July 1, 2026 14:57
spydon added 2 commits July 2, 2026 12:17
…scaped `in` filters

Removes comments that only restated the escaping logic already visible in
the code, and adds a channel test that exercises the actual join-ack
matching path with a value containing a quote and backslash, since the
existing unit test only covered PostgresChangeFilter.toString() in
isolation.
@spydon spydon enabled auto-merge (squash) July 2, 2026 10:24
@spydon spydon merged commit 30349e2 into supabase:main Jul 2, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants