Pular para o conteúdo

Seu app do Cursor é seguro?

É seguro fazer apps de produção com o Cursor? O código costuma rodar bem. Funcionar e estar protegido são testes diferentes, e só um deles roda sozinho.

Vlad Tkachenko5 min de leitura
O cartão de verificação de segurança da Reeve para apps do Cursor, com o logo do Cursor num ladrilho branco.

Os logotipos são propriedade de seus respectivos donos e são exibidos apenas para indicar compatibilidade.

Em resumo

  • Um app feito no Cursor costuma ser seguro de rodar. Se é seguro de expor é outro teste, e ninguém roda esse por você.
  • O código gerado responde à pergunta que você fez. Quais linhas um visitante pode ver é uma pergunta que pertence ao banco de dados.
  • O jeito habitual de publicar uma chave secreta: um refactor do servidor para o navegador e depois acrescentar NEXT_PUBLIC_ ou VITE_ para o erro sumir.

O Cursor te dá controle de verdade (o seu repositório, os seus arquivos, o seu deploy), e isso muda onde o risco fica. Você não está se perguntando o que um builder fez em seu nome. Você está revisando muito código que funciona, rapidamente, e decidindo o que ler com atenção.

Aqui está o que guia após guia erra: perguntar se a IA escreve código inseguro é a pergunta errada. Código gerado é escrito para atender o que você pediu. "Carregue os pedidos do usuário" é atendido por um código que carrega pedidos. Nada nessa frase diz de quem, então nada na resposta decide, e o lugar a que essa decisão pertence não é o arquivo que você está revisando.

Funcionar e estar protegido são dois testes diferentes

Só um deles roda sozinho.

Pense numa loja. O seu app é a vitrine: cada página que você constrói é entregue inteira a cada visitante, porque um navegador não desenha o que não lhe enviaram. O seu banco de dados é o estoque, um prédio separado na internet, com fechadura e endereço próprios.

Quando você roda o seu app e ele funciona, você testou a vitrine: as coisas certas aparecem nas telas certas, para você. Você não testou a fechadura. O estoque é alcançável direto, sem passar pela sua loja, e o fato de o seu app carregar direitinho não diz nada sobre o que ele devolve para quem pula a porta da frente.

Esse é o teste que nunca roda sozinho, em nenhum projeto, gerado ou escrito à mão. Fica mais fácil pular quando o código chega mais rápido do que você lê.

Onde as chaves dão errado num projeto do Cursor

Na mudança de servidor para navegador, quase sempre.

As duas se chamam chave de API. Só uma delas foi feita para ser lida.

Existem dois tipos de credencial e eles parecem quase iguais. Uma chave publicável nomeia o seu projeto e nada mais (sb_publishable_… nos projetos novos do Supabase, anon nos antigos), e foi feita para viver num navegador. Uma chave secreta, sb_secret_… ou a antiga service_role, ignora todas as regras que você escreveu e consegue ler e escrever em cada linha que você tem.

A sequência que publica uma delas é banal. Código que usava uma chave secreta no servidor é refatorado para um componente que roda no navegador. O valor volta como undefined, então a variável é renomeada com o prefixo que a ferramenta de build quer (NEXT_PUBLIC_ no Next.js, VITE_ no Vite), e o app começa a funcionar. A própria documentação do Vite é direta sobre o que esse prefixo faz: esses valores vão empacotados no seu código-fonte na hora do build.

O .gitignore não ajuda aqui. Ele governa o que entra no repositório, e a saída do build é gerada depois. Se você prefere ter certeza de qual chave é qual, existe uma conferência de um minuto.

A conferência que pertence ao banco de dados

Row Level Security, se os seus dados estão no Supabase, uma chave por tabela que decide linha a linha quem pode ler o quê.

O seu app e um estranho batem na mesma porta. A configuração decide quem entra, não as telas do seu app.

Essa é a resposta ao problema do "carregue os pedidos". Em vez de confiar que toda consulta do código vá filtrar direito, o banco se recusa a devolver linhas a que o visitante não tem direito, não importa o que a consulta dizia nem quem a escreveu. Uma regra, aplicada no único lugar por onde todo pedido tem que passar.

