AI-coded apps

    Segurança React Native: Vazamento do sb_publishable na Supabase

    A chave sb_publishable no bundle de um app React Native publicado, com o Row Level Security protegendo os dados na Supabase.

    Ver a chave sb_publishable no seu app React Native publicado não é um vazamento: essa chave foi feita para ser pública, exatamente como a antiga chave anon. Ela tem privilégios baixos e é segura no cliente desde que o Row Level Security esteja ativo. O perigo real não é a sb_publishable aparecer no app, mas sim faltar RLS, o que deixa qualquer pessoa consultar suas tabelas com essa chave pública. A chave que nunca pode vazar é a sb_secret, que ignora o RLS e dá acesso total ao banco.

    Resposta rápida

    A sb_publishable é pública por design; a sb_secret nunca é. Segundo a documentação das novas chaves da Supabase, a chave sb_publishable tem os mesmos privilégios baixos da antiga anon e é segura no cliente quando o Row Level Security está ativo. Já a sb_secret usa a função service_role com BYPASSRLS, ignora todas as políticas e só deve ficar no servidor. Portanto, a sb_publishable no seu app React Native é esperada, não um vazamento. Verifique se o RLS está ativo em todas as tabelas, e trate qualquer exposição da sb_secret como uma emergência, rotacionando a chave.

    sb_publishable vs sb_secret: qual importa

    A primeira coisa é saber qual chave você está vendo, porque a resposta muda por completo. A Supabase agora oferece duas chaves: a sb_publishable, de privilégios baixos e feita para ir no cliente, e a sb_secret, uma chave de acesso total que só deve ficar no servidor. Há também o segredo JWT no modelo legado. A tabela abaixo separa as três.

    ChaveSegura no cliente?Se for exposta
    sb_publishable (antiga anon)Sim, por designSegura só se o RLS estiver ativo
    sb_secret (antiga service_role)Não, nuncaAcesso total, ignora o RLS, rotacione já
    Segredo JWT (legado)Não, nuncaPermite forjar tokens

    Se é a sb_publishable, não se preocupe com a chave em si; a pergunta passa a ser se o RLS protege seus dados. Se é a sb_secret ou o segredo JWT, é uma emergência, porque dão um controle que nenhuma política de RLS consegue conter.

    Por que a sb_publishable no app não é um vazamento

    A sb_publishable é publicável, e o nome já diz tudo: ela foi feita para ser publicada, ou seja, para viajar no bundle do seu app React Native e ser vista. Assim como a antiga chave anon, ela tem privilégios baixos e serve só para o cliente conversar com a Supabase. Encontrá-la no seu app publicado é o comportamento esperado, não uma falha.

    O que a torna segura é o Row Level Security. Com o RLS ativo e políticas corretas, essa chave pública só acessa os dados que você permite, então o fato de ela ser visível não é um problema. Confundir "a chave está no app" com "a chave vazou" leva a um pânico desnecessário: a sb_publishable no cliente é por design.

    O perigo real: a falta de RLS

    O risco real não é a chave, e sim o que está por trás dela. A Supabase cria as tabelas com o RLS desativado por padrão, então, se o seu projeto nunca ativou o RLS, a chave sb_publishable pública permite que qualquer pessoa consulte e baixe suas tabelas inteiras, sem fazer login. A chave não vazou; ela é pública, mas nada protege os dados.

    Foi exatamente isso o que aconteceu no CVE-2025-48757, em que um pesquisador encontrou 170 projetos Lovable cujas tabelas eram legíveis por requisições não autenticadas usando só a chave pública, por falta de RLS. A lição não é esconder a chave publicável, o que é impossível, e sim ativar o RLS em todas as tabelas com políticas que limitem cada usuário aos seus próprios dados.

    A chave que nunca pode vazar: sb_secret

    A chave que você precisa proteger é a sb_secret, ou a antiga service_role. Ela usa a função service_role do Postgres com o atributo BYPASSRLS, ou seja, ignora todas as suas políticas de RLS e tem acesso total de leitura e escrita ao banco. Por isso, nunca deve aparecer no cliente, no repositório ou no bundle do app.

    Se essa chave for exposta, é uma brecha completa, porque quem a tiver acessa tudo, ignorando o RLS. Ela deve viver apenas em componentes controlados por você no servidor, como uma Edge Function ou seu próprio backend, onde você mesmo faz a autorização antes de usá-la. Uma sb_secret no app React Native é um erro de arquitetura, não só uma chave a rotacionar.

    As novas chaves substituem anon e service_role

    A Supabase está migrando o modelo de chaves. As chaves legadas anon e service_role serão descontinuadas até o fim de 2026, e você deve passar a usar a sb_publishable no lugar da anon e a sb_secret no lugar da service_role. Os dois modelos funcionam ao mesmo tempo durante a migração, então você pode trocar os clientes um a um e desativar as chaves legadas só quando nada mais depender delas.

    Uma vantagem prática das novas chaves é a rotação mais simples: você pode revogar uma chave secreta específica e emitir outra, sem invalidar tudo de uma vez como acontecia ao girar o segredo JWT legado. A Supabase também revoga automaticamente as chaves secretas que detecta em repositórios públicos do GitHub, o que ajuda, mas não substitui manter a sb_secret longe do cliente.

    O que fazer se a sb_secret vazou

    Se a sb_secret, e não a publicável, foi exposta, aja em ordem. A prioridade é revogar e gerar uma nova chave, porque é a única ação que invalida a cópia que um atacante já pode ter. A tabela abaixo dá uma resposta clara.

    PassoAçãoPrioridade
    1Revogue e gere uma nova sb_secretImediata
    2Ative o RLS em todas as tabelasAlta
    3Mova a sb_secret para o backendAlta
    4Remova a chave do código e do histórico GitAlta
    5Consulte suas tabelas com a sb_publishableVerifica o RLS
    6Revise os logs do banco de dadosDetecta abuso

    Rotacione primeiro, corrija depois. Remova a chave do código e, principalmente, do histórico do Git, já que apagá-la em um commit posterior não a remove dos anteriores. Trate qualquer sb_secret exposta como comprometida, mesmo que você rotacione rápido, e revise os logs do banco em busca de acessos anormais.

    Como verificar seu app React Native

    A verificação mais importante é simples: consulte suas tabelas com a chave sb_publishable pública, sem sessão iniciada, e confirme que ela não retorna dados que não deveria. É exatamente o teste que um atacante ou um bot faz, então passar por ele é a prova direta de que o RLS está protegendo seus dados.

    Além disso, confirme que a sb_secret não está em lugar nenhum do cliente. Procure por chaves no bundle JavaScript, nos arquivos de configuração e no repositório. Em um app React Native, lembre que as variáveis de ambiente são embutidas em texto claro no bundle na hora do build, então um arquivo .env não esconde uma chave secreta no app publicado.

    Onde os bots entram

    Isso não é um ataque manual. Bots automáticos rastreiam repositórios públicos, bundles e binários em busca de URLs e chaves da Supabase. Ao encontrar uma sb_secret, testam contra a API e ganham acesso total em segundos. Ao encontrar uma sb_publishable, consultam suas tabelas para ver se o RLS está ativo.

    A velocidade é o problema. Como a varredura é contínua, uma chave secreta enviada a um repositório público pode ser detectada e testada em minutos. Por isso, a sb_secret precisa ficar no servidor, e o RLS precisa estar ativo para que a sb_publishable pública, encontrada por um bot, não sirva de nada.

    Antes de publicar, escaneie o build

    Como as ferramentas de IA e os fluxos rápidos facilitam esses descuidos, revisar o build antes de publicar detecta uma sb_secret embutida enquanto ainda é barato corrigir. Uma chave secreta no frontend é justamente o padrão que os atacantes automáticos procuram.

    Um scanner como o PTKD.com analisa seu .apk ou .ipa e devolve resultados ordenados por gravidade e mapeados ao OWASP MASVS, incluindo segredos embutidos e configurações de rede inseguras, para que uma chave exposta não chegue aos usuários. Sendo claro sobre o limite: um scanner de build verifica o app que você publica, não o painel da Supabase, então não substitui ativar o RLS nem rotacionar uma chave. Ele detecta a exposição no cliente; o backend você protege com o RLS.

    O que lembrar

    • A sb_publishable é pública por design; encontrá-la no app React Native não é um vazamento.
    • O perigo real é a falta de RLS, que deixa a chave pública baixar suas tabelas, como no CVE-2025-48757.
    • A sb_secret nunca pode vazar: ela ignora o RLS e dá acesso total, e só deve ficar no servidor.
    • As novas chaves sb_publishable e sb_secret substituem anon e service_role até o fim de 2026.
    • Antes de publicar, escaneie o build com o PTKD.com para que uma sb_secret não chegue aos usuários.
    • #supabase
    • #react native
    • #sb_publishable
    • #row level security
    • #segurança mobile

    Frequently asked questions

    A chave sb_publishable no meu app é um problema?
    Não por si só. A sb_publishable é a chave publicável, feita para ir no cliente, com privilégios baixos, exatamente como a antiga anon. Encontrá-la no seu app React Native publicado é esperado. Ela só é perigosa se o Row Level Security estiver desativado, porque aí qualquer pessoa consegue consultar suas tabelas com ela.
    Qual a diferença entre sb_publishable e sb_secret?
    A sb_publishable é pública, de privilégios baixos, e segura no cliente quando o RLS está ativo. A sb_secret usa a função service_role com BYPASSRLS, ignora todas as políticas e tem acesso total, então só deve ficar no servidor e nunca no cliente. Uma é para o app; a outra, para o backend.
    As novas chaves substituem anon e service_role?
    Sim. As chaves legadas anon e service_role serão descontinuadas até o fim de 2026, substituídas pela sb_publishable e pela sb_secret. Os dois modelos funcionam ao mesmo tempo durante a migração, então você pode trocar os clientes aos poucos e desativar as legadas quando nada mais depender delas.
    O que faço se a chave sb_secret vazou?
    É uma emergência. Revogue e gere uma nova sb_secret de imediato, porque é a única ação que invalida a cópia exposta. Depois, ative o RLS em todas as tabelas, mova a chave para o servidor, remova-a do código e do histórico do Git, e revise os logs do banco em busca de acessos anormais.
    O RLS me protege se a sb_publishable é pública?
    Sim, é exatamente essa a função dele. Com o Row Level Security ativo e políticas que combinam com sua lógica de autenticação, a chave publicável só acessa os dados que você permite, então o fato de ser pública é seguro. O perigo não é a chave ser pública, e sim não ter RLS.
    Como verifico meu build antes de publicar?
    Consulte suas tabelas com a sb_publishable sem sessão e confirme que ela não expõe dados alheios, e verifique que a sb_secret não está no cliente. Um scanner como o PTKD.com (https://ptkd.com) analisa seu build em busca de segredos embutidos e configurações inseguras, alinhado ao OWASP MASVS, para o lado do cliente.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free