Vibe coding e segurança de dados: como auditar sua própria aplicação antes que alguém faça por você

Vibe coding e segurança de dados: como auditar sua própria aplicação antes que alguém faça por você

. 10 min read

Sua IA escreveu o código. Subiu rápido. Funcionou. Agora vem a parte que ninguém te ensina: descobrir o que ficou aberto.

Tem uma frase circulando entre desenvolvedores que resume o momento atual: "Eu não escrevo mais código, eu converso com a IA até a aplicação existir". É o tal do vibe coding — termo popularizado por Andrej Karpathy em 2025 — onde você descreve a ideia, a IA gera o código, você ajusta, ela ajusta, e em poucas horas tem um produto rodando.

E funciona. Eu mesmo já tirei MVP do papel num fim de semana usando Cursor + Claude. O problema não é a velocidade. O problema é o resíduo invisível que esse processo deixa.

Linhas de código em tela escura

O .env que ficou no repo público. A chave de API hardcoded num arquivo de teste que ninguém apagou. O endpoint admin sem autenticação. A pasta /uploads listável. O wp-config.php.bak que o editor criou e o deploy levou junto.

Esses problemas não são novos. O que é novo é a escala. Quando você delega geração de código pra uma IA e move rápido, certos hábitos de segurança simplesmente nunca entram no fluxo. Como o resultado funciona, ninguém volta pra checar.

💭 Esse artigo é sobre auditar sua própria aplicação com as mesmas ferramentas que um atacante usaria. Não é sobre invadir o site dos outros. É sobre olhar o seu antes que alguém olhe.


⚖️ Antes de qualquer coisa: o aviso que ninguém pode pular

🚨 AVISO LEGAL

Tudo que vou mostrar aqui é pra ser usado em uma de duas situações:

  1. Sua própria aplicação — código seu, infra sua, conta sua.
  2. Aplicação de terceiro com autorização explícita por escrito — contrato de pentest, programa de bug bounty público (HackerOne, Bugcrowd, Intigriti).

Rodar essas ferramentas contra sites aleatórios é crime no Brasil — invasão de dispositivo informático (art. 154-A do CP), pena de até 2 anos. Use no seu ambiente.

Dito isso, vamos ao que interessa.


🐉 O ambiente: Kali Linux num container

Terminal Linux com código verde

Você não precisa instalar Kali na sua máquina principal. Eu rodo num container Docker, isolado, que sobe quando preciso e fica desligado o resto do tempo.

# Sobe o container
docker run -it --rm \
    -v $(pwd)/data:/root/data \
    kalilinux/kali-rolling /bin/bash

# Dentro dele:
apt update
apt install -y wpscan nikto nmap whatweb gobuster metasploit-framework
msfdb init

Pronto. Laboratório portátil. Se quiser interface gráfica acessível pelo navegador (útil pra Burp Suite), dá pra adicionar XFCE + noVNC, mas pra varredura de linha de comando o terminal basta.


🔍 Reconhecimento: o que sua aplicação está dizendo pro mundo

Antes de "scanear vulnerabilidades", o passo zero é descobrir o que está exposto. E aqui mora a primeira surpresa de quem fez vibe coding: muito mais coisa do que você imagina.

whatweb — quem você é, na real?

Em segundos, ele te diz o que está rodando no servidor. Cada informação é uma chave que um atacante usa pra correlacionar com CVEs.

$ whatweb https://meusite.com

Output típico:

https://meusite.com [200 OK]
  Apache[2.4.41]
  Cookies[wordpress_test_cookie]
  HTTPServer[Apache/2.4.41 (Ubuntu)]
  JQuery[3.6.0]
  MetaGenerator[WordPress 6.4.2]   ← versão exposta
  PHP[8.1.2]                        ← versão exposta
  WordPress[6.4.2]                  ← versão exposta
  X-Powered-By[PHP/8.1.2]           ← versão exposta

⚠️  4 informações sensíveis vazando em headers

Se sua app vibe-coded está vazando "Powered by Express 4.16.0" no header, você sabe que precisa esconder isso (app.disable('x-powered-by')). É uma linha que ninguém te lembrou de colocar.

gobuster — as portas que você esqueceu de fechar

Esse aqui é o que mais expõe descuido em projeto vibe-coded. Ele faz bruteforce de diretórios e arquivos baseado em wordlists.

gobuster dir -u https://meusite.com \
    -w /usr/share/wordlists/dirb/common.txt \
    -x php,html,txt,bak,old,zip,env,git

Output real do que ele encontra em apps inseguras:

═══════════════════════════════════════════════════
  Gobuster v3.6 — varredura iniciada
═══════════════════════════════════════════════════