Dois detalhes decidem se você tem isso. O Supabase liga o Row Level Security por padrão nas tabelas criadas no Table Editor do painel, e não nas criadas rodando SQL, que é como um arquivo de migração as cria. E a configuração só liga a conferência; quem passa é a política por trás que decide, e uma política pode permitir todo mundo mesmo assim.

Como conferir o seu próprio projeto do Cursor em uns dez minutos

Procure na saída do seu build, não no código-fonte. Compile o app e depois procure nos arquivos gerados por service_role, sb_secret_ e sk_live_. Tudo que aparecer está publicado. Isso é mais rápido e mais honesto do que ler o fonte, porque é o que os visitantes realmente recebem.

Leia o seu arquivo de ambiente procurando prefixos. Toda variável NEXT_PUBLIC_ ou VITE_ é pública por projeto. Para cada uma, pergunte se você a imprimiria na sua página inicial.

Abra Authentication → Policies no Supabase. Qualquer tabela mostrando Row Level Security como desligado pode ser lida por quem tiver o endereço do seu projeto, que está dentro do seu app.

E então olhe de fora. O nosso scan gratuito faz esse último passo por você: ele lê o seu site no ar como um visitante e te dá uma nota em uns 20 segundos, sem precisar de conta: escaneie seu app.

O que fazer

  • Um app que funciona passou em um teste. Se o banco recusa um estranho é outro teste, e ninguém roda esse por você.
  • Código gerado responde à pergunta que você fez. "Quais linhas esta pessoa pode ver" é uma pergunta que pertence ao banco de dados.
  • O jeito comum de publicar uma chave secreta é um refactor do servidor para o navegador seguido de uma troca de prefixo.
  • O .gitignore protege o seu repositório, não a saída do seu build.
  • No Supabase, tabelas criadas rodando SQL começam sem Row Level Security, e ligar isso ainda deixa toda linha legível até que uma política diga o contrário.

Compile o seu projeto e procure service_role e sk_live_ na saída antes de qualquer outra coisa; leva um minuto e a resposta não deixa dúvida. Depois disso, o checklist de segurança de 10 minutos é o caminho mais curto pelo resto.

O que pode dar errado de verdade com um app criado com o Cursor

Nada disso significa que você fez algo errado: são os efeitos colaterais normais de deixar a IA escrever código rápido. Aqui está o que vale a conferida:

  • Uma chave secreta escrita direto no código

    Quando a IA conecta um serviço, às vezes coloca a chave direto no código para funcionar, e se esse código roda no navegador, qualquer um pode ler. Algumas chaves devem ser públicas e tudo bem; o Reeve lê o código carregado do seu app, encontra todas as chaves e diz quais são seguras e quais precisam ir para o servidor.

  • Um .env commitado ou uma pasta .git exposta

    As chaves devem viver em um arquivo .env que nunca é publicado. Mas é fácil commitar o .env por acidente, ou implantar a pasta oculta .git, de modo que todo o histórico, chaves incluídas, fica disponível para download. O Reeve verifica se qualquer um dos dois está acessível por fora.

  • Seu banco de dados deixado aberto (RLS desligado)

    Se o seu app guarda dados (muitas vezes no Supabase ou em outro Postgres), há uma regra (Row Level Security) sobre quem pode ler ou alterar cada linha. Se estiver desligada, suas tabelas podem ficar abertas para qualquer um que encontrar o endereço. É o problema sério mais comum, e é invisível a menos que você verifique.

  • Armazenamento de arquivos público

    Se o seu app aceita envios, eles vivem em “buckets” de armazenamento. Um bucket público significa que qualquer um pode listar ou baixar o que há dentro, então um arquivo privado pode acabar visível para todos. O Reeve verifica se os seus buckets são listáveis; ele nunca baixa os arquivos de ninguém.

  • Source maps deixados ligados

    Um “source map” revela o código original do seu app para qualquer um que olhar. Útil durante o desenvolvimento, mas em produção dá a estranhos uma cópia legível de como o seu app funciona e deixa outras brechas mais fáceis de achar. Vale organizar. O Reeve verifica se os seus estão expostos.

  • Cabeçalhos de segurança ausentes e endpoints abertos

    Pequenas configurações que dizem aos navegadores como proteger seus visitantes, além de se os seus endpoints de dados respondem a qualquer um ou a qualquer site. Pequenos sozinhos; juntos, somam. O Reeve sinaliza o que está faltando.

