Example finding How it works Coverage PENTEST METHODOLOGY DOCS PRICING FAQ MCP CONTACT LOG IN SIGN UP →
LANGUAGE

O Supabase é seguro? Análise de Segurança 2026

O Supabase é sólido como plataforma. O risco é tratar a anon key como privada e publicar tabelas sem RLS — o padrão mais comum em apps gerados por IA.

TESTE SEU APP SUPABASE AGORA

Cole a URL do app — usamos a anon key como um atacante e listamos as linhas que ela não deveria alcançar.

RLS não é negociável

O Supabase expõe seu banco PostgreSQL diretamente aos clientes via anon key. Sem políticas de RLS, qualquer pessoa com a URL do seu projeto consegue ler, modificar ou deletar todos os dados nas tabelas desprotegidas. Isso não é um bug — é o modelo de dados. O Supabase foi desenhado para que o banco seja a camada de autorização; se você quebra esse modelo deixando RLS desativado, não existe segunda linha de defesa.

O modelo mental chave: a anon key não é “a chave que só lê” — é a chave que pode fazer exatamente o que suas políticas permitirem. Sem políticas, “tudo é permitido”.

O padrão que mais vemos: geradores de IA (Lovable, Bolt, Cursor) criam cinco tabelas e o frontend que lê delas. Nunca rodam ALTER TABLE x ENABLE ROW LEVEL SECURITY. O app funciona em dev com um usuário. Funciona em prod com um usuário. Funciona com dois — até o usuário B colar o UUID do A na barra de endereço.

Problemas de segurança comuns

Políticas de RLS ausentes

Tabelas sem RLS ativo ficam totalmente acessíveis para qualquer um com a anon key, levando à exposição completa dos dados. Qualquer um que carrega seu frontend vê a URL do Supabase e a anon key na aba Network do DevTools — assim que tem isso, pode chamar https://<project>.supabase.co/rest/v1/<table>?select=* direto com curl.

Habilite RLS por tabela e escreva pelo menos uma política:

alter table profiles enable row level security;
alter table profiles force row level security;

create policy "users read own profile"
  on profiles for select
  to authenticated
  using ( auth.uid() = user_id );

create policy "users update own profile"
  on profiles for update
  to authenticated
  using ( auth.uid() = user_id )
  with check ( auth.uid() = user_id );

Sem with check em update/insert, um usuário pode modificar uma linha de modo que, depois do update, ela pertença a outra user_id.

Liste tabelas ainda abertas:

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

Vazamento da service role key

A service_role key ignora RLS. Expô-la no código do client dá acesso total ao banco para atacantes. Os caminhos de vazamento mais comuns que vemos: em uma env var NEXT_PUBLIC_* do Next.js (tudo com esse prefixo vai pro bundle), em um repo público do GitHub sob .env.example com valor real, ou em uma env var de preview do Vercel mal escopada para o ambiente errado.

Separe estritamente: a service role key vive só em código de servidor (Edge Functions, API routes sem prefixo NEXT_PUBLIC_, workers de backend). Se você precisa dela no navegador, você não precisa dela — você precisa de uma política RLS melhor.

Rotacione imediatamente se suspeitar de vazamento e audite uso anômalo. Use o Token Leak Checker no bundle.

Políticas de RLS com falhas

Políticas de RLS com erros lógicos criam caminhos de acesso não intencionais. Políticas complexas exigem testes minuciosos. Armadilhas clássicas:

-- RUIM: equivalente a não ter RLS
create policy "users can read" on profiles
  for select using (true);

-- BOM: escopo ao usuário autenticado
create policy "users read own profile" on profiles
  for select using (auth.uid() = user_id);

Outras falhas: política só em select esquecendo update/delete/insert; subquery em tabela sem RLS; to anon acidental; FOR ALL demais generoso.

Escreva testes pgTAP por política e rode no CI — RLS sem testes é esperança, não proteção.

