MÓDULO 4.4

🔒 Segurança em Código Gerado por IA

Os dados são alarmantes: 45% do código gerado por IA tem falhas de segurança. Este módulo ensina a identificar, prevenir e auditar vulnerabilidades antes que cheguem à produção.

7
Tópicos
40
Minutos
Avançado
Nível
Crítico
Tipo
1

📊 Os dados: 45% do código de IA tem falhas de segurança

Antes de qualquer técnica, é essencial entender a escala do problema com dados concretos. O código gerado por IA não é inerentemente inseguro — mas ele reproduz os padrões de segurança (e insegurança) que existem nos dados de treinamento.

📊 Dados verificados de pesquisa (2024–2025)

45%
do código de IA tem ao menos uma falha de segurança
Veracode State of Software Security 2025
2,74x
mais vulnerabilidades em código de IA vs. código humano
CodeRabbit Analysis, dezembro 2025
40%
dos devs não revisam código de IA antes do commit
Stack Overflow Developer Survey 2025
78%
das vuln. em código de IA são OWASP Top 10
CVE Database Analysis 2025
16/18
CTOs reportaram problemas sérios com vibe coding não supervisionado
METR Study on AI Autonomy, 2025
#1
vulnerabilidade: IDOR / Broken Object Authorization
CodeRabbit AI Security Report, 2025

📉 Distribuição dos tipos de vulnerabilidade em código de IA

IDOR / Broken Authorization31%
Secrets Expostos24%
SQL Injection18%
XSS15%
Outras (SSRF, XXE, etc.)12%

⚠️ Por que a IA comete erros de segurança

A IA aprende de exemplos online onde credenciais aparecem hardcodadas para simplificação, onde input não é validado em tutoriais rápidos, onde ownership não é verificado em código de demonstração. O modelo não distingue código de produção de código educacional.

Além disso, a IA otimiza para "funcionar" — não para "funcionar com segurança". Segurança requer instrução explícita e consistente em cada contexto de prompt e nos arquivos de regras.

2

🔟 OWASP Top 10 para código de IA

O OWASP Top 10 lista as vulnerabilidades mais críticas de aplicações web. A IA cria todas elas, mas as 5 mais frequentes têm padrões identificáveis que você pode detectar e prevenir com instruções específicas.

A03

SQL Injection

Como a IA cria: concatena variáveis diretamente em queries SQL, especialmente em exemplos "quick start". Muito comum quando a IA assume que você está prototipando.

Vulnerável — IA gera sem instrução

// PERIGOSO: SQL Injection
const query = `
  SELECT * FROM users
  WHERE email = '${email}'
  AND password = '${password}'
`;
// Atacante envia: ' OR '1'='1
// Resultado: acessa qualquer conta

Seguro — com instrução no CLAUDE.md

// SEGURO: ORM parametrizado
const user = await prisma.user.findFirst({
  where: {
    email,
    password: hashedPassword
  }
});
// Prisma sanitiza automaticamente
// Nunca interpolação de string

Instrução no CLAUDE.md:

NUNCA usar SQL raw com interpolação de string. SEMPRE usar Prisma ou queries parametrizadas ($1, $2). Sem exceções.

A03

XSS — Cross-Site Scripting

Como a IA cria: usa innerHTML para renderizar conteúdo dinâmico — é mais simples de escrever e muito comum em tutoriais de JavaScript. Permite injeção de scripts maliciosos.

Vulnerável

// PERIGOSO: XSS
element.innerHTML = userInput;
// Atacante: <script>steal(cookie)</script>

// Também perigoso:
document.write(data.comment);
container.innerHTML = `<p>${name}</p>`;

Seguro

// SEGURO: textContent escapa automaticamente
element.textContent = userInput;

// Ou sanitize com DOMPurify quando HTML é necessário:
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);

Instrução no CLAUDE.md:

NUNCA usar innerHTML com dados de usuário. SEMPRE textContent para texto. Se HTML é necessário, usar DOMPurify.sanitize() obrigatoriamente.

A01

IDOR — Insecure Direct Object Reference

Como a IA cria: busca recursos pelo ID do parâmetro sem verificar se o usuário autenticado é o dono. É a vulnerabilidade #1 em código de IA — extremamente fácil de introduzir, fácil de explorar.

