Saltar para o conteúdo

Supabase "RLS disabled in public": o que significa

Supabase

Ver como MarkdownAbrir em ClaudeAbrir em ChatGPTAbrir em Perplexity

A pergunta também é copiada. Se o chat abrir vazio, cole-a.

Em resumo

“RLS Disabled in Public” (lint 0013_rls_disabled_in_public, nível ERROR) significa que uma tabela de um schema exposto tem o row level security desligado enquanto anon ou authenticated podem fazer select nela. No meu teste local, a chave pública leu as 3 linhas de 3 de uma tabela assim e inseriu uma nova com 201 Created. Ligue o RLS, junte uma política por operação e verifique os grants, tudo numa migração.

Criei um verificador de segurança do Supabase gratuito, e a sua primeira regra, “RLS desativado em tabelas expostas”, é o mesmo achado que o Security Advisor do Supabase reporta como erro. É a falha mais comum que encontro em apps feitas com ferramentas de IA, por isso aqui fica o que significa e o que permitiu quando a reproduzi.

O que significa “RLS disabled in public”?

O Security Advisor executa um lint chamado rls_disabled_in_public. O seu SQL assinala uma tabela quando três coisas se verificam ao mesmo tempo:

  1. É uma tabela normal com o row level security desligado.
  2. anon ou authenticated têm SELECT sobre ela.
  3. O seu schema está na lista Exposed schemas da Data API, que por omissão é public.

A página do lint classifica-o como ERROR e chama ao create, read, update e delete completos pela internet “a critically unsafe configuration” (uma configuração criticamente insegura). O “public” do nome é o schema, mas o lint cobre todos os schemas expostos, e é por isso que um schema extra nessa lista também merece uma vista de olhos; escrevi sobre isso em Supabase exposed schemas.

O que pode a chave pública fazer a essa tabela?

Criei uma tabela orders com três clientes falsos numa stack local do Supabase (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), com os grants que os projetos existentes dão às tabelas novas, e o RLS desligado. Depois chamei a Data API com a publishable key, como o faz um browser:

Uma tabela, a chave pública, com RLS desligado e ligado. Supabase local, 3 linhas de encomendas falsas. RLS desligado, leitura: Publishable key → orders, sem RLS → 3 de 3 linhas; RLS desligado, inserção: Publishable key → orders, sem RLS → 201 Created; RLS ligado, ainda sem política: Publishable key → orders, com RLS → 0 linhas.
A minha reprodução numa stack local do Supabase, 23 de outubro de 2026.
Pedido com a publishable key RLS desligado RLS ligado, sem política
GET /rest/v1/orders?select=* 200, as 3 linhas com nomes e emails 200, []
POST /rest/v1/orders com uma linha nova 201 Created 401, 42501 “new row violates row-level security policy”

Qualquer pessoa que abra a sua app pode copiar a publishable key da página. Com o RLS desligado, a chave é um passe de leitura e escrita para essa tabela.

Como corrigir sem estragar a app?

Ligar só o RLS faz com que a tabela não devolva nada à app, porque ainda não há nenhuma política. É nesse ecrã vazio que as pessoas, e as ferramentas de IA, juntam uma política com using (true), que devolve todas as linhas a toda a gente. Porque é que os updates e deletes passam a dar sucesso sem alterar nada está em Como ativar o RLS no Supabase e o que devolve. Escreva as políticas reais na mesma migração:

alter table public.orders enable row level security;

revoke all on table public.orders from anon, authenticated;
grant select, insert on table public.orders to authenticated;

create policy "Customers read their orders"
on public.orders for select
to authenticated
using ((select auth.uid()) = user_id);

create policy "Customers create their orders"
on public.orders for insert
to authenticated
with check ((select auth.uid()) = user_id);

Se uma tabela é para ser pública, como uma lista de artigos publicados, mantenha o RLS ligado na mesma e escreva uma só política select para anon, sem grants de escrita. Se nunca usa a Data API e fala com o Postgres só a partir do seu servidor, retire public de Exposed schemas, como os mantenedores do Supabase sugeriram no mesmo issue.

Para garantir que as tabelas novas nunca começam sem RLS, o guia de event triggers do Supabase tem um trigger que o liga em todas as tabelas criadas em public. E, a partir de 30 de outubro de 2026, as tabelas novas não recebem grants da Data API por omissão, por isso respondem 42501 até lhes dar o grant; tratei disso em Supabase 42501 permission denied.

O que não prova um resultado limpo?

Que o RLS esteja ligado não diz nada sobre se as políticas estão certas. No mesmo teste, uma política escrita como using (true) voltou a dar à chave pública as 3 linhas, e este lint fica calado assim que o RLS está ligado. O verificador tem uma regra à parte para isso, “Políticas que permitem todas as linhas”, e como testar o Supabase RLS mostra como provar cada política com utilizadores reais. Políticas para começar, cada uma testada com utilizadores reais através da API, estão em Exemplos de RLS policy no Supabase, testados pela API.

© 2026 Denys Zaichenko. Artigo original: https://madsalt.tech/pt/notes/supabase-rls-disabled-in-public/