You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since #170 ("chore: 0025 query_to_xml workaround", merged 2026-07-02), 0025_public_bucket_allows_listing no longer reads storage.buckets itself. The view now reads a GUC:
and the storage.buckets read moved into a preamble DO block that exists only in the compiled splinter.sql, which populates the GUC transaction-locally:
Consequence: any consumer that executes the lint query without running that preamble in the same transaction gets zero findings — indistinguishable from a genuinely clean result. The lint fails open. #170 itself had to switch this repo's CI runner to psql --single-transaction to keep the GUC visible, which illustrates the hazard: the contract is real, but it lives only in the compiled artifact and CI invocation, and the README documents the pgrst.db_schemas dependency while splinter.public_buckets is undocumented.
Real-world impact (hosted advisor path)
On our hosted project, 0025 reported two findings (user-avatars, workspace-branding) through 2026-06-10. Sometime after #170, the findings disappeared from the hosted security-advisor results while both flagged conditions still hold — we re-verified by executing the lint's own predicate manually with the bucket list supplied: both broad PERMISSIVE SELECT policies still exist and both findings reproduce exactly. We can't inspect the hosted advisor runner, but the observable symptom is precisely what a runner that doesn't execute the preamble in-transaction would produce, and no other 0025-touching change exists in the window.
For an advisor whose job is to flag data exposure, "input not supplied" being indistinguishable from "no exposure found" seems worth closing: consumers (including us) read the absence of findings as a clean bill.
The same hazard is now formalized in the manifest
The versioned splinter.json manifest publishes per-lint query fields with a separatesetup field. A consumer that runs a lint's query without executing setup in the same transaction reproduces the same silent zero for 0025.
Prior art
This is the same failure class as the unset-pgrst.db_schemas case (supabase/cli#5868, fixed by #168 coalescing to 'public'). The difference: 0025 has no sane inline default available — an empty bucket list doesn't degrade the lint, it disables it silently.
Suggestions
Document the splinter.public_buckets contract in the README alongside pgrst.db_schemas, including the transaction-local requirement.
Prefer fail-loud over fail-open: when the setting is absent (as opposed to a legitimately empty []), either raise, or emit a sentinel "not evaluated" row, so runners that skip the preamble become visible instead of silently green.
Summary
Since #170 ("chore: 0025 query_to_xml workaround", merged 2026-07-02),
0025_public_bucket_allows_listingno longer readsstorage.bucketsitself. The view now reads a GUC:coalesce( nullif(pg_catalog.current_setting('splinter.public_buckets', true), '')::pg_catalog.jsonb, '[]'::pg_catalog.jsonb )and the
storage.bucketsread moved into a preambleDOblock that exists only in the compiledsplinter.sql, which populates the GUC transaction-locally:Consequence: any consumer that executes the lint query without running that preamble in the same transaction gets zero findings — indistinguishable from a genuinely clean result. The lint fails open. #170 itself had to switch this repo's CI runner to
psql --single-transactionto keep the GUC visible, which illustrates the hazard: the contract is real, but it lives only in the compiled artifact and CI invocation, and the README documents thepgrst.db_schemasdependency whilesplinter.public_bucketsis undocumented.Real-world impact (hosted advisor path)
On our hosted project, 0025 reported two findings (
user-avatars,workspace-branding) through 2026-06-10. Sometime after #170, the findings disappeared from the hosted security-advisor results while both flagged conditions still hold — we re-verified by executing the lint's own predicate manually with the bucket list supplied: both broadPERMISSIVESELECT policies still exist and both findings reproduce exactly. We can't inspect the hosted advisor runner, but the observable symptom is precisely what a runner that doesn't execute the preamble in-transaction would produce, and no other 0025-touching change exists in the window.For an advisor whose job is to flag data exposure, "input not supplied" being indistinguishable from "no exposure found" seems worth closing: consumers (including us) read the absence of findings as a clean bill.
The same hazard is now formalized in the manifest
The versioned
splinter.jsonmanifest publishes per-lintqueryfields with a separatesetupfield. A consumer that runs a lint'squerywithout executingsetupin the same transaction reproduces the same silent zero for 0025.Prior art
This is the same failure class as the unset-
pgrst.db_schemascase (supabase/cli#5868, fixed by #168 coalescing to'public'). The difference: 0025 has no sane inline default available — an empty bucket list doesn't degrade the lint, it disables it silently.Suggestions
splinter.public_bucketscontract in the README alongsidepgrst.db_schemas, including the transaction-local requirement.[]), either raise, or emit a sentinel "not evaluated" row, so runners that skip the preamble become visible instead of silently green.storage.bucketsdirectly when the GUC is absent and thestorageschema exists (the pre-chore: update 0025 not to use query_to_xml #170 behavior), using whatever construction avoids the originalquery_to_xmlproblem that motivated chore: update 0025 not to use query_to_xml #170.Happy to provide the manual reproduction steps or test against a fix.