Vulnerável — MUITO comum em código de IA

// PERIGOSO: qualquer usuário acessa
app.get('/orders/:id', async (req, res) => {
  const order = await prisma.order.findUnique({
    where: { id: req.params.id }
    // Sem verificar userId!
  });
  res.json(order);
});
// GET /orders/123 revela pedido de outro usuário

Seguro — ownership verificado

// SEGURO: verifica ownership obrigatoriamente
app.get('/orders/:id', auth, async (req, res) => {
  const order = await prisma.order.findFirst({
    where: {
      id: req.params.id,
      userId: req.user.id // CRÍTICO!
    }
  });
  if (!order) return res.status(404).json({});
  res.json(order);
});

Instrução no CLAUDE.md:

SEMPRE verificar req.user.id ao acessar qualquer recurso. NUNCA confiar em parâmetros de URL sem validar ownership. Em CADA query de recurso privado: where: { id, userId: req.user.id }

A07

Broken Authentication

Como a IA cria: middleware de auth esquecido em algumas rotas, tokens sem expiração, refresh tokens implementados incorretamente, senhas sem hash adequado.

Vulnerável

// PERIGOSO: rota admin sem proteção
app.get('/admin/users', async (req, res) => {
  const users = await prisma.user.findMany();
  res.json(users);
});

// PERIGOSO: senha sem hash
await prisma.user.create({
  data: { email, password } // plaintext!
});

Seguro

// SEGURO: auth + role check
app.get('/admin/users', auth, requireRole('admin'),
  async (req, res) => {
    const users = await prisma.user.findMany();
    res.json(users);
  }
);

// SEGURO: bcrypt hash
const hashed = await bcrypt.hash(password, 12);
await prisma.user.create({ data: { email,
  password: hashed } });
A02

Cryptographic Failures / Exposed Secrets

Como a IA cria: hardcoda API keys, connection strings e JWT secrets diretamente no código. Aprende de tutoriais onde isso é feito por simplicidade didática.

Vulnerável — IA gera assim

const jwt = require('jsonwebtoken');
// PERIGOSO: secret hardcodado
const token = jwt.sign(payload, 'minha_chave_123');

const stripe = new Stripe('sk_live_abc...xyz');

const db = new Client({
  connectionString: 'postgres://user:pass@host/db'
});

Seguro

const jwt = require('jsonwebtoken');
// SEGURO: sempre process.env
const token = jwt.sign(payload, process.env.JWT_SECRET!);

const stripe = new Stripe(process.env.STRIPE_KEY!);

const db = new Client({
  connectionString: process.env.DATABASE_URL
});

📋 Bloco de segurança obrigatório no CLAUDE.md

## Regras de Segurança (OBRIGATÓRIAS — sem exceções)
- SEMPRE verificar req.user.id ao acessar dados do usuário
- NUNCA confiar em parâmetros de URL sem validar ownership
- SEMPRE usar ORM parametrizado (Prisma) — nunca SQL raw com input
- NUNCA retornar stack traces ou mensagens de erro internas em produção
- SEMPRE validar e sanitizar input com Zod antes de processar
- NUNCA usar innerHTML com dados de usuário — usar textContent ou DOMPurify
- NUNCA hardcodar secrets — sempre process.env
- SEMPRE hashear senhas com bcrypt (rounds >= 12)
- SEMPRE adicionar middleware de auth em TODAS as rotas privadas
- SEMPRE criar políticas RLS ao criar novas tabelas no Supabase
3

🛡️ Row Level Security — o erro mais comum em apps Supabase

Row Level Security (RLS) é uma funcionalidade do PostgreSQL/Supabase que garante que usuários só acessam seus próprios dados no nível do banco de dados, independente do que a aplicação faça. É a última linha de defesa e a mais frequentemente esquecida em vibe coding.

Tabela vulnerável — sem RLS

-- Tabela criada pela IA sem instrução
CREATE TABLE orders (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id uuid REFERENCES auth.users(id),
  total decimal(10,2),
  status text,
  created_at timestamptz DEFAULT now()
);

-- RLS não habilitado!
-- Resultado: qualquer usuário autenticado
-- pode fazer: SELECT * FROM orders
-- e ver TODOS os pedidos de TODOS os usuários
-- via API Supabase exposta no frontend