O que o Reeve é, e o que não é

O Reeve é uma verificação gratuita, somente leitura e por fora, como um inspetor que testa as portas sem entrar. É rápida e pega os erros comuns de grande impacto. Não é uma auditoria de segurança completa, e uma nota limpa não é garantia. Significa que as portas óbvias estão fechadas.

O Cursor é um editor, não uma hospedagem, então ele não implanta nem protege o seu app por você; mais disso recai sobre você e sobre o código que a IA produziu. As próprias ferramentas do Cursor podem ajudar a revisar o código conforme você avança, e se você usa Supabase o consultor dele sinaliza problemas de banco de dados. O que o Reeve acrescenta: uma visão de fora do app que você realmente publicou, em palavras simples com as quais você pode agir. E se você preferir não pensar nisso, podemos monitorar para você.

Quer que seja resolvido, não só verificado?

O Reeve Care continua monitorando seu app, faz backup dos seus dados e ajuda você a corrigir as coisas quando quebram, para que você siga criando em vez de se preocupar.

Conheça o Reeve Care

Perguntas frequentes

O código escrito pela IA do Cursor é seguro?

Pode ser um bom código, mas “escrito por IA” não significa “verificado quanto à segurança”. A IA otimiza para as coisas funcionarem, o que às vezes significa uma chave no lugar errado ou uma regra de banco de dados ausente. A única forma de saber é verificar o que está exposto. O Reeve faz isso de graça em cerca de 20 segundos.

Acho que commitei um arquivo .env. Isso é perigoso?

Pode ser, se o arquivo (ou a pasta oculta .git) estiver acessível no seu site implantado, porque ele pode conter chaves ativas. O Reeve verifica por fora se qualquer um dos dois pode ser baixado, para você saber se precisa rotacionar essas chaves.

Como sei se o meu app do Cursor está vazando chaves de API?

A causa habitual é uma chave escrita direto em código que roda no navegador. O Reeve lê o código carregado do seu app, encontra todas as chaves e diz quais são seguras de tornar públicas e quais precisam ir para o servidor, sem guardar os valores reais.

Verificar meu app vai mudar algo?

Não. O Reeve só olha o que já é público por fora. Ele nunca faz login, nunca muda nada e nunca baixa seus arquivos. Somente leitura, como conferir se uma porta está trancada sem entrar.

O Cursor escreve código inseguro?

Essa é a pergunta errada para qualquer assistente, inclusive um humano. Código gerado é escrito para atender o que você pediu, e "faça esta página carregar os pedidos" é atendido por um código que carrega todos os pedidos. Nada no pedido dizia quais, então nada na resposta decide isso. Seja qual for a forma do pedido, a regra sobre quem pode ler quais linhas tem que morar no banco de dados.

Meu arquivo .env está no .gitignore. Estou coberto?

Para o seu repositório, quase todo. Mas o .gitignore não tem efeito nenhum sobre o que a sua ferramenta de build publica. Uma variável com prefixo para o navegador (NEXT_PUBLIC_ no Next.js, VITE_ no Vite) é compilada dentro do JavaScript que os seus visitantes baixam, não importa onde ela estivesse guardada, e continua no seu histórico de versões se o arquivo já foi commitado antes de a regra existir.

Como confiro o que o meu app expõe de verdade, em vez de ler o código?

Carregue o seu próprio site, abra o DevTools do navegador e olhe a aba Rede enquanto a página carrega. Tudo que estiver ali é o que um visitante recebe. Ler assim leva alguns minutos e diz mais do que ler o código-fonte, porque é a mesma visão que alguém de fora tem.

Escrito por

Vlad Tkachenko

Fundador da Reeve

Passo meus dias olhando apps criados com Lovable, Bolt, v0, Cursor e Replit, e a curta lista de erros que aparecem neles sem parar.

Mais sobre o autor

Criou em outro lugar? Temos o mesmo resumo honesto para:

← Ver todos os guias de segurança dos criadores

Verificação externa automatizada, não uma auditoria completa. A ausência de achados não é garantia de segurança.