/.env                  (Status: 200) [Size: 412]      🔥 CATÁSTROFE
/.git/config           (Status: 200) [Size: 92]       🔥 REPO INTEIRO ACESSÍVEL
/admin                 (Status: 200) [Size: 2841]     ⚠️  sem auth?
/backup.zip            (Status: 200) [Size: 8412334]  ⚠️
/config.php.bak        (Status: 200) [Size: 1284]     ⚠️
/phpinfo.php           (Status: 200) [Size: 71028]    ⚠️
/uploads/              (Status: 301) [Size: 178]      ⚠️  listável
/test                  (Status: 200) [Size: 412]      ⚠️
/wp-config.php.old     (Status: 200) [Size: 3211]     ⚠️

Progress: 4614 / 4614 (100.00%)
⚠️  9 endpoints suspeitos encontrados

😱 "Mas como o .env ficou acessível?"

O dev nunca pensou que https://app.com/.env era acessível porque "tá na pasta do servidor, ué". Tá. E o servidor serve a pasta inteira. É exatamente assim que vaza.

O que o atacante encontra dentro do .env

Quando ele baixa esse arquivo, vê algo parecido com isso:

# 📄 .env recém-baixado de https://meusite.com/.env
# ────────────────────────────────────────────────

# Database
DB_HOST=db.meusite.com
DB_USER=admin
DB_PASSWORD=P@ssw0rd_Production_2024!
DB_NAME=main_production

# API Keys
OPENAI_API_KEY=sk-proj-aB3kK9...M2pQrXyZ
STRIPE_SECRET_KEY=sk_live_51M8d2K...yT9nQ4w
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7M...EXAMPLEKEY

# Auth
JWT_SECRET=muito_secreto_123_nao_compartilhar
SESSION_SECRET=qwerty12345

# SMTP
SMTP_PASSWORD=EmailM4ster99

Em 30 segundos um desconhecido tem:

  • 🗄️ Acesso total ao seu banco
  • 💳 Sua chave Stripe pra fazer transações
  • 🤖 Sua chave OpenAI pra queimar créditos
  • ☁️ Suas credenciais AWS pra subir instâncias na sua conta

Tudo de graça. Tudo porque um arquivo de 412 bytes ficou acessível.

A correção é simples (e ninguém faz)

No nginx, bloqueia explicitamente arquivos sensíveis:

# /etc/nginx/sites-available/meusite.conf

location ~ /\.        { deny all; }
location ~ \.(env|bak|old|zip|sql|log)$   { deny all; }
location ~ /\.git     { deny all; }

# Proteção extra para WordPress:
location ~* /(?:uploads|files)/.*\.php$   { deny all; }

Boa prática: nunca subir .env pro servidor de produção. Variáveis de ambiente vão direto no painel da hospedagem, no Docker, no systemd — em qualquer lugar que não seja arquivo dentro do webroot.


🔌 WPScan — pra quando seu vibe coding virou WordPress

WordPress dashboard

Boa parte das aplicações que vejo serem montadas rapidinho começa como WordPress + alguns plugins + um tema gratuito. E aí entra o WPScan, ferramenta dedicada ao ecossistema WP.

Pega uma API key gratuita em wpscan.com (necessária pra checar vulnerabilidades) e roda:

wpscan --url https://meusite.com \
    --enumerate vp,vt,u \
    --api-token SEU_TOKEN

Onde:

Flag O que enumera
vp Plugins vulneráveis
vt Temas vulneráveis
u Usuários do WP

Output real:

[i] Target URL: https://meusite.com/

[+] WordPress version 6.2.1 (INSEGURA, lançada 2023-05-16)
    | Vulnerável a 8 vulnerabilidades conhecidas

[+] WordPress theme: astra v4.1.0

[!] PLUGIN VULNERÁVEL: contact-form-7
    | Versão: 5.7.1
    | Última: 5.9.2
    | CVE-2023-6449 — Stored XSS via file upload
    | Severidade: HIGH (8.1)
    | Fix: atualizar para 5.7.4+

[!] PLUGIN VULNERÁVEL: elementor
    | Versão: 3.5.2
    | CVE-2023-48777 — Authenticated File Upload
    | Severidade: CRITICAL (9.8)

[!] USUÁRIOS IDENTIFICADOS:
    | admin       (mensagem de erro de login + author archive)
    | joao        (author archive)
    | marketing   (author archive)

────────────────────────────────────────
⚠️  2 plugins vulneráveis · 3 usuários enumerados

💡 O que fazer com esse output?

Cada CVE listada tem severidade e correção. "Plugin X versão Y → atualize pra Z". É ouro: em três comandos você sabe exatamente o que está furado.

A enumeração de usuários (-u) é especialmente perigosa — se o WP retorna usuários válidos, o atacante já tem metade do bruteforce pronto.


🛠️ Nikto — o velho de guerra que ainda funciona

Nikto é de 2001 e segue extremamente útil. Varre o servidor procurando configurações inseguras, arquivos perigosos, headers ausentes, versões desatualizadas.