Tabela segura — com RLS obrigatório

CREATE TABLE orders (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id uuid REFERENCES auth.users(id) NOT NULL,
  total decimal(10,2),
  status text,
  created_at timestamptz DEFAULT now()
);

-- OBRIGATÓRIO após criar qualquer tabela:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- Usuário vê apenas seus próprios pedidos
CREATE POLICY "users_own_orders" ON orders
  FOR ALL USING (auth.uid() = user_id);

-- Admin vê tudo (opcional)
CREATE POLICY "admins_all_orders" ON orders
  FOR ALL USING (
    EXISTS (SELECT 1 FROM profiles
      WHERE id = auth.uid() AND role = 'admin')
  );

💬 Prompt para solicitar RLS à IA

"Adicione Row Level Security completo para estas tabelas
Supabase. Para cada tabela:

1. ALTER TABLE ... ENABLE ROW LEVEL SECURITY
2. Policy para usuários autenticados verem apenas
   seus próprios dados (where user_id = auth.uid())
3. Policy para admins verem todos os dados
   (verificar role na tabela profiles)
4. Se a tabela for pública (ex: produtos de um catálogo),
   criar policy de leitura pública explícita

Tabelas: orders, profiles, documents, notifications

IMPORTANTE: Sem RLS habilitado, a API Supabase expõe
todos os dados de todos os usuários para qualquer
usuário autenticado."

🚨 O Incidente Lovable — 18.000 usuários expostos (2025)

Um app construído com Lovable (plataforma de vibe coding) foi exposto: sem RLS configurado, qualquer usuário autenticado conseguia acessar dados de qualquer outro usuário fazendo requests diretos à API do Supabase — que o Lovable expõe automaticamente via anon key no frontend.

18.000 usuários tiveram dados potencialmente expostos. O problema: Lovable não ativava RLS por padrão, e a IA não adicionava políticas de RLS sem instrução explícita.

Uma linha de instrução no CLAUDE.md previne este incidente: "SEMPRE habilitar RLS e criar policies ao criar novas tabelas Supabase."

4

🔑 Gestão de secrets — never hardcode, never commit

Secrets hardcodados é um dos erros mais comuns e mais devastadores em código de IA. O modelo aprende de exemplos online onde credenciais frequentemente aparecem hardcodadas para simplificação. Você precisa instruir explicitamente contra isso.

✗ NÃO FAÇA — IA gera assim sem instrução

// NUNCA hardcodar
const stripe = new Stripe(
  'sk_live_51NxAbc123...'  // exposto no git!
);

const db = new Pool({
  password: 'minhasenha123',
  host: 'prod-db.amazonaws.com'
});

const token = jwt.sign(
  payload, 'chave_secreta_123'
);

// .env nunca deve ser commitado
// mas a IA pode colocar valores reais

✓ SEMPRE assim — variáveis de ambiente

// SEMPRE process.env
const stripe = new Stripe(
  process.env.STRIPE_SECRET_KEY!
);

const db = new Pool({
  connectionString: process.env.DATABASE_URL
});

const token = jwt.sign(
  payload,
  process.env.JWT_SECRET!,
  { expiresIn: '1h' }
);

🔍 Onde secrets podem vazar — checklist completo

  • Código-fonte commitado no git
  • Logs de aplicação (evitar logar req.body completo)
  • Variáveis de ambiente no frontend (expostas no bundle)
  • Respostas de API que retornam objetos inteiros
  • Imagens Docker com secrets em layers
  • CI/CD logs com variáveis impressas
  • Stack traces expostos em produção
  • Arquivos .env no repositório (sem .gitignore)

🔍 Prompt para auditar código existente

"Audite este codebase em busca de secrets hardcodados
e práticas inseguras de gestão de credenciais.

