← todos os posts

O teste das duas contas: abra duas, tente ver o dado da outra, e descubra em 10 minutos se seu app vaza

Trocar o número no endereço pega um vazamento. Faltam outros cinco. O roteiro completo com duas contas, uma folha de papel e dez minutos.

"IDOR básico: usuário A acessa dados do usuário B só mudando um ID na URL."

Está numa lista de falhas comuns em app feito com IA que circulou entre programadores brasileiros. IDOR é o nome técnico; a tradução é "trocar um número no endereço e ver o dado de outra pessoa". A frase é certa e, pra quem não é da área, não serve pra nada. Na mesma discussão sobre segurança, apareceu outra: "quem nunca estudou isso não sabe o que não sabe".

Hoje é sobre transformar a primeira frase em coisa que você faz, e a segunda em coisa que você passa a saber.

Já publiquei a versão de cinco minutos: crie duas contas, copie o endereço de um pedido da conta A, cole logado como B. Ela pega o caso clássico, o número no endereço. Só que o dado de um cliente tem pelo menos mais cinco caminhos pra aparecer na tela de outro, e nenhum deles passa pelo endereço. Este post é o roteiro completo: duas contas, uma folha de papel, dez minutos.

Por que a IA não pega isso sozinha

Um programador contratado pra consertar um sistema feito no vibe coding (o jeito de construir pedindo pra IA, sem escrever código) descreveu assim o que encontrou:

"Sistema que só funcionavam usando uma conta específica. Qualquer outra conta retornava erro."

Repare no avesso disso. O sistema foi testado com uma conta. A sua também, aposto. Você cria a conta, cria um pedido, vê o pedido, fica feliz. Com uma conta só, todo dado que aparece na tela é seu mesmo, e a pergunta "esse dado é de quem está olhando?" nunca aparece.

A IA testa igual. Ela confere o caminho feliz: login funcionou, pedido salvou, lista mostrou. Não é preguiça dela nem burrice sua. É que a falha só existe quando tem duas pessoas, e ninguém pôs a segunda pessoa no teste.

O caso que virou registro oficial

Em março de 2025, o engenheiro Matt Palmer achou essa falha num app feito no Lovable. Escreveu um programa que visitou 1.645 apps da vitrine pública da plataforma e encontrou 170 (cerca de 10%) com 303 pontos de acesso devolvendo dado que não deviam: e-mail, nome, telefone, assinatura, pagamento. A falha virou registro público de vulnerabilidade, o CVE-2025-48757, publicado em 29 de maio de 2025.

O que esse número não prova: não é a taxa de falha de todo app feito com IA, é a de uma vitrine, num mês de 2025. E Palmer só olhou a página inicial, sem fazer login. Ele mesmo escreveu que a parte logada provavelmente expunha mais, e não mediu.

O detalhe que me interessa é outro. O verificador de segurança que o Lovable lançou em seguida, segundo Palmer, "só checa se existe alguma regra, não se ela está correta". Ter regra e ter a regra certa são coisas diferentes. Nenhum botão de "verificar segurança" sabe o que é certo pro seu negócio. O teste das duas contas sabe, porque ele não lê a regra: ele tenta passar por ela.

Antes de começar: o preparo (2 minutos)

  1. Dois navegadores. Um normal e uma janela anônima (Ctrl+Shift+N no Chrome, Cmd+Shift+N no Mac). Cada um guarda um login diferente.
  2. Conta A e conta B, com e-mails diferentes. Use dois e-mails seus.
  3. Uma marca. Logado como A, crie um item (pedido, cliente, anotação, o que o seu app guarda) e escreva num campo de texto uma palavra que não existe em mais lugar nenhum: ZEBRA77. Se o app aceita anexo (foto, PDF), anexe um.
  4. Uma folha de papel com seis linhas numeradas. Cada linha vai ganhar um ✓ ou um ✗.

Faça isso no app publicado, com dados de teste. Nunca no app de outra pessoa: o teste é no que é seu.

Os seis testes

1. O endereço (1 minuto)

O da versão curta. Como A, abra o item e copie o endereço da barra, algo como meuapp.com.br/pedido/1043. Como B, cole. Tem que dar "não encontrado" ou "sem permissão". Se o pedido de A aparecer, ✗.

2. A lista e a busca (1 minuto)

Como B, abra toda tela que mostra lista: pedidos, clientes, painel, histórico. Use a busca do app e procure ZEBRA77.

B não pode achar nada. E repare que o teste 1 não pega esse caso: o endereço está protegido, mas a lista puxa "todos os pedidos" e não "os pedidos de quem está logado".

3. Editar e apagar (2 minutos)

Ver é ruim. Mudar é pior. Como A, abra o item e clique em editar; se o endereço mudar (/pedido/1043/editar), copie. Como B, cole e tente salvar uma alteração.

Volte pra janela de A e recarregue. O item mudou? ✗. Se o app tiver botão de apagar, repita com um segundo item de teste de A. Só com dado de teste, claro.