nikto -h https://meusite.com -o relatorio.html -Format html

Tipo de coisa que ele acha em apps vibe-coded:

+ Server: Apache/2.4.41 (Ubuntu)

+ ❌ X-Frame-Options header NÃO está setado.
    └─ Permite clickjacking

+ ❌ X-Content-Type-Options header NÃO está setado.
    └─ Permite MIME sniffing attacks

+ ❌ Strict-Transport-Security header NÃO setado.
    └─ Permite downgrade pra HTTP

+ ⚠️  Cookie PHPSESSID criado sem flag httponly.

+ ⚠️  Métodos HTTP permitidos: GET, HEAD, POST, OPTIONS, PUT, DELETE
    └─ PUT e DELETE expostos sem auth

+ ❌ /readme.html: arquivo default do Apache
+ ❌ /phpinfo.php: PHP information disclosure
+ ⚠️  /uploads/: directory indexing habilitado
+ ❌ /admin/: página admin acessível

────────────────────────────────────────
⚠️  6 issues HIGH · 3 issues MEDIUM

Cada uma dessas linhas é uma classe de ataque que você está deixando aberta. X-Frame-Options ausente vira clickjacking. HSTS ausente vira downgrade pra HTTP. PUT/DELETE abertos viram qualquer coisa.

⚠️ Cuidado com Nikto em produção.

Ele é barulhento — faz milhares de requests rapidamente. Não rode contra produção sem avisar antes, ou use rate limiting. Em staging é tranquilo.


🔐 Procurando segredos vazados: o pesadelo das chaves de API

Cofre antigo com chave

Aqui chegamos ao tema mais doloroso da era vibe coding. Modelos de IA são treinados em código público — e às vezes deixam exemplos com chaves placeholder que parecem placeholders mas o dev esqueceu de trocar. Ou pior: a IA sugere colocar a chave direto no frontend.

trufflehog — caça-segredos no seu próprio repo

Antes mesmo de subir nada, rode no seu repositório:

docker run --rm -v "$PWD:/repo" \
    trufflesecurity/trufflehog:latest \
    filesystem /repo --only-verified

Output quando algo é encontrado:

🐷🔑🐷  TruffleHog. Unearth your secrets.

══════ Found verified result ══════
Detector Type: OpenAI
File:         ./src/lib/ai.js
Line:         14
Verified:     ✅ true
Raw:          sk-proj-aB3kK9...M2pQrXyZ

══════ Found verified result ══════
Detector Type: AWS
File:         ./scripts/deploy.sh
Line:         7
Verified:     ✅ true
Raw:          AKIAIOSFODNN7EXAMPLE

══════ Found verified result ══════
Detector Type: Stripe
File:         ./.env.example
Line:         12
Verified:     ✅ true
Raw:          sk_live_51M8d2K...yT9nQ4w

────────────────────────────────────────
⚠️  3 segredos VERIFICADOS no repositório
⚠️  Todos ainda funcionando contra a API real

A flag --only-verified é importante: ela pega apenas segredos que o TruffleHog conseguiu validar com a API correspondente. Sem isso, vem muito falso positivo. Com ela, se aparece resultado, é real e é urgente.

🚨 Achou um segredo vazado? Protocolo de emergência

1️⃣ Revogue a chave imediatamente
No painel do serviço. Não "rotacione depois", revogue agora. Se já foi pro repo público, considere comprometida desde o segundo zero.

2️⃣ Gere uma nova e atualize as variáveis de ambiente
Direto no painel da hospedagem (Vercel, Hostinger, AWS, Heroku). Nunca em arquivo dentro do projeto.

3️⃣ Audite o histórico do Git

git log --all -p | grep -i "trecho_da_chave"

Se já foi commitada em algum momento, ela está pra sempre acessível em forks e clones.

4️⃣ Limpe o histórico (BFG ou git-filter-repo)
Reescrever histórico é dor de cabeça com colaboradores, mas necessário. Avise o time antes.

5️⃣ Revise logs de uso do serviço
Stripe, OpenAI, AWS — todos têm logs de uso por chave. Veja se houve uso suspeito antes da revogação.

gitleaks — proteção em pre-commit

Pra que isso não aconteça de novo, instala o gitleaks como hook de pre-commit:

# Na raiz do repo:
echo '#!/bin/sh
gitleaks protect --staged --verbose' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

Quando você tentar commitar uma chave:

$ git add .env
$ git commit -m "add api keys"

○ gitleaks pre-commit hook

╭───────────── leak detected ─────────────╮
│ Finding:  OPENAI_API_KEY=sk-proj-...    │
│ Secret:   sk-proj-aB3kK9...M2pQrXyZ     │
│ RuleID:   openai-api-key                │
│ File:     .env                          │
│ Line:     4                             │
╰─────────────────────────────────────────╯