Má configuração de Storage buckets

O Supabase Storage também requer RLS. Buckets públicos podem expor arquivos sensíveis. Em uploads, valide MIME por allowlist e ponha limite de tamanho; senão seu bucket vira CDN grátis para conteúdo de terceiros.

create policy "users read own files"
  on storage.objects for select
  using (
    bucket_id = 'avatars'
    and auth.uid()::text = (storage.foldername(name))[1]
  );

Paths previsíveis como /uploads/{user_id}/doc.pdf em bucket público são enumeráveis.

Edge Functions sem checagem de auth

Edge Functions no Supabase rodam com a service role key se você não configura explicitamente de outro jeito. Uma Function que aceita uma request e executa uma operação no banco sem verificar o JWT que chegou é, efetivamente, um endpoint aberto que ignora RLS. Sempre verifique Authorization e prefira o client com o JWT do usuário para o call ao banco.

// Prefira: JWT do usuário, RLS ainda vale
const supabase = createClient(url, anon, {
  global: { headers: { Authorization: req.headers.get("Authorization")! } },
});

Remova --no-verify-jwt de qualquer function que não seja webhook público. Em webhooks, valide assinatura (Stripe, GitHub).

Realtime e postgres-changes

O Supabase Realtime respeita RLS para subscriptions postgres_changes, mas só se o RLS estiver correto. Uma subscription numa tabela legível por todos transmite cada mudança para cada client. Filtre o canal:

supabase.channel("mine")
  .on("postgres_changes", {
    event: "*",
    schema: "public",
    table: "messages",
    filter: `user_id=eq.${user.id}`,
  }, handler)
  .subscribe();

Funções SECURITY DEFINER e RPC

Funções SECURITY DEFINER rodam com privilégios do dono e podem ignorar o contexto RLS do caller. Uma RPC exposta em /rest/v1/rpc que aceita user_id e devolve linhas sem checar auth.uid() é bypass total.

select n.nspname, p.proname, p.prosecdef
from pg_proc p
join pg_namespace n on n.oid = p.pronamespace
where p.prosecdef = true and n.nspname = 'public';

JWT reutilizado entre ambientes

Segredo JWT copiado de staging para prod (ou entre apps) faz token de um ambiente valer no outro. Trate o secret como valor por ambiente.

Como atacantes abusam de um projeto mal configurado

  1. Extrair URL do projeto + anon JWT do bundle JS.
  2. GET /rest/v1/ com a anon key → OpenAPI com todas as tabelas públicas.
  3. GET /rest/v1/<tabela>?select=* — dump se RLS estiver off.
  4. POST forjando linhas (incluindo is_admin: true se o app confiar nessa coluna).
  5. Listar buckets Storage; baixar objetos públicos.
  6. Bater em /auth/v1/token com listas de credenciais se a política de senha for fraca.

Nada disso exige SQL injection. É a API intencional sem as políticas intencionais. O Supabase RLS Checker automatiza os passos 1–3.

Avaliação de segurança

Pontos fortes

    • PostgreSQL com segurança de nível enterprise
    • Row Level Security (RLS) para controle granular de acesso
    • Autenticação embutida com tokens JWT
    • Código aberto — auditável em termos de segurança
    • Conformidade SOC 2 Type II
    • Criptografia em trânsito e em repouso por padrão
    • Chaves JWT de assinatura por projeto

Preocupações

    • Políticas de RLS frequentemente ausentes ou mal configuradas
    • Configurações padrão podem expor dados
    • Anon key vai para o client — RLS é essencial
    • Vazamento da service role key concede acesso total
    • Sintaxe complexa de RLS leva a brechas de segurança
    • SECURITY DEFINER pode contornar RLS em silêncio
    • Buckets de Storage precisam de políticas próprias

