[{"data":1,"prerenderedAt":422},["ShallowReactive",2],{"blog-pt-google-api-key-exposed-in-frontend":3},{"id":4,"title":5,"body":6,"category":380,"cover":381,"coverAlt":381,"description":382,"draft":383,"extension":384,"faq":385,"image":401,"keywords":402,"meta":409,"navigation":410,"ogTitle":411,"path":412,"published":413,"seo":414,"stem":415,"tldr":416,"updated":413,"__hash__":421},"blog_pt\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend.md","Uma chave de API do Google no frontend é um problema?",{"type":7,"value":8,"toc":368},"minimark",[9,18,26,35,40,43,46,49,52,56,59,66,69,75,79,89,141,148,151,158,162,260,263,268,272,275,282,292,296,299,305,308,311,321,325,356],[10,11,12,13,17],"p",{},"Abra seu app no navegador, veja o código-fonte da página e procure por ",[14,15,16],"code",{},"AIza",".\nSe aparecer uma sequência de quarenta caracteres, provavelmente alguém já disse\nque ela está \"exposta\", e provavelmente não disse o que fazer depois.",[10,19,20,21,25],{},"Aqui está a parte que a maioria dos conselhos sobre isso erra: ",[22,23,24],"strong",{},"uma chave de API\ndo Google no seu frontend não é o mesmo tipo de problema que uma chave secreta do\nStripe no seu frontend, e a correção não é escondê-la."," Tratar as duas do mesmo\njeito leva ou a entrar em pânico por causa do seu mapa ou, pior, a aprender a dar\nde ombros para a palavra \"exposta\" pouco antes do dia em que ela importa.",[10,27,28,29,34],{},"Entre 12 e 14 de agosto de 2026 rodamos as mesmas nove verificações externas em\n30.998 apps no ar criados com Lovable, Bolt, v0, Replit e Base44. Uma chave de\nAPI do Google apareceu em 1.142 deles. Uma chave secreta do Stripe apareceu em\ntrês. Os números completos estão no\n",[30,31,33],"a",{"href":32},"\u002Fresearch\u002Fvibe-coded-app-security-2026","nosso relatório de varredura",".",[36,37,39],"h2",{"id":38},"é-ruim-que-minha-chave-de-api-do-google-esteja-exposta-no-frontend","É ruim que minha chave de API do Google esteja exposta no frontend?",[10,41,42],{},"Quase nunca. Depende inteiramente de a chave estar restrita ou não.",[10,44,45],{},"Uma chave de API do Google não é uma senha. Ela se parece mais com um número de\nconta: diz ao Google qual projeto cobrar e de qual cota descontar. Sozinha, ela\nnão diz nada sobre quem está fazendo a requisição.",[10,47,48],{},"É por isso que ela pode morar na sua página. O mapa é desenhado pelo navegador do\nseu visitante, então é o navegador que precisa mandar esse número de conta ao\nGoogle. Não existe uma versão disso em que o mapa carrega e o número fica\nescondido.",[10,50,51],{},"A proteção vem de um segundo ajuste, guardado do lado do Google, que diz de quais\nsites o número pode ser usado. O Google chama isso de restrição de referenciador\nHTTP. Com ele definido, a chave impressa na sua página funciona no seu site e\ndevolve um erro em qualquer outro lugar.",[36,53,55],{"id":54},"por-que-seu-app-entrega-a-chave","Por que seu app entrega a chave",[10,57,58],{},"Porque a requisição sai do navegador do seu visitante, não do seu servidor.",[10,60,61,62,65],{},"Quando alguém carrega uma página com um mapa, esse navegador fala direto com o\n",[14,63,64],{},"maps.googleapis.com",". Ele precisa dizer a qual projeto do Google a requisição\npertence, e esse identificador precisa estar na página, porque a página é de onde\na requisição parte.",[10,67,68],{},"O Google sabe disso. É por isso que a restrição existe como um controle\nseparado: o identificador ia ser público de qualquer forma, então o que decide\nquem pode usá-lo mora em um lugar que o público não alcança.",[70,71],"diagram",{"alt":72,"caption":73,"src":74},"Duas fileiras. Na fileira de cima uma restrição fica entre as requisições e o Google: uma requisição vinda de yourapp.com passa por ela e chega a maps.googleapis.com, enquanto a mesma chave enviada de other.example é barrada na restrição e marcada com um xis. Na fileira de baixo a restrição está desenhada como uma linha interrompida e as duas requisições passam, a do estranho tracejada em âmbar.","A chave é idêntica nas duas fileiras. A única diferença é se há uma restrição definida nela.","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Frestricted-or-not-1600x820.png",[36,76,78],{"id":77},"como-restringir-uma-chave-de-api-do-google","Como restringir uma chave de API do Google",[10,80,81,82,88],{},"É grátis, leva cerca de cinco minutos e você não precisa mexer no código do seu\napp. No ",[30,83,87],{"href":84,"rel":85},"https:\u002F\u002Fconsole.cloud.google.com\u002F",[86],"nofollow","console do Google Cloud",":",[90,91,92,100,110,129,138],"ol",{},[93,94,95,96,99],"li",{},"Vá em ",[22,97,98],{},"APIs e serviços → Credenciais"," e clique na chave que você achou.",[93,101,102,103,106,107,34],{},"Em ",[22,104,105],{},"Restrições de aplicativo",", escolha ",[22,108,109],{},"Sites",[93,111,112,113,116,117,120,121,124,125,128],{},"Adicione seu domínio. Para um site em ",[14,114,115],{},"yourapp.com",", adicione\n",[14,118,119],{},"https:\u002F\u002Fyourapp.com\u002F*",". Adicione também seu domínio de prévia ou de teste, se\nvocê tiver um, e lembre do endereço ",[14,122,123],{},".lovable.app"," ou ",[14,126,127],{},".vercel.app"," em que seu\napp foi publicado antes de você ligar um domínio próprio.",[93,130,102,131,106,134,137],{},[22,132,133],{},"Restrições de API",[22,135,136],{},"Restringir chave"," e marque só as APIs que\nseu app chama de verdade. Um mapa com busca de lugares precisa da API\nJavaScript do Maps e da API Places, e nada mais.",[93,139,140],{},"Salve, espere alguns minutos, depois carregue seu próprio site e confira se o\nmapa ainda é desenhado.",[10,142,143,144,147],{},"Se o passo 3 estiver errado, você descobre na hora e de forma visível: o mapa\nfalha com ",[14,145,146],{},"RefererNotAllowedMapError"," no console do navegador, o que nomeia o\nproblema exato. Adicione o domínio que falta e volta a funcionar. É uma mudança\nreversível, e por isso vale a pena fazê-la antes de terminar de ler sobre ela.",[10,149,150],{},"Uma coisa para não fazer: as próprias orientações de solução de problemas do\nGoogle dizem que restrições por endereço IP são para chaves do lado do servidor e\nnão servem para uma chave usada por um navegador. Se você restringir por IP uma\nchave do frontend, seu app quebra para todos os visitantes.",[10,152,153,154,34],{},"Se você prefere ver quais chaves seu app está de fato entregando antes de ir uma\na uma, nossa varredura gratuita lê seu site no ar de fora e diz o que encontra.\nLeva cerca de 20 segundos e não precisa de conta: ",[30,155,157],{"href":156},"\u002F#scan","escaneie seu app",[36,159,161],{"id":160},"quais-credenciais-do-google-cabem-em-um-navegador","Quais credenciais do Google cabem em um navegador",[163,164,165,184],"table",{},[166,167,168],"thead",{},[169,170,171,175,178,181],"tr",{},[172,173,174],"th",{},"Credencial",[172,176,177],{},"Como é",[172,179,180],{},"No seu frontend?",[172,182,183],{},"O que realmente protege",[185,186,187,208,224,242],"tbody",{},[169,188,189,193,198,205],{},[190,191,192],"td",{},"Chave de navegador do Maps ou Places",[190,194,195],{},[14,196,197],{},"AIza…",[190,199,200],{},[201,202,204],"key-verdict",{"type":203},"safe","É o lugar dela",[190,206,207],{},"A restrição de referenciador, mais um teto de cota",[169,209,210,213,217,221],{},[190,211,212],{},"Chave de configuração web do Firebase",[190,214,215],{},[14,216,197],{},[190,218,219],{},[201,220,204],{"type":203},[190,222,223],{},"As regras de segurança do Firebase e o App Check",[169,225,226,229,233,239],{},[190,227,228],{},"Uma chave que você usa do seu servidor",[190,230,231],{},[14,232,197],{},[190,234,235],{},[201,236,238],{"type":237},"danger","Nunca",[190,240,241],{},"Nada, depois de pública. Deixe no servidor",[169,243,244,247,253,257],{},[190,245,246],{},"Conta de serviço",[190,248,249,250],{},"um arquivo JSON contendo ",[14,251,252],{},"\"private_key\"",[190,254,255],{},[201,256,238],{"type":237},[190,258,259],{},"Nada. Essa é uma credencial de verdade",[10,261,262],{},"As três primeiras linhas são a mesma sequência. Uma chave de API do Google não\ntraz escrito na frente para que serve, então a pergunta nunca é \"com o que essa\nchave se parece\" e sim \"o que essa chave pode fazer\", e essa resposta mora no\nconsole e não no seu código.",[70,264],{"alt":265,"caption":266,"src":267},"Uma única chave AIza no topo se ramifica em três cópias idênticas. A primeira está marcada com um certo e rotulada yourapp.com, a segunda está marcada com um certo e rotulada firebaseConfig, e a terceira está riscada e rotulada com um asterisco que representa qualquer site. Separado abaixo por uma linha tracejada, um quarto item com os dizeres type service_account está riscado.","Três delas são os mesmos quarenta caracteres. O que as separa é um ajuste que não dá para ver no código da página.","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fone-shape-three-jobs-1600x720.png",[36,269,271],{"id":270},"a-chave-do-firebase-foi-feita-para-ser-pública","A chave do Firebase foi feita para ser pública",[10,273,274],{},"Essa é a linha sobre a qual mais perguntam, e a própria documentação do Firebase\nresponde com clareza: chaves de API dos serviços do Firebase podem ficar no\ncódigo ou em arquivos de configuração, porque elas não controlam o acesso a nada.\nQuem decide isso são as regras de segurança do Firebase e o App Check.",[10,276,277,278,34],{},"Se isso soa familiar, é o mesmo arranjo que o Supabase usa. A chave publicável\nidentifica o projeto, e as regras por trás dela decidem linha por linha quem pode\nler o quê. Nos dois casos a chave só é segura por causa dessas regras, então as\nregras são o que você deve ir olhar:\n",[30,279,281],{"href":280},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","ligá-las não é o mesmo que estar protegido",[283,284,286],"callout",{"type":285},"warn",[10,287,288,291],{},[22,289,290],{},"A única armadilha do Firebase, e ela é nova."," A documentação do Firebase é\nespecífica: não adicione a API Gemini para desenvolvedores, listada como\nGenerative Language API, à lista de APIs permitidas da sua chave web do Firebase.\nEssa chave é publicada de propósito, e cada chamada ao modelo feita com ela é\ncobrada do seu projeto. É um erro fácil de cometer em um app que começou como app\nFirebase e depois ganhou um recurso de IA, o que a esta altura são muitíssimos.",[36,293,295],{"id":294},"o-que-acontece-de-fato-quando-vaza-uma-chave-sem-restrição","O que acontece de fato quando vaza uma chave sem restrição",[10,297,298],{},"Uma conta, uma indisponibilidade ou as duas. Não um vazamento de dados.",[10,300,301,302,304],{},"Raspadores automáticos percorrem páginas públicas colhendo sequências ",[14,303,16],{},", e\numa chave sem restrição funciona de qualquer lugar, então a sua acaba servindo\nblocos de mapa e buscas de lugares para o projeto de outra pessoa. O Google diz\nisso diretamente na própria documentação inicial: o motivo de definir restrições\né impedir o roubo de cota.",[10,306,307],{},"Você normalmente percebe de uma de duas formas. A fatura vem maior que a do mês\npassado sem um motivo que você saiba apontar, ou os mapas do seu app param de ser\ndesenhados no meio do mês porque o projeto esgotou a cota e cada visitante agora\nvê um retângulo cinza.",[10,309,310],{},"As duas têm conserto. Nenhuma expõe os dados dos seus usuários, porque uma chave\ndo Maps não consegue ler seu banco de dados. Essa é a diferença honesta entre\nesse achado e uma chave de banco vazada, e é por isso que nosso scanner reporta\numa chave de API do Google como algo a conferir e não como uma emergência.",[10,312,313,314,317,318,320],{},"A única credencial do Google que de fato se comporta como uma emergência é uma\nconta de serviço. Se seu app está entregando um arquivo JSON com\n",[14,315,316],{},"\"type\": \"service_account\""," e um bloco ",[14,319,252],{}," dentro, isso é uma\ncredencial de verdade com permissões de verdade no seu projeto na nuvem. Exclua a\nchave no console e depois veja o que ela conseguia alcançar.",[36,322,324],{"id":323},"o-que-fazer-agora","O que fazer agora",[326,327,328],"key-takeaways",{},[329,330,331,337,343,346,349],"ul",{},[93,332,333,334,336],{},"Procure ",[14,335,16],{}," no código-fonte do seu site no ar. Cada ocorrência é uma chave pela qual responder.",[93,338,339,340,342],{},"Restrinja cada uma no console do Google Cloud: ",[22,341,109],{}," nas restrições de aplicativo, seu domínio, e só as APIs que você usa. Grátis, cerca de cinco minutos, sem mudar código.",[93,344,345],{},"Já que está lá, coloque também um teto de cota diária na chave. A restrição reduz o tráfego; um teto limita o quanto tudo isso pode custar.",[93,347,348],{},"Deixe sua chave de configuração do Firebase onde está. Confira, em vez disso, se suas regras de segurança estão fazendo o trabalho, e mantenha a API Gemini fora da lista permitida dessa chave.",[93,350,351,352,355],{},"Se você achar um arquivo JSON de ",[14,353,354],{},"service_account"," no seu frontend, trate como urgente. Exclua a chave no console em vez de só remover o arquivo, porque seu histórico de versões ainda tem o valor antigo.",[10,357,358,359,363,364,34],{},"Se você prefere resolver isso como uma lista, o\n",[30,360,362],{"href":361},"\u002Fchecklist","checklist de segurança de 10 minutos"," cobre isso junto com as outras\ncoisas que vale desligar em um app recém-lançado. E para a pergunta maior de\nquais chaves cabem em um navegador, temos\n",[30,365,367],{"href":366},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","um guia para distinguir chaves publicáveis das secretas",{"title":369,"searchDepth":370,"depth":370,"links":371},"",3,[372,374,375,376,377,378,379],{"id":38,"depth":373,"text":39},2,{"id":54,"depth":373,"text":55},{"id":77,"depth":373,"text":78},{"id":160,"depth":373,"text":161},{"id":270,"depth":373,"text":271},{"id":294,"depth":373,"text":295},{"id":323,"depth":373,"text":324},"Noções de segurança",null,"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.",false,"md",[386,389,392,395,398],{"q":387,"a":388},"Alguém achou minha chave do Google Maps no código da página. Devo trocá-la?","Restrinja primeiro: leva cerca de cinco minutos e não quebra nada. Abra a chave no console do Google Cloud, defina as restrições de aplicativo como Sites e adicione seu domínio, depois limite as restrições de API apenas às APIs que seu app usa. Trocar vem depois, e só se a chave ficou sem restrição por um tempo e você vê consumo que não foi você que causou.",{"q":390,"a":391},"Não dá para esconder a chave para ninguém achar?","Não. O navegador do seu visitante precisa enviar a chave ao Google para carregar o mapa, então tudo que o navegador consegue usar, um visitante consegue ler. Minificar ou renomear só atrasa alguém por alguns segundos. Restringir a chave é a correção que realmente funciona, e ela funciona quer alguém ache a chave ou não.",{"q":393,"a":394},"Minha chave está restrita ao meu domínio. Alguém ainda pode usá-la?","Um cabeçalho de referenciador pode ser forjado, então alguém determinado pode enviar requisições que afirmam vir do seu site. O que a restrição elimina é o caso fácil: um raspador automático que colhe chaves em páginas públicas e as usa direto do próprio servidor. É esse tráfego que produz contas surpresa, então a restrição vale a pena mesmo não sendo um muro. Coloque também um teto de cota diária na chave e você terá um limite para o que tudo isso pode custar.",{"q":396,"a":397},"O Firebase colocou uma chave de API no meu arquivo de configuração. Isso é um erro?","Não, e o Firebase documenta isso. Uma chave de API web do Firebase identifica seu projeto em vez de autorizar o acesso, e quem decide o acesso são as regras de segurança do Firebase e o App Check. Ela foi feita para ficar no seu código. A única coisa a evitar é adicionar a API Gemini para desenvolvedores à lista de APIs permitidas dessa chave, porque isso transforma uma chave publicada de propósito em uma que pode gastar dinheiro.",{"q":399,"a":400},"E se eu achar um arquivo com \"type\": \"service_account\" no meu app?","Essa é outra situação e é urgente. Uma chave de conta de serviço é uma credencial de verdade com uma chave privada dentro, e o lugar dela é um servidor. Exclua a chave no console do Google Cloud em IAM e administração, depois Contas de serviço, tire o arquivo do seu frontend e confira sua cobrança e seus registros de auditoria. Excluir só do código não fecha a porta, porque o valor antigo continua no seu histórico de versões.","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",[403,404,405,406,407,408],"chave api google no frontend","restringir chave api google maps","restrição de referenciador http","chave api firebase pública","chave api AIza","minha chave api do google é segura",{},true,"Uma chave de API do Google no seu frontend?","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","2026-08-22",{"title":5,"description":382},"blog\u002Fgoogle-api-key-exposed-in-frontend",[417,418,419,420],"Uma chave de API do Google exposta no seu frontend quase sempre está tudo bem, porque uma chave do Google é um identificador de cobrança e não uma senha.","O que a deixa segura é uma restrição de referenciador HTTP: um ajuste que diz ao Google que a chave só funciona a partir do seu próprio site.","É grátis, leva cerca de cinco minutos e é a única coisa que vale a pena fazer hoje.","Um arquivo de conta de serviço do Google no seu app é o caso diferente e urgente. Essa sim é uma credencial de verdade.","GoAxRGCrATOV0v6HiP5N_3IBFk46Y0sQ0v8qgqP1D9E",1787826050881]