✗ commit aborted: 1 leak found

Bundlers vazando segredos no frontend

Se sua app já está em produção, vale procurar segredos no JavaScript bundleado. Bundlers às vezes empacotam variáveis de servidor por engano:

$ curl -s https://meusite.com/static/js/main.js \
    | grep -E "sk_live|AKIA|AIza|ghp_"

apiKey:"AIzaSyB-X9pT...1qWeRtY"   ← Google API exposta
stripeKey:"sk_live_51M8d...4w"    ← chave LIVE da Stripe!

📌 Variáveis com prefixo público viram públicas.

NEXT_PUBLIC_*, VITE_*, REACT_APP_* são empacotadas no JavaScript que vai pro navegador. Não bote segredo lá. Use serverless functions ou rotas de API pra mediar requisições que precisam de credenciais.


💣 Metasploit — o canivete suíço do pentester

Ferramentas em mesa

Depois de mapear o que está exposto, Metasploit é a ferramenta pra explorar de fato vulnerabilidades conhecidas. Ele tem módulos pré-prontos pra milhares de CVEs.

$ msfconsole

Fluxo típico — validar se uma correção funcionou:

       =[ metasploit v6.4.x                ]
+ -- --=[ 2400+ exploits - 1200+ auxiliary ]

msf6 > search type:exploit cve:2024 wordpress

  #  Name                                    Disclosure  Rank
  -  ----                                    ----------  -----
  0  exploit/unix/webapp/wp_plugin_xyz_rce   2024-03-15  excellent
  1  exploit/multi/http/wp_admin_shell_up    2024-01-08  great

msf6 > use 0
msf6 exploit(wp_plugin_xyz_rce) > set RHOSTS meusite.com
msf6 exploit(wp_plugin_xyz_rce) > check

[+] meusite.com:443 - O alvo PARECE VULNERÁVEL
    └─ confirme se a atualização foi aplicada

🎯 Use check antes de run.

O comando check só verifica se o alvo é vulnerável, sem explorar de fato. É exatamente o que você quer pra validar correção sem risco de quebrar a aplicação.

Aqui é importante reforçar: o uso responsável do Metasploit é validar que uma correção funcionou. Você descobriu via WPScan que o plugin X tem CVE-2024-XXXX. Atualizou. Como saber se a correção funcionou? Tenta explorar com o módulo Metasploit correspondente. Se falhar, ótimo. Se ainda funcionar, a atualização não foi suficiente.


📋 Workflow semanal pra apps vibe-coded

Checklist em prancheta

Junta tudo num roteiro repetível. Eu rodo isso no meu próprio projeto a cada release relevante:

🛡️ Local · pre-commit

  • gitleaks no hook
  • trufflehog filesystem . --only-verified
  • Lint específico da stack: bandit (Python), npm audit (Node), semgrep, snyk

🔍 Staging · pós-deploy

  • whatweb pra ver fingerprint
  • gobuster com wordlist de arquivos sensíveis
  • nikto pra config do servidor
  • wpscan se for WordPress
  • Curl manual em endpoints "que você não lembra de ter exposto" (/api/admin, /.git/config, /.env, /wp-config.php.bak)

🔄 Mensal · rotina

  • Rotacionar API keys mesmo sem indício de vazamento
  • Atualizar dependências (apt, npm, composer, pip)
  • Revisar logs de acesso buscando padrões de scan vindos de terceiros (você não é o único rodando essas ferramentas)

👁️ Cultural · contínuo

  • Sempre que pedir pra IA gerar código que lida com auth, secrets, upload, ou input do usuário — leia linha-por-linha antes de aceitar
  • IA não escreve código inseguro de propósito, mas escreve código que funciona
  • E "funciona" é diferente de "seguro"

🧠 A mentalidade que importa mais que as ferramentas

Vibe coding não é o problema. Ferramentas de IA pra desenvolvimento vieram pra ficar e fazem coisas que eram impossíveis dois anos atrás. O problema é velocidade sem fricção de segurança.

Cada uma das ferramentas que mostrei aqui te dá um momento de fricção saudável. Você roda, ela aponta dez coisas erradas, você corrige cinco e aceita o risco em cinco com consciência. Isso é diferente de subir e torcer.

💎 A diferença entre uma aplicação amadora e uma profissional, em 2026, não é mais "quem escreveu" — porque a IA escreveu boa parte das duas. A diferença é quem auditou depois.

Roda as ferramentas. Olha o resultado. Conserta. Roda de novo.

E mantém o .env longe do webroot, pelo amor.


💬 Curtiu o artigo?

Se quiser uma versão técnica focada em uma dessas ferramentas, ou um post sobre pipelines de CI com gitleaks + semgrep + dependabot, comenta aí embaixo que eu escrevo.


Tags