RowShield
Guides

The same Security Advisor warning keeps coming back

You dismissed it, fixed it, watched it clear — and there it is again on the next look: the same Security Advisor warning, identical wording, third time this month. The advisor is a good tool reporting honestly; the recurrence is the information. Something in the project's life keeps undoing the fix, and no amount of re-fixing addresses that.

This page takes recurrences seriously as a signal. It covers why point-in-time checks meet regressing states, the handful of mechanisms that reliably resurrect old problems, a way to adjudicate each return methodically, and how transitions — created, regressed, resolved — turn the loop into something you can reason about. One scope note up front: recurring warnings are not one of RowShield's nine named rules, so this page declares no rule backing; the drift diffing that classifies transitions is shipped product behaviour, but it is not a rule.

RowShield does not detect this yet. This guide gives you the catalog queries to check it yourself. The nine rules that do ship are listed on the rules index.

Why the same warning returns

The advisor reports state at the moment it is consulted, accurately. Between consultations, the database keeps living: migrations land, hotfixes happen in the console, environments promote over one another. A warning that cleared can absolutely be true again by Friday, and the second sighting differs from the first in one vital respect — it proves the fix did not stick, not that the check misfired.

Treating each return as brand-new work guarantees exhaustion. The productive reframe is forensic: something restored an earlier state, and naming that mechanism ends the cycle, because the durable fix targets the cause — the restore job, the console edit, the recreate-and-forget migration — rather than the symptom it keeps producing.

The usual suspects

Three mechanisms account for most resurrections. Restores: recovering from backup reinstates the schema as it was, holes included. Drop-and-recreate: iterating on a table by dropping it loses its policies with it, and the replacement ships naked. Console edits: a hotfix applied outside the repository repairs production tonight and vanishes from the record, reverting on the next promotion from an environment that never heard about it.

Restores deserve special mention because they arrive disguised as rescue operations. Recovering from an incident by rewinding the database rewinds its protections to whatever they were when the backup was taken — including last month's hole, faithfully preserved. Nobody reviews a successful restore as a security event, which is exactly the gap.

Adjudicate the return methodically

Start from current state rather than memory. For the commonest recurring class — tables without row-level security — one catalog query lists exactly what holds right now, which tells you whether you are re-fixing the same table or discovering that the problem spread:

SELECT n.nspname AS schema,
       c.relname AS table_name,
       c.relrowsecurity AS rls_enabled
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'p')
  AND n.nspname = 'public'
  AND c.relrowsecurity = false
ORDER BY c.relname;

Reconstruct the interval

Then reconstruct the interval between the fix and the return. Migration history first: did anything drop, recreate or restore? Repository second: does the applied migration record contain the fix at all, or only the console? The answers sort recurrences into two kinds — a repeating destroyer to disable, or a fix that never entered the durable path and therefore never truly happened.

Transitions, and what they are called here

RowShield scans on a schedule, snapshots posture, and diffs consecutive runs. A problem seen for the first time is created; one that was resolved and has returned is regressed, a deliberately heavier word; one fixed and holding is resolved. Alerting fires on those transitions only, so a project stuck in the loop pages you on each genuine change instead of every hour.

Precision about scope, stated twice for good reason: this classification is shipped drift-diffing behaviour, not one of the nine named rules, which is why this page carries an empty rule list and says so. RowShield is an independent product, unaffiliated with and not endorsed by Supabase, and it complements the advisor rather than replacing it — the advisor judges depth on demand; scheduled diffing watches the intervals. Run a free audit — no account — at rowshield.dev/audit.

Frequently asked

Is the Security Advisor unreliable, then?
No — the advisor is a good tool that reports what it finds accurately when consulted. Recurrence means the underlying state returned between consultations, which is a property of the interval, not a defect in the check.
How do I find what reverted the fix?
Reconstruct the interval: migration history, restore jobs, and console activity. A fix absent from the repository was never durably applied, and a restore explains a fix that vanished wholesale along with newer schema.
Will alerts repeat while a problem persists?
No. Alerts fire on transitions — created, regressed, resolved — so a project sitting broken pages once, and the next alert arrives when the state genuinely changes rather than on a timer.

Check your project in about ten seconds

Paste a URL. No signup, no writes, nothing stored.

Run the free audit
supabase security advisor warning returnsadvisor finding reappearsrls warning keeps returningsupabase advisor drift