Supabase vs Firebase (modelo de regras)

  • Linguagem: SQL CREATE POLICY vs DSL de paths do Firebase.
  • Default após habilitar: RLS sem política = nega tudo. Firebase sem match = nega tudo. Ambos falham com segurança se você parar no meio; ambos falham sem segurança se você colocar true “pra funcionar”.
  • Auth: auth.uid() vs request.auth.uid.
  • Escape privilegiado: service_role vs Admin SDK — origem da maioria dos vazamentos catastróficos.

Aspectos enterprise

O Supabase oferece, nos planos Pro e Team, SSO (SAML), audit logs para ações do dashboard e bancos branch para ambientes de preview isolados. Se você atua em contexto regulado, três pontos são especialmente relevantes:

  • Fronteira SOC 2: O Supabase é SOC 2 Type II compliant, mas a conformidade vale para a plataforma — não para as políticas que você escreve. Uma política RLS ausente é finding seu na auditoria, não do Supabase.
  • Audit logs: Ative os audit logs e mande pra S3 ou Datadog. Sem logs off-site você não tem evidência, num incidente, de quem rotacionou a service role key ou removeu uma política.
  • Branch DBs para PRs: Use branching em vez de copiar dados de produção para ambientes de preview. Uma URL de preview vazada com dados reais de usuários é um incidente de privacidade.

Erros comuns em apps gerados por IA

  • Criar tabelas no Lovable/Bolt sem habilitar RLS na mesma mudança.
  • “Corrigir” tabela bloqueada com USING (true).
  • Colocar service_role em NEXT_PUBLIC_* / VITE_* / app mobile.
  • Bucket Storage public por conveniência.
  • Políticas só de SELECT; writes abertos (ou o inverso).
  • Confiar em colunas role / is_admin graváveis pelo client.
  • Edge Functions com --no-verify-jwt copiado de tutorial.
  • Segredo JWT compartilhado entre staging e produção.
  • Tabelas órfãs de iterações de prompt sem política.

Multi-tenant e políticas por organização

A maioria dos SaaS de produção passa de “cada linha tem user_id” para workspaces: orgs, org_members e tabelas com org_id. Geradores de IA quase nunca acertam isso de primeira. Ou deixam tudo só com auth.uid() = user_id (quebra o time) ou confiam no org_id vindo do client (quebra o isolamento).

Padrão viável:

create or replace function is_org_member(check_org uuid)
returns boolean
language sql
stable
as $$
  select exists (
    select 1 from org_members
    where org_id = check_org
      and user_id = auth.uid()
  );
$$;

create policy "membros leem faturas"
  on invoices for select
  using (is_org_member(org_id));

Regras duras:

  • Nunca aceite org_id do client sem provar membership na política ou no servidor.
  • Elevação de papel (role = admin) não pode ser gravável pelo client.
  • Teste com três contas: dono da org A, membro da A, membro da B.
  • Índices em org_id evitam que política lenta vire desculpa para desligar RLS.

Claims JWT (app_metadata) podem acelerar políticas, mas envelhecem quando o membership muda. Prefira join em org_members até ter refresh confiável de claims.

Views, RPC e bypass silencioso

Views no Postgres são armadilha clássica de RLS. Uma view criada por dono privilegiado pode expor linhas da tabela base se o contexto de execução não respeitar o caller. Prefira views com security_invoker quando quiser que o RLS do caller valha.

Para cada view em public: quem é o owner, quais colunas expõe, o papel anon consegue SELECT? O mesmo rigor vale para foreign tables e views materializadas expostas no PostgREST.

Auth: identidade fraca anula política boa

Configuração Default seguro Por quê
Confirmação de e-mail Ligada em produção Reduz contas descartáveis
Troca de e-mail segura Ligada Evita sequestro por troca de e-mail
Senha vazada / força Ligada Stuffing é barato para o atacante
Expiração do JWT Access curto Limita token roubado
Redirect URLs Só origens reais Redirect aberto → roubo de token
MFA para admin Obrigatória Suaviza roubo de sessão

