Adjudicating between behaviour and configuration
The Security Advisor built into your project dashboard and RowShield watch the same database from different angles, so occasionally they disagree: one reports a concern the other calls clean.
These disagreements are rarely a bug on either side. They follow from what each instrument can physically observe, and once you know which is which, adjudication takes seconds. This article explains the division of labour, walks through the common conflict patterns, and states plainly where the advisor is ahead of us today.
Two instruments, two blind spots
RowShield is behavioural. The probe exercises the same path a stranger would: the anon key against the REST surface, and public storage objects. Its verdicts answer one question with authority: can data actually be read right now?
The advisor is configurational. It inspects the catalogue statically — policy definitions, function attributes, extension placement, grants — and reasons about what that configuration permits or risks. Its authority covers questions no probe can settle by observation alone.
Each blindness mirrors the other's strength. A probe cannot see inside a function body, so a mutable search_path setting is invisible to it. Static inspection cannot prove runtime effect, so a policy that reads soundly can still admit every row. Neither tool is wrong when they disagree; they are answering different questions.
Common conflicts and how to read them
The advisor is satisfied but the probe finds rows. Something in the configuration is more permissive than it appears: a policy whose predicate collapses to true for the anon role, a view carrying rows past the table's policies, or a grant made directly to a broad role. For exposure questions, behaviour wins — if the probe read rows, they are readable, whatever the labels say.
The probe is quiet but the advisor raises warnings. Typical examples are a security definer function with a mutable search_path, or an extension installed into a widely shared schema. The probe cannot observe these, so silence here is agreement about exposure, nothing more.
Both raise concerns that look different. Often these converge on one root cause, such as a missing policy the advisor flags statically and the probe demonstrates dynamically. Fix it once, rescan, and both should clear together.
Where the advisor is ahead
Today the advisor is ahead of RowShield on security definer functions and search-path hygiene. Analysing those properly means parsing function bodies and reasoning about qualification, which sits on our roadmap under definer-analysis candidates but is not shipping yet. Until then, treat the advisor as the source of truth in that corner and treat our silence there as silence rather than approval.
As a general rule: ask whether data is exposed, and trust the probe. Ask whether the configuration is fragile, and trust the advisor. If a disagreement still seems wrong after that, send us both the scan identifier and the advisor snapshot, and we will reconcile the two rule by rule.
Did this answer your question? If not, tell us what is missing — article corrections go straight to the person who maintains it.