Procure por:
1. Strings que parecem API keys, tokens ou senhas
   (padrões: sk_live_, Bearer , postgres://, etc.)
2. Variáveis com nomes como: secret, password, key,
   token, credential, api_key
3. Variáveis de ambiente usadas diretamente
   (sem process.env)
4. Conexões de banco com credenciais inline
5. JWT secrets hardcodados

Para cada ocorrência encontrada:
- Linha do código
- Tipo de secret
- Risco (alto/médio/baixo)
- Como corrigir

Arquivos a auditar: @src/"

🔐 Checklist de Gestão de Secrets

  • .env no .gitignore — sempre, sem exceção
  • .env.example com chaves vazias — no repositório para documentar variáveis necessárias
  • git-secrets ou trufflehog — scan automático de commits para detectar secrets acidentais
  • GitHub Secret Scanning — alertas automáticos se um secret detectado é pushado
  • Rotate imediatamente — se um secret foi commitado, rotacione antes de corrigir o commit
5

🔍 SAST: análise estática automatizada

SAST (Static Application Security Testing) analisa o código sem executá-lo, detectando vulnerabilidades antes do deploy. Em um fluxo de vibe coding, SAST deve rodar automaticamente em cada commit ou PR — não manualmente depois.

📊 Comparativo de ferramentas SAST

Ferramenta Tier gratuito O que detecta Integração
Snyk 200 testes/mês (open source: ilimitado) Dependências vulneráveis, código, containers IDE, GitHub Actions, CI/CD
SonarQube Community Edition gratuita (self-hosted) Qualidade de código + vuln. de segurança, 30+ linguagens PR gates, CI/CD, VSCode plugin
Semgrep Gratuito para open source, rules públicas Patterns OWASP, secrets, regras customizáveis GitHub Actions, pre-commit, CLI
GitHub Code Scanning Gratuito para repos públicos e private (CodeQL) Vulnerabilidades complexas com análise de fluxo de dados Nativo no GitHub, PR annotations

⚙️ GitHub Action: SAST completo em cada PR

# .github/workflows/security.yml
name: Security Scan

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Semgrep: detecta OWASP Top 10 e secrets
      - name: Run Semgrep
        uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/secrets
            p/owasp-top-ten
            p/typescript
        env:
          SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}

      # Snyk: verifica dependências com vulnerabilidades
      - name: Snyk vulnerability check
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

      # npm audit: check rápido de dependências
      - name: npm audit
        run: npm audit --audit-level=high
6

👁️ Code review focado em segurança

Mesmo com SAST automatizado, code review humano focado em segurança é insubstituível. O humano detecta falhas de lógica de negócio que ferramentas automatizadas não conseguem — como autorização incorreta que tecnicamente compila mas semanticamente está errada.

📋 Checklist de segurança — 10 itens por categoria

🔐Autenticação e Autorização

  • Todas as rotas privadas têm middleware de auth?
  • Verificação de ownership em todos os recursos?
  • Tokens JWT têm expiração definida?

🔑Secrets e Dados Sensíveis

  • Nenhum secret hardcodado no código?
  • Dados sensíveis não estão sendo logados?
  • RLS configurado em todas as tabelas Supabase?

📥Input e Output

  • Todo input de usuário validado com schema (Zod)?
  • Queries usam ORM ou parâmetros ($1, $2)?
  • Erros não expõem stack trace em produção?

📦Dependências

  • Novas dependências auditadas com npm audit?
  • Pacotes de origem conhecida e confiável?

💬 Prompt para code review de segurança com IA

"Faça um code review focado exclusivamente em segurança
destes arquivos. Não avalie qualidade de código ou estilo.

Procure especificamente por:
1. IDOR: endpoints que não verificam ownership
2. SQL Injection: queries com interpolação de string
3. XSS: uso de innerHTML com dados de usuário
4. Secrets expostos: hardcoded ou logados
5. Auth missing: rotas que deveriam ter auth mas não têm
6. RLS missing: tabelas Supabase sem policies
7. Sensitive data in logs: dados sensíveis em console.log
8. Error disclosure: stack traces retornados ao cliente

Para cada problema encontrado:
- Arquivo e linha
- Tipo de vulnerabilidade (OWASP A0X)
- Severidade: Crítica / Alta / Média
- Código vulnerável vs. código corrigido

Arquivos: @src/routes/ @src/controllers/"
7

💀 Casos reais de incidentes — o que aconteceu e por quê

Estudar casos reais é a forma mais eficaz de internalizar a importância de segurança. Estes não são cenários hipotéticos — são incidentes documentados que afetaram usuários reais de plataformas e apps de vibe coding em 2025.