Provedores OAuth com localhost na allowlist de produção são herança de tutorial. OTP por SMS sem rate limit vira arma de custo. Desligue providers que você não usa.

Resposta a incidente com dump via anon key

Se RLS esteve off em tabela com PII:

  1. Conter — ligue RLS já; políticas deny-by-default; rotacione service_role se vazou no client.
  2. Escopo — logs de API com volume de select, IPs estranhos, downloads de Storage.
  3. Rotacionar — sessões, secrets de OAuth se no mesmo incidente, chaves de terceiros no bundle.
  4. Notificar — LGPD (ANPD) e contratos: documente o que era acessível, não só o que você “acha” que foi lido.
  5. Prevenir — testes de RLS no CI + Supabase RLS Checker no deploy.

Vazamento de service_role = compromisso total do banco até prova em contrário.

Como testar políticas de verdade

SQL / dashboard. Dois usuários. A insere. B tenta ler/atualizar/apagar. Esperado: vazio ou erro.

pgTAP no CI. Cada migration nova que cria tabela sem política quebra o pipeline.

HTTP ao vivo (o que o atacante faz):

curl -s "$URL/rest/v1/invoices?select=*&limit=5" \
  -H "apikey: $ANON" -H "Authorization: Bearer $ANON"

Repita com JWT do usuário B filtrando ids do A. Automatize em staging e produção (probes majoritariamente leitura).

Observabilidade e FORCE RLS

Exporte logs de Auth e API para retenção longa. Alerte em:

  • Pico de 401/403 de um IP (probe)
  • Volume anômalo de linhas retornadas em tabelas sensíveis
  • Deploys de Edge Function sem review

Owners de tabela e superusers podem contornar RLS sem FORCE ROW LEVEL SECURITY. Em apps multi-tenant, FORCE nas tabelas sensíveis evita bypass silencioso em sessões privilegiadas de migração mal usadas em runtime.

Como verificar antes do launch

-- 1. Nenhuma tabela public sem RLS
select tablename from pg_tables
where schemaname = 'public' and rowsecurity = false;

-- 2. Políticas existentes
select tablename, policyname, cmd, qual
from pg_policies where schemaname = 'public';
# Anon não deve ver linhas privadas
curl -s "$URL/rest/v1/profiles?select=*&limit=1" \
  -H "apikey: $ANON" -H "Authorization: Bearer $ANON"

Depois repita com dois JWTs de usuários reais e confirme que leitura cruzada falha. Checklist:

  1. rowsecurity = true em toda tabela public (FORCE onde fizer sentido).
  2. Políticas por comando com auth.uid() (ou claims de org reais).
  3. Sem USING (true) salvo tabela intencionalmente pública.
  4. service_role só no servidor; grepped do bundle; rotacionada se vazou.
  5. Storage com políticas; buckets sensíveis privados.
  6. Auth: confirmação de e-mail, proteção contra senhas vazadas, redirects apertados.
  7. Edge Functions com JWT; webhooks com assinatura.
  8. Realtime filtrado + RLS ok.
  9. RPCs SECURITY DEFINER auditadas.
  10. Views e RPCs no mesmo review de autorização.
  11. Probes de dois usuários + anon no CI ou pré-release.
  12. Scan ao vivo: VibeEval, RLS Checker, Token Leak Checker.

Grants, PostgREST e o mistério “RLS ligado e ainda aberto”

RLS não é o único portão. O Postgres ainda aplica GRANT. Uma tabela pode ter RLS e políticas boas e mesmo assim surpreender se:

  • Papéis anon / authenticated tiverem grants inesperados.
  • Uma subquery da política ler tabela auxiliar legível por todos, vazando existência de dados.
  • Tudo estiver em public incluindo tabelas de lixo de staging expostas na API.

Ao depurar “por que o anon lê isso”, siga a ordem: RLS ligado? Políticas existem? A expressão é falsa para anon? GRANT na tabela? View? service_role acidental?