4. O anexo (1 minuto)

Como A, abra a foto ou o PDF que você anexou, clique com o botão direito, "copiar endereço da imagem" (ou do link). Cole numa terceira janela anônima, sem login nenhum.

Abriu? ✗. Aqui não precisa nem ser cliente: qualquer um com o link vê. É comum porque, no Supabase (o banco que fica por trás do Lovable e de muita outra ferramenta), arquivo vive num "balde", e a própria documentação diz que num balde público "qualquer um que tenha o endereço do arquivo consegue acessá-lo", e que isso "contorna os controles de acesso" pra baixar. A regra que você escreveu pro banco não vale pro arquivo. Documento, comprovante e foto de cliente não podem morar em balde público.

5. O que chega no navegador sem aparecer na tela (2 minutos)

Este é o que quase ninguém faz, e é o que mais me preocupa.

A tela mostra o que o app escolhe mostrar. Mas o que o seu navegador recebeu pode ser mais. Tem app que pede ao banco "todos os pedidos" e só depois filtra na tela os do usuário. Visualmente, perfeito. Por baixo, o pedido de A chegou no computador de B.

Pra ver, como B: aperte F12 (no Mac, Cmd+Option+I). Abre o painel de ferramentas do navegador. Clique na aba Rede (Network, se estiver em inglês). Recarregue a tela de lista. Com o painel aberto, aperte Ctrl+F (Cmd+F no Mac) e procure ZEBRA77.

Essa busca olha tudo que o servidor mandou, não só o que apareceu. Achou? ✗. O dado de A está saindo pra B, só não está sendo exibido. Você não invadiu nada: olhou o que o seu próprio app entregou no seu próprio navegador.

6. O que sai do app (1 minuto)

Exportar planilha, gerar relatório, PDF de resumo, e-mail automático. Se existir, rode como B e procure ZEBRA77 no arquivo. Exportação costuma ser escrita depois, às pressas, e a regra de quem-vê-o-quê fica pra trás.

Leia a folha

Seis ✓: o seu app separa um cliente do outro nesses seis caminhos. Não quer dizer que ele está seguro em tudo. Quer dizer que a falha mais comum não está nele hoje.

Algum ✗? Agora você tem uma coisa que não tinha antes: o problema com nome e endereço. E o pedido pra IA tem que ter os dois. "Melhora a segurança" não serve. Assim serve:

Falhou O pedido
1 ou 3 "No servidor, antes de mostrar, alterar ou apagar um pedido, confira se ele pertence ao usuário logado. Se não pertencer, responda com erro de permissão."
2 ou 6 "A lista, a busca e a exportação de pedidos devem trazer só as linhas cujo dono é o usuário logado. A regra fica no banco, não na tela."
4 "Mova os anexos de clientes pra um balde privado e gere links temporários só pro dono do arquivo."
5 "A consulta da tela de lista está trazendo pedidos de outros usuários e filtrando na tela. Faça o filtro no banco, com regra de acesso por linha."

Um pedido de cada vez. Depois de cada um, refaça o teste daquela linha, você, nas duas janelas. "Pronto, corrigido" não é ✓. ✓ é você olhando a janela de B e não vendo a zebra.

Se o seu app usa Supabase, uma coisa da semana: o Supabase está mudando um padrão. Tabela nova deixou de nascer acessível pela internet em projetos novos desde 30 de maio, e a mudança chega aos projetos antigos em 30 de outubro de 2026. Bom. Mas o próprio aviso diz que "o comportamento do RLS continua o mesmo". RLS é a regra por linha do banco, a que diz "cada linha tem dono e só o dono lê". Ou seja: a regra que decide qual cliente vê qual linha continua sendo a que você escreve. E quando a tabela nova der erro de permissão, a tentação da IA vai ser liberar geral pra "funcionar". Depois de qualquer correção desse tipo, o teste das duas contas de novo.

Quando refazer

A folha não vai pro lixo. Refaça os seis testes sempre que:

  • a IA mexer em login, cadastro ou banco de dados;
  • aparecer tela nova com lista, busca ou exportação;
  • você trocar de plataforma ou de banco.

Dez minutos. Menos que um café com um cliente explicando por que ele viu o pedido do outro.

O que isso era, na parede inteira

Este é um teste da fase que eu chamo de Estruture: o portão dela pede regras testadas e login que protege, e o teste das duas contas é como você prova a segunda coisa sem ler uma linha de código. Mas ele vem depois de outras: o app precisa estar num banco que é seu, com teste separado do de verdade, e com um ponto de retorno se a correção quebrar outra coisa. E tem vizinhos que ele não cobre: a área de admin que só esconde o botão, a chave secreta que foi parar no navegador, o app inteiro aberto pra quem nem fez login.

Uma folha com seis linhas resolve uma parede. O app tem várias, e elas têm ordem.

Fontes