00:00:00Um relatório publicado este mês analisou cerca de 20.000 aplicativos independentes e descobriu que um em cada nove
00:00:04estava expondo credenciais do Supabase no código do front-end.
00:00:08Isso não está em um log de servidor ou em um repositório privado.
00:00:11Isso está simplesmente no JavaScript que todo visitante baixa.
00:00:14E a questão é: esses apps não foram hackeados, eles apenas enviaram o segredo por acidente.
00:00:18Para ficar claro, algumas chaves devem ser públicas.
00:00:21O problema é o pipeline, porque o mesmo erro pode enviar uma chave que nunca deveria estar
00:00:25no navegador, para começo de conversa.
00:00:27Temos vídeos novos saindo o tempo todo.
00:00:28Não se esqueça de se inscrever.
00:00:35Aqui está a verdade simples que confunde algumas pessoas.
00:00:38Todos nós sabemos, mas é fácil esquecer quando se está trabalhando rápido.
00:00:41Quando você marca uma variável de ambiente como pública, sua ferramenta de build a trata como se ela devesse estar
00:00:46no navegador e ela é adicionada ao pacote (bundle) do cliente.
00:00:50O Next.js faz isso com "NEXT_PUBLIC", o Vite faz isso com "VITE_" e o SvelteKit usa
00:00:56"public".
00:00:57A palavra "Next" não é um selo de segurança; é, literalmente, a etiqueta de envio.
00:01:01Agora que sabemos disso, vamos à parte do Supabase.
00:01:04Algumas chaves devem ser públicas, como a "anon" ou a chave publicável, e outras são privadas, como
00:01:10a "service_role" ou chaves mestras.
00:01:12Se uma chave privada vai parar no navegador, bem, acho que você pode imaginar o que acontece.
00:01:17A Segurança em Nível de Linha (RLS) não vai te salvar nesse caso.
00:01:20O Supabase tem documentações claras dizendo que as chaves de serviço podem ignorar a RLS.
00:01:24Então, se essa chave estiver no seu front-end, todo o seu trabalho com políticas não importa mais.
00:01:29Deixe-me mostrar exatamente como isso aconteceu usando meu próprio sandbox.
00:01:33Primeiro, criei um app CRUD simples usando Next.js e conectei meu Supabase nele.
00:01:38Aqui está meu arquivo .env, e aqui está o erro.
00:01:41Coloquei uma chave em uma variável com o prefixo "PUBLIC".
00:01:45Esta chave é publicável, então já se espera que ela seja visível.
00:01:48O problema real é que o exato mesmo caminho "NEXT_PUBLIC" pode acidentalmente enviar uma chave privada também.
00:01:53Executei o "npm run build" para gerar a build e iniciei meu app.
00:01:59Aqui estou eu no Chrome.
00:02:00Vou adicionar rapidamente algumas informações ao nosso banco de dados, nosso app CRUD.
00:02:05Certo, agora posso abrir o pacote JavaScript compilado e vou procurar por ela.
00:02:10Lá está ela.
00:02:12A URL e a chave estão literalmente dentro do arquivo que seus usuários acabaram de baixar em seus
00:02:18navegadores.
00:02:19E note o que não aconteceu.
00:02:21Ninguém invadiu nada.
00:02:22Eu apenas encontrei isso, certo?
00:02:24Ninguém explorou uma vulnerabilidade.
00:02:25É apenas a leitura do que o app já enviou para a internet pública.
00:02:29Se você consegue ver, qualquer um pode ver.
00:02:32Abra as ferramentas de desenvolvedor, olhe os arquivos JavaScript e procure por ela.
00:02:35É só isso que você precisa fazer.
00:02:36Então, se o seu plano é "ninguém vai olhar", bem, a internet está cheia de pessoas e bots
00:02:41cujo trabalho é literalmente procurar por esse tipo de coisa.
00:02:44Então aqui está a solução que realmente funciona.
00:02:47O navegador deve chamar apenas a sua API.
00:02:50Sua API roda no lado do servidor.
00:02:52É lá que as chaves privadas devem ficar.
00:02:54Mova a operação privada para uma rota de API ou uma função de servidor.
00:02:58O cliente chama o seu endpoint, o seu endpoint chama o Supabase, então gere a build e verifique
00:03:03o pacote novamente.
00:03:04Se a chave sumiu do pacote, você realmente resolveu o problema, mas não pare por aí
00:03:09porque há outras coisas que você pode fazer.
00:03:11Certifique-se de que a Segurança em Nível de Linha (RLS) esteja ativada para as tabelas voltadas ao usuário
00:03:16e que suas políticas façam o que você espera.
00:03:18Dedique algum tempo aos testes também.
00:03:19Acho que isso costuma ser negligenciado.
00:03:21Agora, a parte para evitar que o erro volte: a maioria das pessoas corrige isso uma vez e depois o reintroduz
00:03:26mais tarde, na pressa.
00:03:28Portanto, adicione algumas proteções; comece com uma varredura de segredos no CI para que as builds falhem
00:03:34se uma chave aparecer onde não deveria.
00:03:36Depois, crie uma regra de PR para que qualquer coisa com "NEXT_PUBLIC" ou "VITE_" seja tratada como pública por padrão,
00:03:41porque ela é.
00:03:42Por fim, adicione a rotação de chaves.
00:03:43Se você tiver o menor indício de que as chaves foram expostas, apenas troque-as.
00:03:47Isso é melhor do que esperar para ver o que acontece nos dias seguintes.
00:03:50Aqui está o que você pode tentar agora mesmo.
00:03:52Gere a build do seu app do jeito que você o publica.
00:03:55Procure na saída por "supabase", "JWT", "service_role" e qualquer coisa que pareça um token.
00:04:01Se encontrar algo privado, considere comprometido, pois você o encontrou.
00:04:05Troque a chave e mude sua lógica para o lado do servidor.
00:04:08Se você for se lembrar de apenas uma frase deste vídeo, que seja esta:
00:04:11Se está no pacote (bundle), é público.
00:04:13A gente se vê em outro vídeo.