Paridade dev × produção

Usar service_role no SQL local “porque funciona” treina o hábito errado. Exija caminhos de app com JWT de usuário, um target de CI que falhe com tabela aberta, e seeds com dois usuários provando isolamento. Testar RLS só em produção é como descobrir o buraco depois do vazamento.

O veredito

O Supabase é seguro como plataforma, com a segurança testada do PostgreSQL. O fator crítico é a configuração correta de RLS. Habilite RLS em cada tabela, escreva e teste as políticas minuciosamente e nunca exponha a service_role key no código do client. Com configuração correta, o Supabase oferece excelente segurança.

Três checagens antes de cada launch: (1) select * from pg_tables where rowsecurity = false and schemaname = 'public' — lista vazia? Bom. (2) Faça grep no bundle do frontend procurando service_role e qualquer key que não seja a anon key. (3) Tente, como segundo usuário de teste, ler dados do primeiro. Se algo passa, sua política está errada.

Se Edge Functions não reintroduzirem proxies com poderes de deus, o Supabase é base excelente para SaaS — inclusive frontends gerados por IA que falam com o banco direto.

LGPD e tabelas abertas via anon key

Quando RLS está desligado em tabela com dados pessoais (nome, e-mail, CPF, endereço, histórico de compras), o risco não é só “bug técnico” — é acesso indevido a dado pessoal sob a LGPD. Pontos práticos para times brasileiros:

  1. Base legal e minimização não salvam política USING (true) em produção. Se qualquer pessoa na internet consegue select *, o tratamento saiu do controle.
  2. Registro de incidentes: documente janela de exposição, quais colunas/tabelas eram legíveis com a anon key, e se havia logs de API com volume anômalo.
  3. ANPD / notificação: avalie com jurídico se a acessibilidade generalizada exige comunicação a titulares e à autoridade — “não vimos download nos logs” raramente basta quando a API era pública.
  4. Contratos com clientes B2B: DPA costuma exigir medidas técnicas adequadas; RLS ausente é finding de auditoria seu, não do Supabase SOC 2.
  5. Prova de correção: screenshots/SQL de rowsecurity = true, políticas com auth.uid(), e resultado de probe anon vazio + dual-user.

Guarde o relatório do Supabase RLS Checker e do scan VibeEval junto ao ticket de incidente.

Políticas por papel (anon vs authenticated)

Erros comuns em apps gerados:

-- Acidentalmente público
create policy "leitura" on profiles for select to anon using (true);

-- Só autenticados, mas qualquer um vê todos
create policy "leitura" on profiles for select to authenticated using (true);

O segundo ainda é vazamento total entre usuários. Escopo correto:

create policy "ler_proprio"
  on profiles for select
  to authenticated
  using (auth.uid() = id);

Tabelas intencionalmente públicas (catálogo) devem listar colunas não sensíveis via view, não expor profiles inteiro.

WITH CHECK em inserts de onboarding

Fluxo típico Lovable: trigger ou client cria linha em profiles no signup. Política de insert sem WITH CHECK (auth.uid() = id) permite forjar perfil de outro UUID. Sempre:

create policy "criar_proprio_perfil"
  on profiles for insert
  to authenticated
  with check (auth.uid() = id);

E proíba colunas de privilégio no payload (role, is_admin, plan).

Recursos relacionados

Como proteger o Supabase

Guia passo a passo de segurança com padrões de RLS, validação de JWT e hardening de Storage.

Checklist de segurança do Supabase

Checklist de segurança interativo — de “RLS em cada tabela” até “audit logs ativados”.

Guia de RLS

Aprofundamento em políticas que realmente checam o caller.

Supabase RLS Checker

Scan automatizado que verifica que cada tabela do seu projeto tem RLS ativo e pelo menos uma política.

Token Leak Checker

Acha service role keys, anon keys e secrets JWT vazados no seu bundle de frontend e nos seus repos.

Riscos de segurança de vibe coding

Visão geral dos padrões de falha que código gerado por IA introduz tipicamente em projetos Supabase.

Proteção de senha no Lovable

Auth forte + RLS: as duas camadas juntas.

Rotina semanal para times em Lovable + Supabase

  1. Listar tabelas sem RLS.
  2. Rodar scan na URL de produção.
  3. Revisar Functions novas sem verificação de JWT.
  4. Confirmar que previews não usam service_role de produção.
  5. Rotacionar qualquer segredo que tenha aparecido em log ou chat.

Exemplo de política multi-tenant

create policy "docs_por_org"
  on documents for select
  using (
    org_id in (
      select org_id from memberships where user_id = auth.uid()
    )
  );

Teste com usuário fora da org — zero linhas.

Resposta a incidente (resumo)

Corrigir políticas → rotacionar service_role se exposta → auditar logs → comunicar usuários se dados pessoais vazaram → adicionar testes para não regredir.

Checklist de migração SQL segura

Toda migration que cria tabela deve, no mesmo arquivo:

  1. create table ...
  2. alter table ... enable row level security (+ force se multi-tenant)
  3. Políticas por comando (select/insert/update/delete)
  4. Grants mínimos a anon/authenticated se necessário
  5. Teste: dual-user ou pgTAP

Geradores de IA costumam entregar só o passo 1. Rejeite PRs de schema incompletos.

Separação preview × produção no Supabase

  • Projeto Supabase separado para preview (ou branch DB), nunca a service_role de produção em Vercel Preview.
  • Redirect URLs de Auth: incluir só domínios reais; remover localhost e tunnels de produção.
  • Stripe test keys no preview; live só em production context.
  • Seeds com dados sintéticos — copiar dump de produção para preview é incidente de privacidade se a URL vazar.

pgTAP mínimo no CI

-- exemplo conceitual
select plan(2);
select is_empty(
  $$ select * from invoices $$,
  'anon não lista faturas'
);
select finish();

Rode contra um DB de CI com JWT de teste. Sem isso, RLS é documentação, não controle.

OpenAPI do PostgREST como mapa de ataque

Com a anon key, GET /rest/v1/ (ou o endpoint de schema) lista tabelas expostas. Atacantes não precisam adivinhar nomes — o próprio projeto documenta a superfície. Por isso “esconder” o nome da tabela no frontend não é controle. RLS e grants são.

Depois de cada migration, abra o schema como anon e confirme que tabelas internas (admin_*, billing_raw) não aparecem ou negam tudo.

Lovable, Bolt e Cursor em cima do Supabase

O mesmo Postgres recebe frontends diferentes:

Gerador Risco modal no Supabase
Lovable Tabelas novas sem RLS
Bolt service_role / secrets no bundle Vite
Cursor RLS ok às vezes, mas RPC/API custom sem ownership

Independentemente do gerador, o checklist SQL deste guia vale. Veja o experimento mesmo spec e Firebase para o modelo de regras irmão.

Rotação de chaves (runbook curto)

  1. Dashboard Supabase → Settings → API → reset service_role (e JWT secret se comprometido).
  2. Atualize só secrets de servidor (Edge Functions, CI).
  3. Force logout / revogue sessões se tokens de usuário vazaram em massa.
  4. Grep histórico de git e bundles antigos em CDN (cache).
  5. Re-deploy frontends que embutiram a chave errada.
  6. Documente horário UTC e quem aprovou.

Anon key rotacionada quebra todos os clients até redeploy — planeje janela; service_role rotacionada é urgente e localizada no servidor.

Políticas de Storage com pasta por usuário

Padrão recomendado de path: {user_id}/arquivo.ext e política:

create policy "upload_proprio"
  on storage.objects for insert to authenticated
  with check (
    bucket_id = 'docs'
    and auth.uid()::text = (storage.foldername(name))[1]
  );

