Lançar depressa é ótimo, mas há uma lista curta de coisas que vale a pena rever antes de abrires a tua app ao mundo. Nenhuma exige ser especialista em segurança, e todas se verificam por fora em dois minutos. Este guia percorre cada ponto com três coisas: porque importa, como o verificares tu mesmo e como o corrigir, com exemplos de configuração para as stacks que as apps feitas com IA mais usam (Next.js na Vercel, Supabase, Firebase). No fim tens a versão de dois minutos para colares na tua lista de lançamento.
Como os atacantes encontram isto em minutos
A maioria das brechas em apps feitas com IA não são hacks engenhosos. Alguém abre o teu site, carrega em F12, lê o JavaScript que a tua app já enviou para o browser dele e copia um URL que a tua app já chama. Os scanners automáticos fazem o mesmo em escala, batendo em caminhos comuns como /.env ou /.git em milhares de sites por dia sem sequer saberem que existes. Tudo o que vem a seguir é algo que eles conseguem verificar sem qualquer acesso ao teu código, e é precisamente por isso que deves verificá-lo primeiro.
1. Nenhum segredo no frontend
Porque importa. As chaves de API e os tokens pertencem só ao servidor. Quando um assistente de IA "liga" um serviço, muitas vezes mete a chave diretamente no código do cliente, onde qualquer pessoa a lê nas DevTools. Uma chave sk_live_ do Stripe fugida move dinheiro real; uma chave service_role do Supabase entrega a tua base de dados inteira; uma chave da OpenAI ou da Anthropic deixa-te a pagar a fatura de outra pessoa.
Como verificar. Abre o teu site, carrega em F12 → separador Sources (ou Network filtrado por JS) e procura nos ficheiros strings como sk_live, service_role, AKIA, sk-ant, AIza ou -----BEGIN. Se a tua framework usa variáveis com prefixo público (NEXT_PUBLIC_, VITE_, NUXT_PUBLIC_), confirma que nenhuma guarda um segredo: esse prefixo significa literalmente "isto vai para o browser".
Como corrigir. Passa todos os segredos para variáveis de ambiente do servidor e faz a chamada a partir de uma API route ou função serverless; o browser fala com o teu servidor, nunca com o fornecedor. E roda a chave fugida: depois de ter estado num bundle público, trata-a como comprometida mesmo depois de a removeres. Mais em os segredos que a tua app deixa fugir no browser.
2. HTTPS e headers de segurança
Porque importa. Serve tudo por HTTPS e redireciona o HTTP para lá, para que ninguém consiga ler ou alterar o tráfego. Depois acrescenta os headers que os browsers usam para defender os teus utilizadores: Content-Security-Policy para conter injeções, Strict-Transport-Security para fixar o HTTPS, X-Frame-Options para bloquear clickjacking e X-Content-Type-Options para impedir o browser de "adivinhar" tipos de ficheiro. A maioria das apps geradas sai sem nenhum deles por defeito.
Como verificar. Pede o teu site com curl -I https://oteudominio.com e olha para os headers que voltam, ou usa o verificador gratuito de headers de segurança.
Como corrigir. No Next.js declaras-os em next.config.js; na Vercel, para qualquer framework, em vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}
A CSP merece um momento à parte: começa em modo Content-Security-Policy-Report-Only, vê o que bloquearia e passa-a a ativa quando já não partir nada. Vê os headers de segurança HTTP explicados.
3. Regras da base de dados (RLS) em todas as tabelas
Porque importa. Se usas Supabase ou Firebase, a tua app fala com a base de dados diretamente a partir do browser, por isso as regras da base de dados são a única coisa entre um visitante e os teus dados. Sem elas, qualquer pessoa com a chave pública lê e escreve nas tuas tabelas sem iniciar sessão: exatamente a falha por trás da vulnerabilidade de RLS do Lovable.
Como verificar. Com a app aberta, copia uma chamada a /rest/v1/ do separador Network e abre-a numa janela anónima. Se devolver dados sem sessão, estás exposto. No Supabase, o Table Editor marca as tabelas com uma etiqueta vermelha "RLS disabled". No Firebase, confirma que as regras não continuam em modo de teste (allow read, write: if true ou com uma data de validade).
Como corrigir. Ativa o Row-Level Security em todas as tabelas com uma política de negar por defeito e escreve regras por operação ligadas ao utilizador. No Supabase, o mínimo para uma tabela com uma coluna user_id:
alter table public.items enable row level security;
create policy "items: só as próprias linhas" on public.items
for all to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);
E nunca confies em esconder um botão na interface: o pedido continua a existir.
4. Nenhum ficheiro sensível exposto
Porque importa. Um único pedido a /.env pode entregar todos os segredos que a tua app usa; /.git/config permite a qualquer pessoa descarregar o teu repositório inteiro; source maps publicados permitem reconstruir o teu código original; um backup.sql esquecido é a tua base de dados num ficheiro.
Como verificar. Experimenta oteudominio.com/.env, /.git/HEAD, /.DS_Store, /backup.sql no browser, e abre um ficheiro JS do teu bundle para ver se termina numa linha //# sourceMappingURL= a apontar para um .map acessível. Em plataformas como a Vercel ou a Netlify o .env nunca é publicado, mas num VPS com nginx ou Apache acontece.
Como corrigir. Bloqueia os dotfiles no servidor (no nginx, location ~ /\. { deny all; }), desativa os source maps em produção (productionBrowserSourceMaps: false no Next.js, build.sourcemap: false no Vite) e tira os backups da pasta pública.
5. CORS bem fechado
Porque importa. Uma política de CORS que reflete qualquer origem com credenciais permite a um site malicioso ler os dados dos teus utilizadores usando a sessão deles. Access-Control-Allow-Origin: * sem credenciais é inofensivo para dados públicos; o perigo é devolver a origem que pede, seja ela qual for, e acrescentar Access-Control-Allow-Credentials: true.
Como verificar. Pede um dos teus endpoints de API com curl -I -H "Origin: https://evil.example" https://oteudominio.com/api/qualquercoisa. Se a resposta devolver essa mesma origem em Access-Control-Allow-Origin mais Allow-Credentials: true, tens o problema.
Como corrigir. Mantém uma lista fechada de origens permitidas (os teus domínios de produção e, no máximo, o de preview) e compara com ela; qualquer outra origem não recebe header nenhum.
6. Cookies e sessões bem configuradas
Porque importa. As cookies de sessão devem levar Secure (só HTTPS), HttpOnly (ilegíveis a partir do JavaScript, para que um XSS não as roube) e SameSite=Lax ou Strict (defende contra CSRF). São uma linha de configuração e fecham uma classe inteira de bugs de roubo de contas.
Como verificar. F12 → Application → Cookies e olha para as colunas Secure, HttpOnly e SameSite da tua cookie de sessão. Se usas um fornecedor de auth (Supabase Auth, Clerk, NextAuth) costumam sair bem; as que falham são as cookies que a tua própria app acrescenta.
Como corrigir. Ao definir a cookie: Set-Cookie: session=…; Secure; HttpOnly; SameSite=Lax; Path=/. No Express, res.cookie(name, value, { secure: true, httpOnly: true, sameSite: 'lax' }).
7. Dependências com vulnerabilidades conhecidas
Porque importa. A tua app arrasta centenas de pacotes. Uma versão vulnerável de uma biblioteca que processa input do utilizador é uma porta de entrada que não escreveste mas que é tua na mesma.
Como verificar e corrigir. Corre npm audit no projeto e resolve primeiro os resultados críticos e altos; ativa o Dependabot ou o Renovate no repositório para que os patches venham ter contigo. Se o teu site expõe um package.json público, também estás a anunciar as tuas versões.
8. Limites de pedidos nos endpoints que custam dinheiro ou abrem portas
Porque importa. O formulário de login, o registo, o envio de emails e qualquer endpoint que chame uma API de IA paga precisam de um limite por IP ou por conta. Sem isso, um script tenta milhares de passwords ou acumula uma fatura de tokens durante a noite.
Como corrigir. Um rate limit simples no servidor (por IP e por minuto) e, nos fornecedores pagos, um teto de gastos configurado no painel deles. Os fornecedores de auth costumam vir com limites de tentativas já ativos: confirma que não os desativaste.
9. Erros que não contam de mais
Porque importa. Uma página de erro com o stack trace completo, a consulta SQL ou o caminho do servidor é um mapa para quem está a atacar. O mesmo vale para headers como X-Powered-By que anunciam versões exatas.
Como corrigir. Páginas de erro genéricas em produção, com o detalhe só nos teus logs. Remove o X-Powered-By (no Next.js, poweredByHeader: false).
10. Domínio e email prontos para utilizadores reais
Porque importa. Se envias email (confirmações, recuperação de password), sem SPF, DKIM e DMARC vai parar ao spam ou, pior, qualquer pessoa vai poder enviar emails a fazer-se passar pelo teu domínio. E um certificado ou domínio a caducar deita o site inteiro abaixo.
Como verificar e corrigir. Publica registos SPF e DMARC no DNS, ativa o DKIM no teu fornecedor de envio e liga a renovação automática do domínio e do certificado. Meia hora de trabalho que evita o pior dia possível.
Por que ordem corrigir se tens uma hora
- Primeiro, segredos no frontend e regras da base de dados: as duas falhas que entregam dados reais a qualquer pessoa.
- Depois, ficheiros expostos e CORS: baratos de corrigir e muito sondados pelos scanners automáticos.
- A seguir, headers, cookies e páginas de erro: reforçam o que já funciona.
- Por fim, dependências, limites de pedidos e email: menos urgentes no dia do lançamento, essenciais na semana seguinte.
A tua checklist de 2 minutos antes de lançar
- Nenhum
sk_live_,service_roleou chave privada no teu JavaScript; variáveis públicas revistas. - HTTPS forçado, com HSTS, X-Frame-Options, X-Content-Type-Options e uma CSP pelo menos em modo de relatório.
- Row-Level Security (ou regras do Firebase) em todas as tabelas; o teste anónimo devolve vazio.
.env,.git, backups e source maps inacessíveis.- CORS limitado às tuas próprias origens, nunca a devolver a origem com credenciais.
- Cookies com Secure, HttpOnly e SameSite.
npm auditlimpo de resultados críticos e altos.- Limites de tentativas no login, no registo e nos endpoints de IA; tetos de gastos nos fornecedores.
- Páginas de erro sem traces; sem
X-Powered-By. - SPF, DKIM e DMARC publicados; renovação automática do domínio e do certificado.
Despacha isto de uma vez
Em vez de verificares tudo isto à mão, corre o Scanaris: verifica estes pontos e mais uns 40 no teu site em produção em 30 segundos, ordena os resultados por impacto e dá-te um prompt pronto a colar para corrigir cada um com a tua IA, antes que outra pessoa os encontre. Ativa a monitorização e avisa-te quando alguma coisa desta lista voltar a partir depois do lançamento.
Perguntas frequentes
Isto substitui uma auditoria de segurança profissional?
Não. Esta lista cobre o que se consegue verificar por fora e o que falha em quase todas as apps feitas com IA. Uma auditoria revê também a tua lógica de negócio, as permissões entre utilizadores e o próprio código. Mas sem esta lista, a auditoria começaria pelos mesmos pontos.
Quanto tempo demora tudo isto?
Verificar: dez minutos com um scanner ou meia hora à mão. Corrigir: entre uma tarde e um dia, consoante quantos pontos falham; os segredos e o RLS são os que demoram mais porque obrigam a passar código para o servidor.
E depois do lançamento?
Repete a lista sempre que a IA gerar uma funcionalidade nova que toque em dados ou chaves, e configura uma nova análise automática semanal: as apps partem-se por causa de alterações, não por causa do tempo.