Skip to content

fix(postgrest): escape embedded quotes and backslashes in in()/notIn() filter values - #2489

Open
kazuki-netizen wants to merge 1 commit into
supabase:masterfrom
kazuki-netizen:fix/in-filter-escaping
Open

fix(postgrest): escape embedded quotes and backslashes in in()/notIn() filter values#2489
kazuki-netizen wants to merge 1 commit into
supabase:masterfrom
kazuki-netizen:fix/in-filter-escaping

Conversation

@kazuki-netizen

Copy link
Copy Markdown

What

.in() and .notIn() wrap values containing PostgREST reserved characters (, ( )) in double quotes, but do not escape a " or \ inside the value. A value like a"b,c currently serializes to in.("a"b,c"), whose stray quote breaks PostgREST's list parsing.

Fix

Escape \\\ and "\" (backslash first) before wrapping. This matches PostgREST's quoted-element parser (pQuotedValue in ApiRequest/QueryParams.hs, where a backslash escapes the following character inside quotes; see also PostgREST/postgrest#1938 and supabase/postgrest-js#164). The shared logic is extracted into a small formatInFilterValue() helper used by both in() and notIn(). Simple values are still emitted unquoted — no behavior change for existing callers.

Test

Adds test/in-filter-escaping.test.ts with URL-level assertions (mock fetch, no live server) covering reserved-char quoting, embedded-quote escaping, backslash escaping, simple-value passthrough, and notIn parity. All 6 pass; tsc --noEmit, ESLint, and Prettier are clean on the touched files.

🤖 Generated with Claude Code

…) filter values

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@mandarini mandarini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kazuki-netizen, thank you so much for contributing to Supabase! 💚

This is a real bug and a clean fix. One thing before this can merge: test/in-filter-escaping.test.ts mocks fetch, so it only checks that the code agrees with itself about the expected string, it never proves the value survives a real PostgREST server. This package already has a Docker-backed PostgREST instance for exactly this (nx test:infra postgrest-js), and the existing tests in test/filters.test.ts hit it directly at localhost:54321. Could you add one test there that inserts a row with a tricky value (something like a"b,c) and asserts .in() / .notIn() return it correctly? That gives the fix durable proof against the real server contract instead of just the mock, and it should be a small addition alongside what you already have.

Thank you again for digging into this one, it's contributions like yours that keep these SDKs solid.

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