No Trinco · Capítulo 5 · Amostra
A chave estava certa. O banco estava aberto.
Como testar e corrigir regras do Supabase. Versão de novembro de 2026.
Use somente no laboratório ou em sistema autorizado. Os comandos abaixo são para comprovar uma falha no seu ambiente. Fazer isso em apps de terceiros sem autorização pode gerar responsabilidade legal.
O que aconteceu
Moltbook
Em janeiro de 2026, a Wiz analisou a rede social de agentes Moltbook navegando como um usuário comum. No JavaScript público havia a URL do projeto Supabase e uma chave pública. Até aí, isso pode ser normal.
O problema estava no banco: sem regras adequadas de RLS, essa chave dava acesso de leitura e escrita. A Wiz relatou cerca de 1,5 milhão de tokens, aproximadamente 35 mil e-mails e 4.060 conversas privadas acessíveis. O time corrigiu em etapas, em poucas horas, e novos pontos expostos foram aparecendo durante o processo. (Wiz)
Projetos publicados na Lovable
Em 2025, pesquisadores relataram RLS inadequado em 170 de 1.645 projetos analisados, com 303 endpoints expostos. Em um site, conseguiram inserir um registro com "payment_status": "paid", sem passar pela Stripe. O relato é dos pesquisadores e descreve também críticas à resposta da empresa. (declaração sobre o CVE-2025-48757)
Por que isso acontece
O navegador precisa falar com o Supabase, então uma chave pública costuma aparecer no código. A proteção real fica em duas camadas: permissões do banco e políticas de RLS.
A documentação do Supabase orienta ativar RLS em toda tabela de um schema exposto. Ela também avisa que uma política to anon using (true) expõe todas as linhas a qualquer visitante.
Três erros recorrentes:
- Criar a tabela e esquecer o RLS.
- Criar uma política, mas abrir mais do que devia.
- Proteger a leitura e esquecer inclusão, alteração ou exclusão.
O que isso prova sobre IA? Não prova que a IA sempre gera esse erro. Mostra que um app pode parecer pronto e funcionar bem na tela, enquanto a regra mais importante está errada.
Teste no laboratório
Suba a DemoAgenda na versão vulnerável com npm run iniciar. Ela roda só em 127.0.0.1, com dados fictícios. Depois, em Bash ou Git Bash, defina as variáveis mostradas no terminal.
Missão 1: ler sem login
curl "$SUPABASE_URL/rest/v1/agendamentos?select=id,cliente_nome&limit=1" \
-H "apikey: $CHAVE_PUBLICA"
Resultado vulnerável: a API devolve um registro fictício.
Resultado esperado depois da correção: no laboratório, HTTP 401 com permissão negada. Em outro projeto, o retorno pode ser erro ou lista vazia, conforme as permissões da tabela.
Missão 2: tentar alterar
curl -X PATCH "$SUPABASE_URL/rest/v1/agendamentos?id=eq.1" \
-H "apikey: $CHAVE_PUBLICA" \
-H "Content-Type: application/json" \
-H "Prefer: return=representation" \
-d '{"status":"cancelado"}'
Faça este teste só no laboratório. Se o registro mudar sem login, a escrita também está aberta.
Evite select=* e limite o resultado. Para provar o problema, um registro fictício basta. Em um sistema autorizado com dados reais, pare no mínimo necessário e combine a evidência no escopo.
Como corrigir
Exemplo para uma tabela em que cada usuário acessa só os próprios registros:
alter table public.agendamentos enable row level security;
revoke all on table public.agendamentos from anon;
create policy "ler os proprios agendamentos"
on public.agendamentos for select to authenticated
using ((select auth.uid()) = usuario_id);
create policy "criar os proprios agendamentos"
on public.agendamentos for insert to authenticated
with check ((select auth.uid()) = usuario_id);
create policy "alterar os proprios agendamentos"
on public.agendamentos for update to authenticated
using ((select auth.uid()) = usuario_id)
with check ((select auth.uid()) = usuario_id);
create policy "excluir os proprios agendamentos"
on public.agendamentos for delete to authenticated
using ((select auth.uid()) = usuario_id);
Comandos e SQL testados no laboratório, que usa Postgres real e uma API simplificada. Teste também no seu projeto Supabase antes de publicar a mudança.
Adapte ao seu negócio. Em clínicas, por exemplo, atendentes podem precisar ver mais registros, e essa exceção deve ser explícita. Campos como payment_status não devem poder ser alterados livremente pelo usuário: quem confirma pagamento é o servidor, depois de validar o webhook.
Peça ajuda à sua ferramenta de IA
Liste todas as tabelas públicas do Supabase, indicando se o RLS está ativo e quais políticas existem. Não altere nada ainda. Aponte políticas com using (true), permissões para anon e campos sensíveis que o usuário possa alterar. Depois proponha SQL para cada usuário acessar somente os próprios dados, explicando cada regra.
Como confirmar
- Repita a leitura sem login. Ela não pode devolver dados privados.
- Repita a alteração sem login. Ela precisa falhar.
- Com a conta A, tente ler e alterar um registro da conta B. Precisa falhar.
- Com a conta A, use normalmente os próprios registros. Precisa funcionar.
- Transforme esses testes em verificação automática no projeto.
Se você encontrou uma chave secreta ou service_role exposta, RLS não resolve: essa chave ignora as políticas. Gere outra, revogue a antiga, remova do cliente e investigue acessos.
Se havia dados reais expostos
Corrija, preserve registros e avalie o que foi acessado. No Brasil, a ANPD informa que o controlador deve comunicar incidentes que se enquadrem nas regras em até três dias úteis, salvo prazo específico em lei. Busque orientação jurídica para decidir como isso se aplica ao seu caso.
Checklist do capítulo
- RLS ativo em todas as tabelas expostas
- Permissões revisadas para
anon e authenticated
- Leitura e escrita testadas sem login
- Isolamento testado entre duas contas
- Campos de pagamento e papel protegidos
- Nenhuma chave secreta no navegador
Referências
No guia completo
Este capítulo continua com regras por papel, arquivos no Storage, Firebase e testes automatizados no laboratório.
Conhecer o guia