Skip to content

core encryptQuery mints every-row-matching terms for 1–2 char free-text match needles (Supabase adapter guards, core doesn't) #697

Description

@coderdan

Summary

Found by the rc.2 skilltester run (2026-07-17, GA blocker B2). Core encryptQuery will happily produce a free-text match query term for a 1–2 character needle. Because of how the match index tokenises, such a term matches essentially every row, silently turning LIKE '%ab%'-style searches into full-table matches instead of a real filter.

The Supabase v3 adapter already guards against this (short-needle rejection in its query builder), but the core encryptQuery path — which every other surface (Drizzle, raw pg, prisma-next) goes through — does not. So the protection is inconsistent: it depends on which adapter you happen to use, and the no-ORM / raw-SQL surfaces get no protection at all.

Impact

  • Correctness / silent data exposure of intent. A query the developer believes is a narrow substring search returns every row. On an access-controlled surface (e.g. RLS + PostgREST), a match term that matches all rows can defeat the intended narrowing.
  • Inconsistent behaviour across adapters for the same logical query.

Expected

Core encryptQuery should reject (or at minimum loudly refuse to emit) a free-text match term whose needle is shorter than the minimum the match index can meaningfully discriminate on, with an actionable error naming the minimum length. The rejection belongs in the core so every surface inherits it, and the Supabase adapter's bespoke guard can then defer to it.

Also

  • The stash-encryption skill currently overstates free-text search without noting the minimum-needle constraint — fix that claim in the same change (see AGENTS.md "check the skills").

Repro sketch

  1. Encrypt a free-text/match column.
  2. encryptQuery('ab', { table, column, queryType: 'match' }) (a 2-char needle).
  3. Run the resulting term against a populated table → it matches all rows rather than only those containing ab.

References

  • rc.2 skilltester report: docs/evals/2026-07-17-rc2-full-run-report.md
  • Supabase adapter's existing guard is the reference behaviour to lift into core.

https://claude.ai/code/session_01MxTTPaPP16m6br7Hoab94w

Metadata

Metadata

Assignees

Labels

SDKbugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions