Saltar para o conteúdo
GUIAS

Supabase RLS: como verificar se os dados da tua app estão expostos

Por Guilherme Menezes. Última revisão: 6 de novembro de 2026.

Row Level Security (RLS) é a funcionalidade do Postgres que decide que linhas de uma tabela cada pedido pode ler ou alterar. Se a tua app usa Supabase e uma tabela não tem RLS, qualquer pessoa com a chave pública pode conseguir ler e alterar os dados dela. Para confirmar, verifica se o RLS está ativo em cada tabela e testa com dois utilizadores diferentes.

Porque é que isto é tão grave?

A chave pública do Supabase (a publishable, ou a antiga anon) foi feita para estar no código da app, e qualquer pessoa a consegue ler. A documentação do Supabase é clara: o que protege os dados são as regras de RLS, não o segredo dessa chave.

Sem RLS, uma tabela num esquema exposto pode ser lida e alterada por qualquer papel que tenha permissões sobre ela. Em projetos que ainda dão permissões por defeito, as tabelas novas em public começam com todos os privilégios atribuídos a anon, authenticated e service_role.

Como vejo se uma tabela tem RLS ativo?

No editor de SQL do Supabase, corre esta consulta:

select tablename, rowsecurity
from pg_tables
where schemaname = 'public';

Cada linha com rowsecurity a false é uma tabela sem RLS. Se ela guardar dados que não são públicos, é o primeiro problema a resolver.

Como ativo o RLS?

alter table public.faturas enable row level security;

Com o RLS ativo e sem regras, a API deixa de devolver dados com a chave pública. A tua app pode parecer avariada até criares as regras, por isso faz isto primeiro num ambiente de teste.

Como escrevo uma regra que limita cada utilizador aos seus dados?

Esta regra deixa cada utilizador ler só as suas faturas. Assume que a coluna user_id guarda o dono:

create policy "Cada utilizador lê as suas faturas"
on public.faturas for select
to authenticated
using ( (select auth.uid()) = user_id );

auth.uid() devolve o id de quem faz o pedido, ou null se não tiver sessão. Precisas de uma regra para cada operação que a app usa: select, insert, update e delete.

O RLS ativo chega?

Não. Estes são os erros que deves procurar a seguir:

  • Regras abertas a todos. using ( true ) para anon expõe todas as linhas a qualquer visitante. Só faz sentido para dados públicos.
  • insert e update sem with check. Sem esta condição, um utilizador pode conseguir gravar linhas em nome de outro.
  • Chave secreta no browser. A chave secret e a antiga service_role ignoram o RLS. Nunca podem estar no código que corre no browser. Lê o guia sobre chaves expostas.
  • Código de servidor sem verificações. Uma função que usa a chave secreta ignora as regras, por isso tem de confirmar ela própria quem pode fazer o quê.

Como testo de verdade?

Ler as regras não chega: testa-as.

  1. Cria dois utilizadores de teste, A e B, cada um com dados próprios.
  2. Com a sessão de A, tenta ler, alterar e apagar os dados de B.
  3. Sem sessão, tenta fazer o mesmo com a chave pública.
  4. Repete para cada tabela com dados privados.

Faz estes testes só na tua app e num ambiente de teste. Se algum pedido devolver ou alterar dados que não devia, tens uma falha a corrigir antes de lançar.

Fontes

Queres que eu reveja a tua app?

Envia-me o repositório. Respondo em 1 dia útil com o âmbito e o preço fechado. A auditoria demora de 3 a 5 dias úteis depois de aceitares o âmbito.