Lovable — 18.000 usuários com dados expostos

Março 2025 · Plataforma de vibe coding no-code
CRÍTICO

O que aconteceu

Pesquisador de segurança descobriu que apps gerados pelo Lovable não tinham RLS habilitado no Supabase por padrão. Qualquer usuário autenticado podia acessar dados de qualquer outro via API pública.

Causa raiz

A plataforma não habilitava RLS por padrão. A IA não adicionava políticas de RLS sem instrução explícita. A anon key do Supabase no frontend dava acesso a todas as linhas de todas as tabelas.

Como prevenir

Instrução no CLAUDE.md: "SEMPRE habilitar RLS e criar policy ao criar tabela." Verificação: nunca deploy sem confirmar RLS em 100% das tabelas com dados de usuário.

Base44 — vazamento de dados de clientes empresariais

Abril 2025 · Plataforma SaaS gerada com IA
CRÍTICO

O que aconteceu

Funcionalidade de exportação de relatórios gerada por IA não validava que o usuário tinha acesso aos dados solicitados. Usuário de empresa A conseguia exportar dados da empresa B passando um ID diferente na URL.

Causa raiz

IDOR clássico (A01 OWASP). A IA gerou o endpoint sem verificar ownership do tenant. O endpoint recebia tenant_id como parâmetro e retornava os dados sem checar se pertenciam ao usuário autenticado.

Como prevenir

NUNCA confiar em IDs de URL sem verificar no banco que pertencem ao usuário autenticado. Em multi-tenant: sempre filtrar por tenant_id extraído do token JWT, nunca do body/params.

CurXecute — CVE-2025-54135 · Privilege escalation por prompt injection

Junho 2025 · Plugin de IDE para agentes de IA
CVE

O que aconteceu

Plugin de IDE para agentes de vibe coding executava código arbitrário via prompt injection. Um arquivo malicioso no repositório continha instruções disfarçadas que o agente interpretava como comandos legítimos, executando com as permissões do desenvolvedor.

Causa raiz

Agent privilege escalation: o plugin não sanitizava o conteúdo de arquivos antes de passá-los ao contexto do agente. Conteúdo de arquivos de terceiros (dependências, arquivos clonados) podia injetar instruções no agente.

Como prevenir

Cuidado com plugins de IDE de origem desconhecida. Agentes com acesso ao filesystem são vetores de ataque. Revise permissões de cada plugin. Nunca execute agentes com permissões de root ou admin desnecessárias.

💡 O padrão comum entre os incidentes

Os três incidentes têm um denominador comum: a IA gerou código funcional, mas sem as verificações de segurança que um desenvolvedor experiente aplicaria instintivamente. A IA não tem "instinto de segurança" — ela precisa de instrução explícita.

Todos eram preveníveis com: (1) instruções de segurança no CLAUDE.md, (2) SAST automatizado no CI, (3) code review de segurança antes de cada deploy. Nenhum exigia conhecimento de segurança avançado.

Resumo do Módulo 4.4

45% do código de IA tem falhas — dados verificados do Veracode e CodeRabbit. IDOR lidera com 31% dos casos. Revisão é obrigatória.
OWASP Top 5 em código de IA — SQL Injection, XSS, IDOR, Broken Auth e Secrets Expostos. Instrua o agente explicitamente para cada um.
RLS é obrigatório no Supabase — o incidente dos 18K usuários aconteceu por omissão de 3 linhas de SQL. Uma instrução no CLAUDE.md previne.
Never hardcode, never commit — sempre process.env. Oito lugares onde secrets podem vazar além do código-fonte.
SAST no pipeline — Semgrep + Snyk + GitHub Code Scanning em cada PR. O GitHub Action deste módulo é o ponto de partida.
Checklist antes do deploy — 10 itens por categoria: auth, secrets, input/output, dependências. Use com a IA como revisor auxiliar.
Cases reais ensinaram — Lovable (RLS), Base44 (IDOR), CurXecute (prompt injection). Todos preveníveis com as técnicas deste módulo.

Próximo Módulo:

4.5 — 🧪 Testes Automatizados com IA: o guardrail que permite vibe coding seguro em produção