create policy "ler_proprio"
  on storage.objects for select to authenticated
  using (
    bucket_id = 'docs'
    and auth.uid()::text = (storage.foldername(name))[1]
  );

Buckets public só para assets realmente públicos (logo, marketing). Nunca misture contratos e avatares no mesmo bucket público “só por enquanto”.

Checklist rápido em português (imprimir)

  • Nenhuma tabela public com rowsecurity = false
  • Nenhuma política USING (true) em dado sensível
  • INSERT/UPDATE com WITH CHECK adequado
  • service_role só no servidor; bundle limpo
  • Storage privado + políticas de pasta
  • Auth: e-mail confirmado, redirects fechados
  • Edge Functions com JWT; webhooks com assinatura
  • Teste anon + usuário A + usuário B
  • Scan RLS Checker na URL de produção
  • Plano de incidente LGPD documentado

Escaneie seu app Supabase

Deixe o VibeEval checar sua aplicação Supabase em busca de má configuração de RLS e vulnerabilidades — tabelas sem políticas, keys vazadas, buckets de Storage públicos, BOLA em Edge Functions. Resultados em menos de 60 segundos, com arquivo e número de linha pra corrigir.

Common questions

O Supabase é seguro como plataforma?
Sim. O Supabase roda em PostgreSQL gerenciado, é SOC 2 Type II compliant, força TLS e aplica patches na própria infraestrutura. As vulnerabilidades que encontramos em apps Supabase quase nunca estão na plataforma — estão em políticas RLS ausentes, service role keys vazadas e buckets de Storage públicos que o desenvolvedor configurou por conta própria.
Qual é a diferença entre a anon key e a service role key?
A anon key é pública por design — ela vai pro navegador e só é tão poderosa quanto suas políticas RLS permitem. A service role key ignora RLS por completo e dá acesso total a qualquer tabela. A service role key nunca pode acabar no bundle do client, em uma env var de preview do Vercel sem escopo, ou em um repo público.
Como testo se minhas políticas RLS realmente funcionam?
Autentique-se com a anon key como dois usuários de teste diferentes e tente ler os dados de um pelo outro via `select`, `update` e `delete`. Se uma request passa quando não deveria, você tem uma brecha. O Supabase oferece `pgTAP` para testes orientados a políticas no CI.
Preciso de RLS também para os buckets de Storage?
Sim. O Supabase Storage replica o mesmo modelo — cada bucket é privado por padrão, mas assim que você seta `public: true` ou escreve uma política que retorna `true`, os arquivos ficam legíveis anonimamente. Escreva uma política por bucket sobre `storage.objects` que valide `auth.uid()` contra o campo de proprietário.
A anon key sozinha é uma vulnerabilidade?
Não. Enviar a anon key no client é o modelo documentado. A falha é RLS ausente/incorreto ou vazamento da service_role. Trate a anon key como identificador público da API e coloque o controle real nas políticas.
Com que frequência devo revalidar o RLS?
Sempre que criar tabela, view, RPC ou bucket — e depois de qualquer feature gerada por IA. Tabelas novas nascem com RLS desligado. Rode o Supabase RLS Checker na URL de produção antes de cada launch.
Edge Functions podem vazar a service_role?
Sim, se logarem env, devolverem stack com detalhes, ou forem proxies sem checar o JWT do usuário. Trate toda Function com service_role como serviço privilegiado.
Como o Supabase se compara ao Firebase em segurança?
Ambos expõem dados ao client com regras declarativas. Supabase usa RLS em SQL; Firebase usa Security Rules. Os dois falham do mesmo jeito: regra que só checa 'está logado' em vez de 'é dono da linha'.

Teste o rls com a anon key

Exercitamos sua anon key pública e mostramos cada tabela/linha que ela ainda consegue ler. Teste de 14 dias, sem cartão.

14-day free trial · No credit card · Cancel anytime

ESCANEAR MEU APP SUPABASE