Chaves da OpenAI ou da Stripe no seu app feito com IA? Leve-as para uma função no servidor
Qualquer pessoa copia uma chave do frontend. Quais podem ficar no navegador, como achar as que não podem e como levá-las para uma Edge Function do Supabase.
4 min de leitura
Você pediu à sua ferramenta de IA para colocar um chatbot, pagamentos ou envio de e-mail no app. Funcionou de primeira, e muitas vezes funcionou tão rápido porque a chave da API foi direto para o código do frontend.
Tudo o que está no frontend é enviado ao navegador de cada visitante. Se uma chave está ali, qualquer pessoa pode abrir as ferramentas de desenvolvedor, copiá-la e usá-la, na sua conta e na sua fatura. Existem scanners automáticos procurando exatamente essas chaves em sites públicos.
Quais chaves podem ficar no navegador
Nem toda chave é secreta. Muitos serviços emitem dois tipos de propósito:
| Pode ficar no navegador | Nunca no navegador |
|---|---|
Chave publicável da Stripe (pk_live_…) |
Chave secreta ou restrita da Stripe (sk_live_…, rk_live_…) |
| Chave publicável ou anon do Supabase | Chave secreta ou service role do Supabase (o que fazer se ela vazou) |
| IDs de analytics e de tags | Chaves da OpenAI, da Anthropic e de outras IAs (sk-…) |
| Chaves de mapas restritas ao seu domínio | Chaves de envio de e-mail (Resend re_…, SendGrid, Postmark) |
A regra: se a chave permite gastar dinheiro, ler dados privados ou enviar algo em seu nome, ela pertence a um servidor.
O custo de uma chave vazada depende do serviço. Uma chave de IA pode gerar uma conta alta em poucas horas. Uma chave secreta da Stripe lê os seus clientes e emite reembolsos. Uma chave de e-mail permite mandar phishing a partir do seu domínio, o que ainda prejudica a entrega dos seus e-mails por meses.
Encontre as chaves no app publicado
Abra o app, aperte F12, vá em Sources (Chrome) ou Debugger (Firefox) e busque em todos os arquivos (Ctrl+Shift+F ou Cmd+Option+F) por: sk-, sk_live, rk_live, re_, sb_secret_, service_role.
Se você tem o código localmente, gere o build e busque no resultado, que é exatamente o que os visitantes recebem:
npm run build
grep -rEn "sk-[A-Za-z0-9_-]{20,}|sk_live_|rk_live_|re_[A-Za-z0-9_]{20,}|sb_secret_|service_role" dist/Uma origem comum é o arquivo de ambiente. Em projetos Vite, o que inclui a maioria dos apps do Lovable e do Bolt, toda variável que começa com VITE_ é copiada para o código do navegador. No Next.js, vale o mesmo para NEXT_PUBLIC_. Um segredo em VITE_OPENAI_API_KEY é público, mesmo morando no .env.
Corrigindo
1. Troque a chave primeiro
Mudar o código não “desvaza” a chave. No painel do provedor, crie uma chave nova e apague a antiga. Faça isso primeiro, mesmo que você ache que ninguém a viu.
Aproveite e defina um limite de gasto mensal nos provedores de IA. Ele transforma um possível desastre num prejuízo com teto.
2. Guarde a chave nova como segredo do servidor
No Supabase, as Edge Functions leem segredos do ambiente. Adicione a chave no painel, em Edge Functions → Secrets, ou pela CLI:
supabase secrets set OPENAI_API_KEY=sk-your-new-keyO Lovable tem um lugar próprio para segredos e os pede quando uma integração precisa de um, em vez de colocá-los no código. Na Vercel ou na Netlify, use variáveis de ambiente sem o prefixo VITE_ ou NEXT_PUBLIC_, lidas só por funções de servidor.
3. Chame o serviço a partir de uma função no servidor
O navegador chama a sua função; a sua função chama o serviço com a chave secreta. Uma Edge Function mínima para um recurso de IA:
import { createClient } from 'npm:@supabase/supabase-js@2';
Deno.serve(async (req) => {
// 1. Only signed-in users may call this function.
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')! // public key: it only identifies the project
);
const token = (req.headers.get('Authorization') ?? '').replace('Bearer ', '');
const { data: { user } } = await supabase.auth.getUser(token);
if (!user) return new Response('Unauthorized', { status: 401 });
// 2. Accept only what the feature needs.
const { question } = await req.json();
if (typeof question !== 'string' || question.length > 2000) {
return new Response('Bad request', { status: 400 });
}
// 3. The secret key never leaves the server.
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: Deno.env.get('OPENAI_MODEL'),
max_tokens: 500,
messages: [{ role: 'user', content: question }]
})
});
const data = await response.json();
return Response.json({ answer: data.choices?.[0]?.message?.content ?? '' });
});No app, a chamada passa a ser supabase.functions.invoke('ask', { body: { question } }), e o cliente do Supabase envia junto o token do usuário logado.
4. Pagamentos: deixe o servidor decidir o preço
Na Stripe, mudar a chave de lugar não basta. Se o navegador diz à sua função quanto cobrar, alguém pode trocar o valor. O navegador deve mandar só o que está sendo comprado (o ID de um produto ou plano); o servidor busca o preço, cria a Checkout Session com a chave secreta e devolve o link. Depois, confirme os pagamentos por webhooks verificados com a assinatura da Stripe, nunca por uma página de “sucesso” que o usuário pode abrir direto.
Antes de cada publicação
- Procure os padrões acima no build.
- Mantenha segredos fora de qualquer variável com prefixo público.
- Quando a IA sugerir colocar uma chave no frontend “por enquanto”, peça uma função no servidor.
Se o seu app lida com pagamentos, recursos de IA ou dados pessoais, o nosso Security Check gratuito procura chaves expostas, funções abertas e webhooks sem assinatura, de fora e sem alterar nada, e envia por escrito os problemas mais graves.
Chaves de APIApps feitos com IASupabaseBolt
Continue lendo
Todos os artigos
Segurança de apps
Antes de lançar um app feito no Lovable: checklist de segurança
Quinze verificações antes de chegarem usuários e dados reais: regras do banco, chaves, storage, login, pagamentos, funções e backups. Quase todas em minutos.
4 min de leitura

Segurança de apps
Buckets públicos no Supabase Storage: os arquivos dos seus usuários estão expostos?
Avatares podem ser públicos; documentos, notas fiscais e contratos, não. Como revisar os buckets e as regras do Supabase Storage e corrigir sem quebrar nada.
4 min de leitura

Segurança de apps
Achou a chave secreta do Supabase no navegador? O que fazer na primeira hora
Uma chave service role ou secreta no frontend dá a qualquer pessoa acesso total ao banco. A ordem certa: revogar, substituir, olhar os logs e corrigir a causa.
5 min de leitura