[{"data":1,"prerenderedAt":922},["ShallowReactive",2],{"blog-pt-open-api-endpoint-exposed":3,"blog-index-pt":572},{"id":4,"title":5,"body":6,"category":530,"cover":531,"coverAlt":532,"description":533,"draft":534,"extension":535,"faq":536,"image":551,"keywords":552,"meta":560,"navigation":561,"ogTitle":562,"path":563,"published":564,"seo":565,"stem":566,"tldr":567,"updated":564,"__hash__":571},"blog_pt\u002Fblog\u002Fopen-api-endpoint-exposed.md","Um endpoint de API aberto é um problema? Leia o JSON",{"type":7,"value":8,"toc":516},"minimark",[9,13,21,26,29,32,35,41,44,48,51,54,118,121,125,128,138,144,150,168,179,188,192,195,202,274,282,294,298,301,304,307,312,322,326,329,332,356,359,363,366,369,379,382,388,399,421,427,430,436,446,451,454,460,463,472,476,496,503],[10,11,12],"p",{},"Seu scan voltou com uma linha que não soa como um veredito: alguns endpoints de\nAPI respondem sem login. Talvez alguém tenha falado de forma mais direta e dito\nque você tem um endpoint de API aberto. Embaixo há um endereço, e há uma boa\nchance de você não reconhecê-lo.",[10,14,15,16,20],{},"Aqui está a parte que guia após guia conta errado: ",[17,18,19],"strong",{},"o conselho de sempre para\nesse achado é colocar um login na frente do seu endpoint, e na maioria dos\naplicativos que escaneamos não existe nenhum endpoint seu na frente do qual\ncolocar um."," Sete em cada dez dos que encontramos pertencem à plataforma em que\no aplicativo foi publicado. Ler esse achado começa, então, por descobrir de quem\né o endereço, e a resposta costuma aparecer logo na primeira linha do que volta.",[22,23,25],"h2",{"id":24},"o-que-um-endpoint-de-api-aberto-significa-no-seu-relatório","O que um endpoint de API aberto significa no seu relatório",[10,27,28],{},"Significa que um caminho escrito no código do seu aplicativo respondeu a uma\nrequisição que não levava login, e que o que voltou foi JSON.",[10,30,31],{},"Três passos, e nenhum deles é esperto. Carregamos seu aplicativo num navegador\ndo jeito que um visitante faz, e lemos o código que esse navegador baixou. Ali\ndentro estão os endereços que o seu aplicativo chama quando precisa de dados.\nDepois pedimos dados a cada um, sem conta, sem cookie e sem chave. Se um\nendereço responde com JSON que não é uma mensagem de erro, ele vai para o\nrelatório.",[10,33,34],{},"Isso registra o que aconteceu. Não é um julgamento sobre os dados, porque nada\nque esteja fora do seu aplicativo consegue dizer se uma lista de coisas é uma\nlista de coisas públicas. Por isso o achado é redigido assim: estes endpoints\ndevolveram dados sem nenhuma autenticação, isso pode ser intencional para dados\npúblicos, verifique se nenhum deles expõe informações privadas.",[36,37],"diagram",{"alt":38,"caption":39,"src":40},"Código baixado de um aplicativo, com quatro endereços destacados dele. Cada endereço recebe um pedido de dados de uma requisição que carrega uma chave riscada, ou seja, sem login. Três voltam vazios ou recusados e um volta com um bloco de dados.","Os endereços saem do seu próprio código, e cada um é consultado sem nada anexado. O que responder é o que cai no relatório.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fwhat-the-check-does-1600x620.png",[10,42,43],{},"Então o relatório entrega a você uma lista de endereços para abrir. Cada um\ndeles precisa ser aberto num navegador desconectado, e são as primeiras linhas\nda resposta que resolvem a questão.",[22,45,47],{"id":46},"todo-endpoint-de-api-aberto-é-um-problema-de-segurança","Todo endpoint de API aberto é um problema de segurança?",[10,49,50],{},"Não. Existem três tipos, e só o terceiro é um problema.",[10,52,53],{},"Pense num prédio de apartamentos. Algumas coisas ali são para qualquer um que\nentre: o horário na porta, as saídas de emergência, o aviso de que o elevador\npassa por manutenção na terça. Em algum outro canto do mesmo prédio existe um\narquivo com os dados dos moradores. Do corredor, um quadro de avisos e um\narquivo destrancado são dois móveis que dá para abrir, e o único jeito de\ndistinguir os dois é ler o que está no papel.",[55,56,57,73],"table",{},[58,59,60],"thead",{},[61,62,63,67,70],"tr",{},[64,65,66],"th",{},"O que respondeu",[64,68,69],{},"De quem é o endereço",[64,71,72],{},"Onde você está",[74,75,76,92,104],"tbody",{},[61,77,78,82,85],{},[79,80,81],"td",{},"Configurações da plataforma: avisos de cookie, interruptores",[79,83,84],{},"Do seu builder, em todo aplicativo que ela publica",[79,86,87],{},[88,89,91],"key-verdict",{"type":90},"safe","Nada a fazer",[61,93,94,97,100],{},[79,95,96],{},"Seus próprios dados públicos: uma tabela de preços, um artigo",[79,98,99],{},"Seu, e feito para ser lido",[79,101,102],{},[88,103,91],{"type":90},[61,105,106,109,112],{},[79,107,108],{},"Linhas sobre pessoas: nomes, e-mails, pedidos, mensagens",[79,110,111],{},"Seu, e alcançável por qualquer um que tenha o endereço",[79,113,114],{},[88,115,117],{"type":116},"danger","Feche hoje",[10,119,120],{},"A primeira linha é um quadro de avisos que outra pessoa parafusou na parede. A\nsegunda é um quadro que você pendurou de propósito. A terceira é o arquivo, e\nele está aberto desde que o endereço existe.",[22,122,124],{"id":123},"como-verificar-o-que-os-seus-endpoints-devolvem","Como verificar o que os seus endpoints devolvem",[10,126,127],{},"Abra cada um desconectado e leia o que chega. A leitura demora mais do que o\nachado sugere, e é o único passo que responde à pergunta.",[10,129,130,133,134,137],{},[17,131,132],{},"Ache os endereços."," Abra seu aplicativo em produção, aperte F12 para abrir as\nferramentas de desenvolvedor do navegador, clique em ",[17,135,136],{},"Rede"," e recarregue a\npágina. Passe pelas requisições que voltam como JSON. Esses são os endereços de\nonde o seu aplicativo busca dados, e a lista do relatório é um subconjunto\ndeles.",[10,139,140,143],{},[17,141,142],{},"Consulte cada um como um estranho."," Copie uma URL, abra uma janela anônima\npara estar desconectado, e cole. O que você vê é exatamente o que qualquer\npessoa na internet vê naquele endereço.",[10,145,146,149],{},[17,147,148],{},"Leia as primeiras linhas."," Três coisas podem voltar:",[151,152,153,162,165],"ul",{},[154,155,156,157,161],"li",{},"Um erro, uma recusa, ou ",[158,159,160],"code",{},"[]",". O endereço quer um login, ou não há nada ali\npara quem está desconectado. Siga em frente.",[154,163,164],{},"Configurações. Flags, interruptores, uma cor, a lista de recursos ligados, um\nnúmero de versão. Ninguém é nomeado e nada é descrito. Siga em frente.",[154,166,167],{},"Linhas. Um e-mail, o nome de uma pessoa, o valor de um pedido, o texto de uma\nmensagem, um telefone. Pare aqui, é essa.",[10,169,170,171,174,175,178],{},"Se encontrar linhas, tente mudar um número na URL antes de fechar a aba. Um\nendereço que entrega o registro de uma pessoa em ",[158,172,173],{},"id=1"," e o de outra em ",[158,176,177],{},"id=2","\nestá entregando todos, e vale saber disso antes de decidir o quanto isso é\nurgente.",[10,180,181,182,187],{},"Nosso scan gratuito faz os dois primeiros passos por você: ele lê no código do\nseu aplicativo os endereços que ele chama, consulta cada um sem login, e lista\nos que responderam com dados. Leva uns 20 segundos e não precisa de conta:\n",[183,184,186],"a",{"href":185},"\u002Fsecurity-scanner","escaneie seu aplicativo",". O terceiro passo é seu, porque\nvocê é a única pessoa que sabe se um nome nessa lista é um cliente de verdade.",[22,189,191],{"id":190},"a-maioria-dos-que-encontramos-é-da-plataforma","A maioria dos que encontramos é da plataforma",[10,193,194],{},"Na nossa varredura de agosto de 2026, 3.852 dos 30.926 aplicativos em que essa\nverificação conseguiu uma resposta tinham pelo menos um endereço respondendo sem\nlogin. Desses, 2.705 eram aplicativos Base44, e na Base44 o endereço é quase\nsempre o mesmo.",[10,196,197,198,201],{},"É o ",[158,199,200],{},"\u002Fapi\u002Fconsent\u002Fconfig",", as configurações de cookies da plataforma. Em\nsetembro reabrimos uma amostra de aplicativos Base44 apontados e o único\nendereço que respondeu foi esse. Ele devolve configurações, é idêntico de um\naplicativo para outro, e não tem dado de ninguém ali. O scanner está relatando\nisso corretamente e o dono não tem nada para corrigir.",[55,203,204,217],{},[58,205,206],{},[61,207,208,211,214],{},[64,209,210],{},"Plataforma",[64,212,213],{},"Aplicativos com o achado",[64,215,216],{},"Aplicativos em que a verificação respondeu",[74,218,219,230,241,252,263],{},[61,220,221,224,227],{},[79,222,223],{},"Base44",[79,225,226],{},"2.705",[79,228,229],{},"5.419",[61,231,232,235,238],{},[79,233,234],{},"Domínios próprios",[79,236,237],{},"82",[79,239,240],{},"955",[61,242,243,246,249],{},[79,244,245],{},"Bolt",[79,247,248],{},"4",[79,250,251],{},"1.120",[61,253,254,257,260],{},[79,255,256],{},"Lovable",[79,258,259],{},"8",[79,261,262],{},"18.518",[61,264,265,268,271],{},[79,266,267],{},"v0",[79,269,270],{},"0",[79,272,273],{},"1.786",[10,275,276,277,281],{},"Falta uma plataforma nessa tabela, de propósito. À Replit cabe um bloco grande\ndos achados restantes, e ninguém reabriu uma amostra deles como fizemos com os\nda Base44, então ainda não sabemos de quem são aqueles endereços. Publicar um\nnúmero como problema do dono antes que alguém tenha olhado é exatamente o\ncaminho pelo qual uma configuração de plataforma da Base44 vira uma estatística\nsobre donos negligentes. Todo número acima vem do\n",[183,278,280],{"href":279},"\u002Fresearch\u002Fvibe-coded-app-security-2026","nosso scan de 30.998 aplicativos vibe-coded no ar",",\nque publica cada um junto com a base sobre a qual foi medido.",[10,283,284,285,288,289,293],{},"Leia as duas pontas dessa tabela juntas, porque a diferença é a parte útil. Na\nLovable são 8 aplicativos em 18.518, e na v0 nenhum. Esses aplicativos não têm\num pequeno servidor próprio: a página fala com o Supabase direto do navegador,\nentão não existe em lugar nenhum um ",[158,286,287],{},"\u002Fapi\u002F…"," seu para essa verificação\nencontrar. O que protege os dados num aplicativo assim são as regras em cada\ntabela, e esse é outro achado com um\n",[183,290,292],{"href":291},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","jeito próprio de dar errado",".",[22,295,297],{"id":296},"quando-o-json-são-configurações-e-quando-são-pessoas","Quando o JSON são configurações e quando são pessoas",[10,299,300],{},"Uma pergunta decide: alguma coisa na resposta descreve uma pessoa?",[10,302,303],{},"Configurações descrevem o seu aplicativo. Um flag dizendo se o modo escuro está\nligado, a lista de moedas que você aceita, a versão de alguma coisa, o texto de\num banner de cookies. Publicar isso revela como o seu aplicativo está\nconfigurado, e o seu aplicativo roda à vista de todo mundo de qualquer forma.",[10,305,306],{},"Linhas descrevem seus usuários. Um nome, um e-mail, o que alguém comprou, o que\nescreveu, onde mora. Isso não é uma frase sobre configuração, é o conteúdo do\narquivo, e importa pelo quanto é banal levá-lo embora. Não há arrombamento. O\nendereço é uma linha de texto que funciona em qualquer navegador, então ele é\ncolado num grupo de mensagens, salvo nas anotações de alguém, e baixado de tempos\nem tempos por um script que ninguém está olhando.",[36,308],{"alt":309,"caption":310,"src":311},"Duas respostas de tamanho e formato idênticos. A da esquerda contém quatro interruptores, dois ligados e dois desligados. A da direita contém quatro linhas, cada uma com a figura de uma pessoa e uma linha tarjada ao lado.","As duas são um 200 e um bloco de JSON, e é tudo o que a verificação enxerga. A diferença entre elas é a pergunta inteira, e dá para respondê-la lendo.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fsettings-or-people-1600x660.png",[313,314,316],"callout",{"type":315},"note",[10,317,318,321],{},[17,319,320],{},"O caso desconfortável é o endereço que já foi configurações."," Um endpoint que\ndevolvia a lista de categorias do seu aplicativo era dado público no dia em que\nfoi escrito. Depois alguém adicionou uma coluna à tabela de trás para que a\npágina pudesse mostrar quem criou cada categoria, e o mesmo endereço passou a\nentregar nomes. Nada mudou na tela, o endereço não saiu do lugar, e o achado no\nseu relatório se lê exatamente como antes.",[22,323,325],{"id":324},"fechar-um-e-por-que-renomear-o-caminho-não-fecha","Fechar um, e por que renomear o caminho não fecha",[10,327,328],{},"Exija um login no endereço, e responda 401 a quem chamar sem ter um.",[10,330,331],{},"A correção é essa, e ela fica no endereço e em nenhum outro lugar. Três coisas\nque parecem a correção e não são:",[151,333,334,340,350],{},[154,335,336,339],{},[17,337,338],{},"Renomear o caminho, ou tirá-lo do seu código."," Dessa é preciso desconfiar,\nporque o achado some. Quem já tinha a URL continua tendo, ela está em\nhistóricos de navegação e em logs de servidor, e o arquivo continua aberto, só\nque sem a etiqueta na frente.",[154,341,342,345,346,293],{},[17,343,344],{},"Estreitar o seu cabeçalho CORS."," Isso decide quais outros sites podem ler\numa resposta dentro do navegador de alguém, e nada mais consulta esse\ncabeçalho. Um script ou um terminal lê o mesmo endereço de qualquer jeito, e é\npor isso que\n",[183,347,349],{"href":348},"\u002Fblog\u002Fcors-wildcard-security-risk","o achado do curinga é outra pergunta",[154,351,352,355],{},[17,353,354],{},"Filtrar no aplicativo."," Se a página esconde as linhas que não deveria\nmostrar, o endereço continua mandando. O filtro tem que acontecer antes de a\nresposta sair.",[10,357,358],{},"Existe uma quarta opção, e numa página pública ela costuma ser a melhor: deixar\nde ter o endpoint. Se os dados são só para a sua própria página, a página pode\nrecebê-los enquanto está sendo construída, e o endereço sai do seu código junto\ncom eles.",[22,360,362],{"id":361},"como-a-correção-fica-no-código","Como a correção fica no código",[10,364,365],{},"Duas coisas, no handler que responde ao endereço: descobrir quem está pedindo, e\nparar se a resposta for ninguém.",[10,367,368],{},"Talvez você nunca digite isso, e tudo bem. Leia assim mesmo, porque é com isso\nque você confere se o seu builder fez de fato o que você pediu. Esta é a forma\nde antes, que é o que o scan encontrou:",[370,371,376],"pre",{"className":372,"code":374,"language":375},[373],"language-text","app.get('\u002Fapi\u002Forders', async (req, res) => {\n  const orders = await db.orders.findMany()\n  res.json(orders)\n})\n","text",[158,377,374],{"__ignoreMap":378},"",[10,380,381],{},"E depois:",[370,383,386],{"className":384,"code":385,"language":375},[373],"app.get('\u002Fapi\u002Forders', async (req, res) => {\n  const user = await getUserFromRequest(req)\n  if (!user) {\n    return res.status(401).json({ error: 'Not signed in' })\n  }\n\n  const orders = await db.orders.findMany({ where: { userId: user.id } })\n  res.json(orders)\n})\n",[158,387,385],{"__ignoreMap":378},[10,389,390,391,394,395,398],{},"Duas coisas mudaram e as duas importam. O ",[158,392,393],{},"401"," é a porta. O ",[158,396,397],{},"where"," é a razão\nde a porta valer a pena: sem ele um visitante logado consegue ler os pedidos de\ntodos os outros clientes, o que é um público menor para os mesmos dados e\ncontinua sendo o errado.",[10,400,401,404,405,408,409,412,413,416,417,420],{},[17,402,403],{},"Em Edge Functions do Supabase, leia a configuração antes de escrever qualquer\ncoisa."," Edge Functions conferem o token de quem chama por conta própria: a\nreferência de configuração do Supabase deixa ",[158,406,407],{},"verify_jwt"," em ",[158,410,411],{},"true"," por padrão,\nentão uma função que responde a desconhecidos é uma em que alguém desligou isso,\nseja com uma linha em ",[158,414,415],{},"supabase\u002Fconfig.toml",", seja publicando com\n",[158,418,419],{},"--no-verify-jwt",":",[370,422,425],{"className":423,"code":424,"language":375},[373],"[functions.orders]\nverify_jwt = false\n",[158,426,424],{"__ignoreMap":378},[10,428,429],{},"Se a sua função deve ser privada, apague essas duas linhas e publique de novo.\nDeixe-as só onde o endpoint realmente precisa responder a qualquer um, que é o\ncaso que a própria documentação do Supabase usa como exemplo: um webhook de\npagamento. Dentro da função, o SDK atual entrega a você um cliente já limitado à\npessoa que chamou:",[370,431,434],{"className":432,"code":433,"language":375},[373],"import { withSupabase } from 'npm:@supabase\u002Fserver'\n\nexport default {\n  fetch: withSupabase({ auth: 'user' }, async (_req, ctx) => {\n    const { data } = await ctx.supabase.from('orders').select()\n    return Response.json(data)\n  }),\n}\n",[158,435,433],{"__ignoreMap":378},[10,437,438,439,442,443,293],{},"O ",[158,440,441],{},"ctx.supabase"," roda como quem chamou, então são as suas regras de segurança em\nnível de linha que decidem o que volta, que é a mesma proteção da qual o resto\ndo seu aplicativo depende e\n",[183,444,445],{"href":291},"o que vale a pena conferir à parte",[447,448,450],"h3",{"id":449},"o-prompt-para-colar-no-seu-builder","O prompt para colar no seu builder",[10,452,453],{},"Se você constrói no Lovable, Bolt, Cursor, Replit ou v0, entregue isto a ele.\nDeixe em inglês, seja qual for o idioma em que você está lendo, porque é nesse\nidioma que essas ferramentas raciocinam, e troque as duas partes entre colchetes\npelo que o seu relatório diz:",[370,455,458],{"className":456,"code":457,"language":375},[373],"A security scan of [my-app.com] found these API endpoints answer\nwithout any authentication: [\u002Fapi\u002Forders, \u002Fapi\u002Fusers].\n\nPlease look at each one and decide whether it is meant to be public.\nFor the ones that are not, require a valid session or API token and\nreturn 401 otherwise. Make sure each one returns only the rows that\nbelong to the person asking, not the whole table filtered in the UI.\nFor any that must stay open, make sure they return only non-sensitive\ndata and add rate limiting so they cannot be abused.\n\nTell me what you changed for each endpoint, and do not rename or\nremove the paths.\n",[158,459,457],{"__ignoreMap":378},[10,461,462],{},"Aquela última frase está ali de propósito. Quando se pede a um modelo que faça\num achado desaparecer, ele às vezes pega o caminho mais curto e move o endereço,\nque é o único resultado que parece sucesso num novo scan e não muda nada.",[313,464,466],{"type":465},"warn",[10,467,468,471],{},[17,469,470],{},"Escaneie de novo desconectado, não logado."," Depois que a correção estiver no\nar, confira do jeito que a seção acima descreve: uma janela anônima e a URL.\nTestar logado prova que o endpoint ainda funciona para você, e isso nunca esteve\nem dúvida. Saia da conta e leia de novo.",[22,473,475],{"id":474},"o-que-fazer-agora","O que fazer agora",[477,478,479],"key-takeaways",{},[151,480,481,484,487,490,493],{},[154,482,483],{},"Abra cada endereço apontado numa janela anônima e leia o que volta. Esse é o passo que o relatório não faz por você.",[154,485,486],{},"Se a resposta forem configurações e o endereço for um que você nunca escreveu, ele é do seu builder e não há nada a corrigir. Procure o caminho na documentação da sua plataforma antes de gastar qualquer coisa com isso.",[154,488,489],{},"Se a resposta tiver um nome, um e-mail ou um pedido, exija hoje um login naquele endereço e devolva 401 a quem não tiver.",[154,491,492],{},"Não renomeie o caminho nem apague a referência a ele. O achado some e o endereço continua respondendo.",[154,494,495],{},"Tente mudar um id na URL no seu próprio aplicativo. Um endereço que serve um registro a um estranho costuma servir todos.",[10,497,498,499,293],{},"Os endereços dessa lista foram todos escritos por alguém que sabia o que havia\natrás deles na época, e o que muda é justamente o que há atrás. O Reeve Care\nroda esse scan de novo no seu aplicativo em produção com uma periodicidade e\nmanda um e-mail quando um resultado piora, que é exatamente o caso que a\npassagem desconectada acima não consegue pegar:\n",[183,500,502],{"href":501},"\u002Fpricing","o que ele vigia e quanto custa",[10,504,505,506,510,511,515],{},"Se preferir resolver tudo de uma vez, a\n",[183,507,509],{"href":508},"\u002Fchecklist","checklist de segurança em 10 minutos"," cobre isso ao lado do resto\ndo que um aplicativo recém-lançado costuma deixar aberto, e\n",[183,512,514],{"href":513},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","quais chaves são seguras no seu frontend","\né o outro achado com o qual as pessoas costumam chegar.",{"title":378,"searchDepth":517,"depth":517,"links":518},3,[519,521,522,523,524,525,526,529],{"id":24,"depth":520,"text":25},2,{"id":46,"depth":520,"text":47},{"id":123,"depth":520,"text":124},{"id":190,"depth":520,"text":191},{"id":296,"depth":520,"text":297},{"id":324,"depth":520,"text":325},{"id":361,"depth":520,"text":362,"children":527},[528],{"id":449,"depth":517,"text":450},{"id":474,"depth":520,"text":475},"Noções de segurança","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcover-1200x630.png","Duas portinholas idênticas numa parede, de cada uma sai uma folha. Uma traz uma fileira de interruptores, a outra uma coluna de rostos.","Seu scan apontou um endpoint de API aberto. Se isso importa depende do que voltou, e a maioria dos que encontramos era da própria plataforma.",false,"md",[537,540,542,545,548],{"q":538,"a":539},"O que significa \"endpoint de API aberto\" no meu relatório?","Significa que lemos o código que o seu aplicativo envia para um navegador, achamos ali dentro um endereço de onde o seu aplicativo busca dados, e pedimos dados a esse endereço sem conta e sem login. Ele respondeu, e a resposta era JSON. O achado é isso. Ele registra o que aconteceu, e não julga se os dados eram privados, porque nada fora do seu aplicativo tem como saber.",{"q":47,"a":541},"Não. Muitos endereços existem para responder a qualquer um: uma tabela de preços publicada, um artigo, a lista de quais recursos estão ligados. O problema é o endereço que devolve linhas que pertencem a pessoas, porque ele faz isso para todo mundo que tiver a URL. Leia o que voltou e pergunte se alguma coisa ali descreve uma pessoa.",{"q":543,"a":544},"Meu relatório aponta um endpoint que eu não escrevi. O que é isso?","Em geral é do seu builder. Plataformas que dão ao seu aplicativo um pequeno servidor próprio também colocam nele alguns endereços delas, e esses estão no código de todo aplicativo da plataforma. O exemplo mais claro que medimos são as configurações de cookies da Base44 em \u002Fapi\u002Fconsent\u002Fconfig, que respondem por 2.705 dos 3.852 achados da nossa varredura de agosto de 2026. Elas devolvem configurações, são idênticas em todo aplicativo Base44, e nada ali pertence a você.",{"q":546,"a":547},"Como eu verifico o que os endpoints do meu aplicativo devolvem?","Abra seu aplicativo em produção, aperte F12, clique em Rede e recarregue. As requisições que voltam como JSON são os endereços de onde o seu aplicativo busca dados. Copie cada URL, abra uma janela anônima para estar desconectado, e cole uma de cada vez. Leia o que chega. Um erro ou uma lista vazia está tudo bem. Linhas com nomes, e-mails ou valores de pedidos podem ser lidas por qualquer pessoa que tenha aquele endereço.",{"q":549,"a":550},"Esconder o caminho resolve?","Não. Renomear o endereço, ou tirar do seu código a referência a ele, impede que um scanner o encontre e o deixa respondendo exatamente como antes. Quem já tinha a URL continua tendo, e ela fica em históricos de navegação, logs de servidor e em tudo que rastreou o seu site. A correção é no endereço: exigir um login e responder 401 a um desconhecido.","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",[553,554,555,556,557,558,559],"endpoint de api aberto","endpoint de api sem autenticação","endpoint de api devolve dados sem login","meu endpoint de api é público","rota de api desprotegida","endpoint de api sem login","endpoint json exposto",{},true,"Um endpoint de API aberto é um problema de segurança?","\u002Fblog\u002Fopen-api-endpoint-exposed","2026-09-25",{"title":5,"description":533},"blog\u002Fopen-api-endpoint-exposed",[568,569,570],"Um endpoint de API aberto significa que um caminho escrito no código do seu aplicativo respondeu a uma requisição sem login, e o que voltou foi JSON.","Dos que encontramos em 30.926 aplicativos, sete em cada dez foram colocados lá pela plataforma em que o aplicativo foi publicado, e devolvem configurações.","A pergunta que decide é se algo na resposta descreve uma pessoa. Uma tabela de preços é pública de propósito. Uma lista dos seus clientes nunca foi.","Fpd59tRfHD2jgNEJ0KypCT1FBVrzxKA66YmIWQA1pYE",[573,579,585,591,597,603,609,615,621,627,633,639,645,652,658,664,669,670,676,682,688,694,700,706,712,718,724,730,736,742,748,754,760,766,772,778,784,790,796,802,808,814,820,826,832,838,844,849,855,861,867,873,879,885,890,896,902,907,912,918],{"path":574,"title":575,"description":576,"published":577,"category":530,"image":578,"draft":534},"\u002Fblog\u002Fbase44-security-scan","Scan de segurança do Base44: o que só ele enxerga","O scan de segurança do Base44 verifica sete tipos de problema por dentro. Esta é a metade que ele lê e mais ninguém, e a metade que ele nunca olha.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":580,"title":581,"description":582,"published":583,"category":530,"image":584,"draft":534},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Sua chave de API vazou. A ordem em que agir","Uma chave de API vazou e você não sabe o que fazer primeiro. Nem toda chave no seu frontend é um vazamento, e a ordem importa mais que a pressa.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":586,"title":587,"description":588,"published":589,"category":530,"image":590,"draft":534},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sem desligar o RLS","\"Infinite recursion detected in policy for relation\" significa que a sua policy perguntou à tabela que ela protege. Veja como quebrar o círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":592,"title":593,"description":594,"published":595,"category":530,"image":596,"draft":534},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" no Supabase, e a correção errada","\"No API key found in request\" significa que sua requisição chegou ao Supabase sem chave. Quase toda resposta aponta para as regras do seu banco.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":598,"title":599,"description":600,"published":601,"category":530,"image":602,"draft":534},"\u002Fblog\u002Fis-base44-safe","O Base44 é seguro? O que vimos em 5.442 apps Base44","O Base44 é seguro? Rodamos nove verificações em 5.442 apps Base44 no ar. Quase todas tiraram B por motivos que o dono nunca escolheu.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":604,"title":605,"description":606,"published":607,"category":530,"image":608,"draft":534},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Esconder uma chave de API: mova para uma Edge Function do Supabase","Esconder uma chave de API é tirá-la do navegador, e uma Edge Function do Supabase é o menor lugar para guardá-la. Dois passos em volta pesam mais.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":610,"title":611,"description":612,"published":613,"category":530,"image":614,"draft":534},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Seu arquivo .env está exposto? Os doze caminhos para testar","Seu arquivo .env está exposto no seu próprio servidor web? Doze endereços dizem isso em um minuto, e um acerto significa que tudo nele já é público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":616,"title":617,"description":618,"published":619,"category":530,"image":620,"draft":534},"\u002Fblog\u002Fis-v0-safe","Segurança do v0: os 1.790 aplicativos v0 escaneados tiraram A","A segurança do v0 medida em 1.790 aplicativos v0 no ar: todos tiraram A. Só 17 citavam um banco de dados, e é sobretudo isso que esse A mede.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":622,"title":623,"description":624,"published":625,"category":530,"image":626,"draft":534},"\u002Fblog\u002Fis-bolt-safe","O Bolt é seguro? O que vimos em 1.123 aplicativos Bolt","O Bolt é seguro? Passamos 1.123 aplicativos Bolt no ar por nove verificações. A hospedagem saiu limpa. Os achados: chaves e tabelas abertas nos aplicativos.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":628,"title":629,"description":630,"published":631,"category":530,"image":632,"draft":534},"\u002Fblog\u002Fis-supabase-down-or-your-app","O Supabase caiu ou o problema é o seu app? Como saber","O Supabase caiu ou o problema é o seu app? Um projeto pausado, um banco cheio e um erro seu parecem iguais. Quatro verificações separam os casos.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":634,"title":635,"description":636,"published":637,"category":530,"image":638,"draft":534},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","O Supabase criptografa meus dados? Sim. Veja o que isso impede","O Supabase criptografa os dados? Sim: AES-256 em repouso, TLS em trânsito, SOC 2 e ISO 27001. O que cada um cobre, e o vazamento que nenhum deles impede.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":640,"title":641,"description":642,"published":643,"category":530,"image":644,"draft":534},"\u002Fblog\u002Fsupabase-free-plan-limits","Quanto custa o Supabase? Os limites do plano gratuito","Quanto custa o Supabase: o plano gratuito tem 500 MB de banco, 5 GB de egress e nenhum backup. O que acontece em cada limite e o que o Pro de $25 muda.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":646,"title":647,"description":648,"published":649,"category":650,"image":651,"draft":534},"\u002Fblog\u002Ftest-your-supabase-backup","Teste o backup do seu Supabase antes do dia em que precisar","Como testar o backup do seu Supabase: restaurar num projeto de teste, contar as linhas, entrar e procurar a linha que falta num arquivo cortado.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":650,"image":657,"draft":534},"\u002Fblog\u002Fsupabase-backup-github-action","Backup grátis do Supabase com uma GitHub Action, e a pegadinha","Um backup do Supabase com GitHub Action é grátis e serve para muitos apps. O workflow, a connection string certa e o egress de cada execução.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":659,"title":660,"description":661,"published":662,"category":650,"image":663,"draft":534},"\u002Fblog\u002Fdownload-your-supabase-backup","Por que você não consegue baixar seu backup do Supabase","Você não consegue baixar seu backup do Supabase num projeto atual, porque a cópia diária é um snapshot físico. Como conferir e como ter uma cópia só sua.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":665,"title":666,"description":667,"published":662,"category":530,"image":668,"draft":534},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": o grant que falta","A partir de 30 de outubro, uma tabela nova no Supabase responde \"permission denied for table\" até receber um grant. O e-mail mostra só metade.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":563,"title":5,"description":533,"published":564,"category":530,"image":551,"draft":534},{"path":671,"title":672,"description":673,"published":674,"category":530,"image":675,"draft":534},"\u002Fblog\u002Flovable-security-scan","Escaneamento de segurança do Lovable: o que ele não prova","Escaneamento de segurança do Lovable: o que o Quick scan e o Deep scan checam, quando cada um roda, e a única coisa que nenhum escaneamento por dentro prova.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":677,"title":678,"description":679,"published":680,"category":650,"image":681,"draft":534},"\u002Fblog\u002Fsupabase-backup-auth-users","Por que seu dump do Supabase não tem usuários dentro","Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":683,"title":684,"description":685,"published":686,"category":530,"image":687,"draft":534},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":689,"title":690,"description":691,"published":692,"category":530,"image":693,"draft":534},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":695,"title":696,"description":697,"published":698,"category":530,"image":699,"draft":534},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":530,"image":705,"draft":534},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Uma chave secreta da Stripe no frontend pode mover dinheiro","Uma chave secreta da Stripe exposta no seu frontend pode reembolsar, cobrar e ler cada ficha de cliente que você tem. Sua chave pk_live_ é que deve estar aí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":707,"title":708,"description":709,"published":710,"category":530,"image":711,"draft":534},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variáveis de ambiente do Vite expostas: o prefixo diz publique isto","Variáveis de ambiente do Vite expostas no seu app: fizeram o que o prefixo pediu. VITE_ e NEXT_PUBLIC_ significam publique isto, e a IA nunca soube o custo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":713,"title":714,"description":715,"published":716,"category":530,"image":717,"draft":534},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":719,"title":720,"description":721,"published":722,"category":530,"image":723,"draft":534},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":725,"title":726,"description":727,"published":728,"category":530,"image":729,"draft":534},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":731,"title":732,"description":733,"published":734,"category":650,"image":735,"draft":534},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":737,"title":738,"description":739,"published":740,"category":650,"image":741,"draft":534},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":743,"title":744,"description":745,"published":746,"category":650,"image":747,"draft":534},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":749,"title":750,"description":751,"published":752,"category":530,"image":753,"draft":534},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":755,"title":756,"description":757,"published":758,"category":530,"image":759,"draft":534},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Ative Row Level Security em toda tabela do Supabase e comprove","Ativar Row Level Security no Supabase sem política fecha a tabela por completo. Uma política sem a chave ligada não faz nada. Aqui está o SQL, e o teste.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":761,"title":762,"description":763,"published":764,"category":530,"image":765,"draft":534},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": o que o aviso não vê","O Supabase marca \"RLS disabled in public\" como erro. Ele não diz nada sobre a política de leitura que deixa a sua tabela igualmente aberta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":767,"title":768,"description":769,"published":770,"category":530,"image":771,"draft":534},"\u002Fblog\u002Frotate-supabase-service-role-key","Como rotacionar uma chave service_role do Supabase vazada","O Supabase manda fechar o vazamento primeiro. Outros guias mandam rotacionar agora. O que vale depende de para onde a sua chave service_role vazou.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":773,"title":774,"description":775,"published":776,"category":530,"image":777,"draft":534},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Dez ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":530,"image":783,"draft":534},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":530,"image":789,"draft":534},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":791,"title":792,"description":793,"published":794,"category":530,"image":795,"draft":534},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":797,"title":798,"description":799,"published":800,"category":530,"image":801,"draft":534},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Sua chave de API da OpenAI está exposta no frontend. Troque-a.","Uma chave de API da OpenAI exposta no frontend não pode ser presa a um domínio. Troque-a hoje, mova a chamada para o seu servidor e limite o gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":803,"title":804,"description":805,"published":806,"category":530,"image":807,"draft":534},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":809,"title":810,"description":811,"published":812,"category":650,"image":813,"draft":534},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":815,"title":816,"description":817,"published":818,"category":530,"image":819,"draft":534},"\u002Fblog\u002Freplit-secrets-explained","Como usar secrets no Replit, e o que ainda assim é publicado","Como usar secrets no Replit: adicionar um, ler de volta e resolver as duas causas do undefined. E as chaves que a ferramenta Secrets não consegue proteger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":821,"title":822,"description":823,"published":824,"category":650,"image":825,"draft":534},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":827,"title":828,"description":829,"published":830,"category":530,"image":831,"draft":534},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":833,"title":834,"description":835,"published":836,"category":530,"image":837,"draft":534},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":839,"title":840,"description":841,"published":842,"category":530,"image":843,"draft":534},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":348,"title":845,"description":846,"published":847,"category":530,"image":848,"draft":534},"Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":850,"title":851,"description":852,"published":853,"category":650,"image":854,"draft":534},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":856,"title":857,"description":858,"published":859,"category":650,"image":860,"draft":534},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":862,"title":863,"description":864,"published":865,"category":530,"image":866,"draft":534},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":868,"title":869,"description":870,"published":871,"category":530,"image":872,"draft":534},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":874,"title":875,"description":876,"published":877,"category":650,"image":878,"draft":534},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":880,"title":881,"description":882,"published":883,"category":530,"image":884,"draft":534},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Qualquer um consegue ler seu banco Supabase? Testamos 3.680 apps","Qualquer um consegue ler seu banco de dados Supabase sem fazer login? Escaneamos 30.998 apps no ar criadas com builders de IA e medimos quantas dizem que sim.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":886,"title":887,"description":888,"published":883,"category":530,"image":889,"draft":534},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":891,"title":892,"description":893,"published":894,"category":530,"image":895,"draft":534},"\u002Fblog\u002Fsupabase-new-api-keys","As novas chaves de API do Supabase: qual vai no seu app?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":650,"image":901,"draft":534},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":291,"title":903,"description":904,"published":905,"category":530,"image":906,"draft":534},"O Supabase Row Level Security está ligado. A tabela continua pública.","Ligar o Supabase Row Level Security não protege uma tabela. Quem protege são as políticas, e a que consertou o seu app pode deixar qualquer um entrar.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":908,"title":909,"description":910,"published":905,"category":650,"image":911,"draft":534},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":913,"title":914,"description":915,"published":916,"category":650,"image":917,"draft":534},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":513,"title":919,"description":920,"published":916,"category":530,"image":921,"draft":534},"Quais chaves de API são seguras no navegador e quais não são","Sua chave anon do Supabase foi feita para ser pública. Sua chave service_role não, e ela ignora todas as regras que você criar. Como diferenciar as duas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791618971778]