StingwardAuditoria de segurança

Auditoria de segurança do projeto

my-saas

Há problemas graves. Corrija os itens críticos e altos antes de lançar ou de colocar mais usuários no app.

Alvo
./my-saas
Data
22 de outubro de 2026
Tipo
Projeto
Achados
4 críticos, 6 altos, 7 médios, 1 baixo
Revisão por IA
18 confirmados
Ferramenta
Stingward 0.1.7

Gerado pelo Stingward 0.1.7, software livre (Apache 2.0). github.com/HiveControlAgents/StingWard

1Resumo executivo

Resumo

O app funciona, mas vários dos problemas dele podem ser usados contra ele hoje. Corrija primeiro a chave da OpenAI: ela está numa variável que vai para o navegador de cada visitante, então qualquer pessoa pode copiar e gastar o seu dinheiro. Logo depois, tire a rota do agente que executa a resposta da IA como comando, porque ela deixa um estranho rodar qualquer coisa no seu servidor. A consulta de faturas, o download do PDF e a prévia de links confiam no que o visitante manda, e as versões antigas do next e do axios precisam de atualização.

NotaF

O que a nota quer dizer

A nota vai de A a F e depende só dos achados mais graves. Depois da revisão por IA, os alarmes falsos e o que foi corrigido não contam.

  1. ASó itens baixos, ou nenhum.
  2. BItens médios, nenhum alto ou crítico.
  3. CUm ou dois itens altos, nenhum crítico.
  4. DTrês ou mais itens altos, nenhum crítico.
  5. FPelo menos um item crítico.

Revisão por IA: 18 confirmados.

Corrija primeiro

  1. Qualquer visitante do site pode copiar NEXT_PUBLIC_OPENAI_API_KEY e usar como se fosse você: estourar a fatura do serviço ou chegar aos dados que a chave protege.

    Onde:.env:1

  2. Qualquer visitante do site pode copiar NEXT_PUBLIC_OPENAI_API_KEY e usar como se fosse você: estourar a fatura do serviço ou chegar aos dados que a chave protege.

    Onde:app/api/chat/route.ts:3

  3. Uma instrução escondida numa página, num arquivo ou numa mensagem que o modelo leia vira comando no seu servidor ou no navegador dos seus usuários.

    Onde:app/api/agent/route.ts:16

2Plano de correção

Siga de cima para baixo. O esforço é uma estimativa para quem conhece o código.

Rápido: menos de uma hora. Horas: cabe num dia. Dias: mais de um dia, em geral porque é preciso testar de novo ou reescrever uma parte.

#ProblemaOndeEsforço
Crítico: corrija agora
1Segredo exposto no navegador: NEXT_PUBLIC_OPENAI_API_KEY.env:1Horas
2Segredo exposto no navegador: NEXT_PUBLIC_OPENAI_API_KEYapp/api/chat/route.ts:3Horas
3Texto escrito pelo modelo chega a um comando de shellapp/api/agent/route.ts:16Horas
4next 14.1.0: 36 falhas conhecidas; a pior é CVE-2025-29927 (Authorization Bypass in Next.js Middleware)package-lock.json:15Dias
Alto: nesta semana
5SDK de IA rodando no navegador (dangerouslyAllowBrowser)app/api/chat/route.ts:3Horas
6Tabela profiles sem RLS no Supabasesupabase/migrations/0001_profiles.sql:1Horas
7Consulta SQL montada com dados da requisiçãoapp/api/invoices/route.ts:7Horas
8Caminho de arquivo montado com dados da requisição (fs.readFileSync())app/api/invoices/pdf/route.ts:6Horas
9Servidor busca uma URL que veio da requisição (fetch())app/api/preview/route.ts:4Horas
10axios 1.6.0: 31 falhas conhecidas; a pior é CVE-2026-25639 (Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig)package-lock.json:19Horas
Médio: neste mês
11Arquivo .env fora do .gitignore.envRápido
12Política do Supabase liberada para todos: read invoices (select)supabase/migrations/0001_profiles.sql:9Horas
13CORS aberto para qualquer siteapp/api/chat/route.ts:8Rápido
14Texto escrito pelo modelo chega à página como HTMLcomponents/Chat.tsx:6Horas
15Rota de IA sem login e sem limite de usoapp/api/agent/route.ts:7Horas
16Rota de IA sem login e sem limite de usoapp/api/chat/route.ts:5Horas
17requests >=2.19.0: a menor versão aceita (2.19.0) tem 5 falhas conhecidas; a pior é CVE-2018-18074 (Insufficiently Protected Credentials in Requests)worker/requirements.txt:2Horas
Baixo: quando puder
18requirements.txt sem lockfile: 2 dependência(s) com versão abertaworker/requirements.txtRápido

3Achados em detalhe

Trechos lidos dos arquivos no momento da auditoria. Segredos aparecem mascarados.

Aplicação 10

#1CríticoConfirmadoRegra APP001

Segredo exposto no navegador: NEXT_PUBLIC_OPENAI_API_KEY

Onde
  • .env:1
Revisão

Sua chave da OpenAI está numa variável que começa com NEXT_PUBLIC_, e o Next.js copia essas variáveis para o código que o navegador de cada visitante baixa. Qualquer pessoa pode pegar a chave ali e gastar o seu crédito na OpenAI. Crie uma chave nova, apague esta na OpenAI e guarde a nova como OPENAI_API_KEY, sem o prefixo.

Evidência
.env linha 1
1NEXT_PUBLIC_OPENAI_API_KEY=[REDACTED:secret_field]
Por que importa

Variáveis com prefixo NEXT_PUBLIC_ vão para o JavaScript que o navegador baixa. Qualquer visitante vê o valor.

Como corrigir

Tire o prefixo NEXT_PUBLIC_, use a variável só no servidor (API route, server action, edge function) e troque a chave.

Padrões
#2CríticoConfirmadoRegra APP001

Segredo exposto no navegador: NEXT_PUBLIC_OPENAI_API_KEY

Onde
  • app/api/chat/route.ts:3
Revisão

A rota do chat lê a chave dessa mesma variável, então trocar o nome só no .env não basta. Mude esta linha para ler OPENAI_API_KEY depois que a chave tiver o nome novo.

Evidência
app/api/chat/route.ts linha 3
2
3const openai = new OpenAI({ apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY, dangerouslyAllowBrowser: true });
4
Por que importa

Variáveis com prefixo NEXT_PUBLIC_ vão para o JavaScript que o navegador baixa. Qualquer visitante vê o valor.

Como corrigir

Tire o prefixo NEXT_PUBLIC_, use a variável só no servidor (API route, server action, edge function) e troque a chave.

Padrões
#3CríticoConfirmadoRegra APP009

Texto escrito pelo modelo chega a um comando de shell

Onde
  • app/api/agent/route.ts:16
Revisão

O que a IA responde é executado como comando no seu servidor, e quem digita a tarefa decide boa parte dessa resposta. Alguém pode pedir uma tarefa que apaga arquivos ou manda suas chaves para fora, e o servidor faz. Tire a chamada exec e deixe o agente escolher só entre uma lista curta de ações fixas.

Evidência
app/api/agent/route.ts linha 16
15 });
16 exec(reply.choices[0].message.content ?? "");
17 return Response.json({ ok: true });
Por que importa

A resposta do modelo pode ser guiada por qualquer coisa que ele leu (uma página, um arquivo, a mensagem de alguém). Usar isso direto transforma uma injeção de prompt em comandos rodando no seu servidor.

Como corrigir

Trate a saída do modelo como entrada de usuário: mapeie a resposta para comandos de uma lista fixa e passe os argumentos em lista, sem shell.

Padrões
#5AltoConfirmadoRegra APP002

SDK de IA rodando no navegador (dangerouslyAllowBrowser)

Onde
  • app/api/chat/route.ts:3
Revisão

Esta opção avisa a biblioteca da OpenAI que ela pode rodar no navegador, onde a chave fica visível para todos. Este arquivo roda no servidor, então tire o dangerouslyAllowBrowser: ele só desliga o aviso que protege você.

Evidência
app/api/chat/route.ts linha 3
2
3const openai = new OpenAI({ apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY, dangerouslyAllowBrowser: true });
4
Por que importa

A chave da OpenAI/Anthropic vai junto para o navegador. Alguém copia e usa sua conta até estourar a fatura.

Como corrigir

Chame a API de IA por uma rota no servidor e deixe a chave só lá.

Padrões
#6AltoConfirmadoRegra APP004

Tabela profiles sem RLS no Supabase

Onde
  • supabase/migrations/0001_profiles.sql:1
Revisão

A tabela profiles guarda o e-mail e o plano dos seus usuários, e sem RLS (as regras do Supabase sobre quem vê cada linha) qualquer pessoa com a chave pública do Supabase do seu app pode ler ou mudar todas elas. Ligue o RLS nesta tabela e crie uma regra que deixe cada usuário ver só a própria linha.

Evidência
supabase/migrations/0001_profiles.sql linha 1
1create table public.profiles (
2 id uuid primary key references auth.users,
Por que importa

Sem Row Level Security, qualquer pessoa com a chave anon (que é pública) lê e altera essa tabela.

Como corrigir

Adicione: alter table profiles enable row level security; e crie políticas para cada operação.

Padrões
#12MédioConfirmadoRegra APP005

Política do Supabase liberada para todos: read invoices (select)

Onde
  • supabase/migrations/0001_profiles.sql:9
Revisão

Esta regra deixa qualquer pessoa, mesmo sem login, ler todas as faturas. Mude para cada usuário ler só as faturas em que o user_id é o dele.

Evidência
supabase/migrations/0001_profiles.sql linha 9
8alter table public.invoices enable row level security;
9create policy "read invoices" on public.invoices for select using (true);
Por que importa

A política usa true como condição, então vale para qualquer pessoa, logada ou não.

Como corrigir

Troque true por uma condição como auth.uid() = user_id.

Padrões
#13MédioConfirmadoRegra APP003

CORS aberto para qualquer site

Onde
  • app/api/chat/route.ts:8
Revisão

Esta resposta diz aos navegadores que qualquer site pode chamar a sua rota de chat, então outro site pode usar os visitantes dele para gastar o seu crédito na OpenAI. Tire o cabeçalho Access-Control-Allow-Origin ou ponha nele só o endereço do seu site.

Evidência
app/api/chat/route.ts linha 8
7 const reply = await openai.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: prompt }] });
8 return new Response(JSON.stringify(reply), { headers: { "Access-Control-Allow-Origin": "*" } });
9}
Por que importa

Qualquer página da internet pode chamar sua API pelo navegador de quem visitar.

Como corrigir

Liste só os domínios do seu front-end em origin/allow_origins.

Padrões
#14MédioConfirmadoRegra APP009

Texto escrito pelo modelo chega à página como HTML

Onde
  • components/Chat.tsx:6
Revisão

As mensagens do chat, inclusive as respostas da IA, entram na página como HTML. Se alguém fizer a IA responder com um script, ele roda no navegador dos seus usuários e pode agir em nome deles. Mostre as mensagens como texto simples ou limpe com um sanitizador antes.

Evidência
components/Chat.tsx linha 6
5 const { messages } = useChat();
6 return messages.map((m) => <div key={m.id} dangerouslySetInnerHTML={{ __html: m.content }} />);
7}
Por que importa

A resposta do modelo pode ser guiada por qualquer coisa que ele leu (uma página, um arquivo, a mensagem de alguém). Usar isso direto transforma uma injeção de prompt em scripts rodando no navegador de quem usa o app.

Como corrigir

Trate a saída do modelo como entrada de usuário: mostre como texto, ou converta o Markdown e limpe com DOMPurify.sanitize antes de inserir.

Padrões
#15MédioConfirmadoRegra APP011

Rota de IA sem login e sem limite de uso

Onde
  • app/api/agent/route.ts:7
Revisão

Qualquer pessoa na internet pode chamar esta rota quantas vezes quiser, e cada chamada custa uma requisição à OpenAI, além de rodar um comando no seu servidor. Exija login e limite quantos pedidos cada usuário pode fazer por minuto.

Evidência
app/api/agent/route.ts linha 7
6// The user describes a chore in plain words and the agent does it on the server.
7export async function POST(req: Request) {
8 const { task } = await req.json();
Por que importa

Quem achar essa URL chama o modelo na sua conta em loop: a fatura dispara e o seu app vira proxy de IA de graça para outras pessoas.

Como corrigir

Exija usuário logado, limite pedidos por usuário ou IP (@upstash/ratelimit, express-rate-limit, slowapi), defina max_tokens / maxOutputTokens e ponha um limite de gasto no painel do provedor.

Padrões
#16MédioConfirmadoRegra APP011

Rota de IA sem login e sem limite de uso

Onde
  • app/api/chat/route.ts:5
Revisão

A rota do chat também funciona sem login e sem limite, então um script pode usar a sua conta da OpenAI de graça até a fatura chegar. Ponha aqui a mesma exigência de login e o mesmo limite por usuário.

Evidência
app/api/chat/route.ts linha 5
4
5export async function POST(req: Request) {
6 const { prompt } = await req.json();
Por que importa

Quem achar essa URL chama o modelo na sua conta em loop: a fatura dispara e o seu app vira proxy de IA de graça para outras pessoas.

Como corrigir

Exija usuário logado, limite pedidos por usuário ou IP (@upstash/ratelimit, express-rate-limit, slowapi), defina max_tokens / maxOutputTokens e ponha um limite de gasto no painel do provedor.

Padrões

Dependências 4

#4CríticoConfirmadoRegra DEP001

next 14.1.0: 36 falhas conhecidas; a pior é CVE-2025-29927 (Authorization Bypass in Next.js Middleware)

Onde
  • package-lock.json:15
Revisão

Seu app está preso a uma versão antiga do next, com muitos problemas de segurança já publicados. O pior deles deixa alguém pular as verificações que o middleware (o código que roda antes de cada página) deveria fazer. Atualize o next para a versão indicada na correção abaixo e confira se o app continua funcionando.

Evidência
package-lock.json linha 15
14 },
15 "node_modules/next": {
16 "version": "14.1.0",
Por que importa

Esta versão tem falhas públicas. Outras: CVE-2024-46982, CVE-2026-75604, GHSA-2464-fhr4-w9xw, GHSA-2xp9-vwfh-vxw4, CVE-2024-34351 e mais 30. Chance de a CVE-2025-29927 ser explorada nos próximos 30 dias: 99% (EPSS).

Como corrigir

Atualize next para 15.5.28 ou mais nova.

Falhas conhecidas nesta versão
IDSeveridadeResumoCorrigida em
CVE-2025-29927CríticoAuthorization Bypass in Next.js MiddlewareEPSS 99%14.2.25
CVE-2024-46982CríticoNext.js Cache PoisoningEPSS 59%14.2.10
CVE-2026-75604CríticoNext.js: Unauthenticated Remote Code Execution on windows-hosted serversEPSS 2%15.5.24
GHSA-2464-fhr4-w9xwCríticoNext.js: Unauthenticated Remote Code Execution in Image Optimization API when SVG files...15.5.28
GHSA-2xp9-vwfh-vxw4CríticoNext.js: Unauthenticated Remote Code Execution in Image Optimization API when AVIF file...15.5.24
CVE-2024-34351AltoNext.js Server-Side Request Forgery in Server ActionsEPSS 5%14.1.1
CVE-2024-51479AltoNext.js authorization bypass vulnerabilityEPSS 4%14.2.15
CVE-2026-44578AltoNext.js vulnerable to server-side request forgery in applications using WebSocket upgradesEPSS 2%15.5.16

e mais 28 falhas

Padrões
#10AltoConfirmadoRegra DEP001

axios 1.6.0: 31 falhas conhecidas; a pior é CVE-2026-25639 (Axios is Vulnerable to Denial of Service via __proto__ Key in mergeConfig)

Onde
  • package-lock.json:19
Revisão

Seu projeto está preso a uma versão antiga do axios, com problemas de segurança já publicados, e o pior deles pode fazer o app parar de responder. Atualize o axios para a versão indicada na correção abaixo.

Evidência
package-lock.json linha 19
18 },
19 "node_modules/axios": {
20 "version": "1.6.0",
Por que importa

Esta versão tem falhas públicas. Outras: CVE-2024-39338, CVE-2025-58754, CVE-2026-44495, CVE-2026-44496, CVE-2026-44494 e mais 25.

Como corrigir

Atualize axios para 1.20.0 ou mais nova.

Falhas conhecidas nesta versão
IDSeveridadeResumoCorrigida em
CVE-2026-25639AltoAxios is Vulnerable to Denial of Service via __proto__ Key in mergeConfigEPSS 2%1.13.5
CVE-2024-39338AltoServer-Side Request Forgery in axiosEPSS 1%1.7.4
CVE-2025-58754AltoAxios is vulnerable to DoS attack through lack of data size checkEPSS 1%1.12.0
CVE-2026-44495Altoaxios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollution Gad...EPSS 1%1.15.2
CVE-2026-44496AltoAxios: Regular Expression Denial of Service (ReDoS) via Cookie Name Injection1.16.0
CVE-2026-44494Altoaxios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `config.pr...1.16.0
CVE-2026-42033AltoAxios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request...1.15.1
CVE-2025-27152Altoaxios Requests Vulnerable To Possible SSRF and Credential Leakage via Absolute URL1.8.2

e mais 23 falhas

Padrões
#17MédioConfirmadoRegra DEP004

requests >=2.19.0: a menor versão aceita (2.19.0) tem 5 falhas conhecidas; a pior é CVE-2018-18074 (Insufficiently Protected Credentials in Requests)

Onde
  • worker/requirements.txt:2
Revisão

Esta linha deixa uma instalação ficar com uma versão do requests de 2018, com problemas de segurança conhecidos. Suba o mínimo para a versão indicada na correção abaixo ou, melhor, trave as versões exatas, como explica o achado sobre o lockfile.

Evidência
worker/requirements.txt linha 2
1openai>=1.30
2requests>=2.19.0
Por que importa

Sem lockfile, a faixa é a única regra: quem já tem a versão 2.19.0 instalada continua com ela, porque ela cabe na faixa, e a instalação pode escolhê-la para atender outros pacotes. Outras falhas na versão 2.19.0: CVE-2023-32681, CVE-2024-47081, CVE-2024-35195, CVE-2026-25645.

Como corrigir

Suba a versão mínima para 2.33.0: troque requests>=2.19.0 por requests>=2.33.0. Na próxima instalação, quem tem versão antiga recebe a nova.

Falhas conhecidas na menor versão aceita
IDSeveridadeResumoCorrigida em
CVE-2018-18074AltoInsufficiently Protected Credentials in RequestsEPSS 7%2.20.0
CVE-2023-32681MédioUnintended leak of Proxy-Authorization header in requestsEPSS 3%2.31.0
CVE-2024-47081MédioRequests vulnerable to .netrc credentials leak via malicious URLs2.32.4
CVE-2024-35195MédioRequests `Session` object does not verify requests after making first request with veri...2.32.0
CVE-2026-25645MédioRequests has Insecure Temp File Reuse in its extract_zipped_paths() utility function2.33.0
Padrões
#18BaixoConfirmadoRegra DEP003

requirements.txt sem lockfile: 2 dependência(s) com versão aberta

Onde
  • worker/requirements.txt (o arquivo inteiro)
Revisão

Sem um lockfile (um arquivo que fixa a versão exata de cada pacote), cada instalação do worker pode pegar versões diferentes, inclusive uma quebrada ou adulterada. Gere um com uma ferramenta como uv ou pip-tools e guarde no projeto.

Por que importa

Sem lockfile não dá para saber qual versão está instalada, nem para auditar. Cada instalação pode puxar uma versão diferente.

Como corrigir

Gere e faça commit do lockfile (npm install, poetry lock, uv lock) ou fixe as versões com ==.

Padrões

Código 3

#7AltoConfirmadoRegra COD001

Consulta SQL montada com dados da requisição

Onde
  • app/api/invoices/route.ts:7
Revisão

O valor user que vem do endereço entra direto na consulta ao banco, então um visitante pode reescrever a consulta e ler as faturas de todos os clientes. Faça a consulta mandar esse valor separado (consulta com parâmetros), para o banco tratar como dado e nunca como parte do comando.

Evidência
app/api/invoices/route.ts linha 7
6 const user = new URL(req.url).searchParams.get("user");
7 const { rows } = await pool.query(`select * from invoices where user_id = '${user}'`);
8 return Response.json(rows);
Por que importa

O valor entra no meio do texto do SQL. Quem manda algo como ' OR '1'='1 consegue ler, mudar ou apagar dados do banco.

Como corrigir

Passe os valores como parâmetros e deixe o driver juntar: cursor.execute("... WHERE id = %s", (id,)), $1 no Postgres, ? no SQLite, sql`...` ou $queryRaw`...` no Prisma. Nome de coluna ou de tabela não pode ser parâmetro: escolha o nome numa lista fixa (SORTS[chave], if order not in ALLOWED: abort(400)).

Padrões
#8AltoConfirmadoRegra COD007

Caminho de arquivo montado com dados da requisição (fs.readFileSync())

Onde
  • app/api/invoices/pdf/route.ts:6
Revisão

O nome do arquivo vem do endereço e é juntado à pasta do jeito que chega, então um nome como ../.env deixa qualquer pessoa baixar arquivos de fora de invoices, inclusive suas chaves. Use só o nome do arquivo, sem pastas, e confira se a fatura é de quem está logado.

Evidência
app/api/invoices/pdf/route.ts linha 6
5 const file = new URL(req.url).searchParams.get("file") ?? "";
6 const pdf = fs.readFileSync(path.join(process.cwd(), "invoices", file));
7 return new Response(pdf, { headers: { "Content-Type": "application/pdf" } });
Por que importa

Um valor como ../../.env deixa alguém ler ou sobrescrever qualquer arquivo que o servidor alcança.

Como corrigir

Use só o nome do arquivo (os.path.basename, secure_filename, path.basename) ou resolva o caminho e confira que ele continua dentro da pasta esperada.

Padrões
#9AltoConfirmadoRegra COD008

Servidor busca uma URL que veio da requisição (fetch())

Onde
  • app/api/preview/route.ts:4
Revisão

Seu servidor abre qualquer endereço que o visitante mandar, inclusive endereços que só o servidor alcança, como serviços internos ou o endereço da própria nuvem que entrega credenciais. Aceite só links públicos da web e recuse endereços privados e internos antes de abrir.

Evidência
app/api/preview/route.ts linha 4
3 const { url } = await req.json();
4 const page = await fetch(url);
5 const html = await page.text();
Por que importa

Alguém pode fazer o seu servidor chamar endereços internos, como o serviço de metadados da nuvem (169.254.169.254), e devolver a resposta com as credenciais.

Como corrigir

Aceite só os domínios de que você precisa, bloqueie endereços privados e locais e não siga redirecionamentos sem conferir.

Padrões

Segredos 1

#11MédioConfirmadoRegra SEC003

Arquivo .env fora do .gitignore

Onde
  • .env (o arquivo inteiro)
Revisão

O seu .gitignore não lista o .env, então o arquivo com as suas chaves vai fácil para o GitHub sem querer. Ponha uma linha com .env no .gitignore e, se o arquivo já foi enviado alguma vez, troque todas as chaves dele.

Por que importa

O arquivo ainda não foi commitado, mas o próximo git add . leva as chaves junto.

Como corrigir

Adicione .env ao .gitignore.

Padrões

4Escopo e método

O que foi verificado

Revisão por IA

Depois da varredura automática, uma IA leu o código de cada achado e marcou cada um como confirmado ou alarme falso. Na dúvida, o achado ficou confirmado. O comentário da revisão aparece junto de cada achado.

Como a revisão muda a nota

Bases consultadas

BasePara quê Situação
OSV.devfalhas conhecidas e pacotes maliciososconsultado
CISA KEVfalhas que atacantes estão explorando agoraconsultado, catálogo 2026.10.21
EPSS (FIRST)chance de exploração nos próximos 30 diasconsultado
NVDnota de severidade quando o aviso não traznão foi preciso: todos os avisos tinham nota

Para essas bases saíram só nomes e versões de pacotes. Para a revisão por IA, o trecho de cada achado, com os segredos mascarados, foi enviado ao modelo de IA.

Como foi feito

  1. Listamos os arquivos do alvo, sem as pastas de dependências e de build, como node_modules e dist. Numa skill de terceiros o build é lido, porque é ele que roda.
  2. Lemos os lockfiles e perguntamos ao OSV.dev sobre cada pacote e versão. Falhas que estão na lista KEV da CISA viram críticas; EPSS e NVD completam a chance de exploração e as notas que faltam.
  3. Rodamos 51 regras para segredos, erros comuns de apps feitos com IA, falhas no código do próprio projeto, configurações de agentes e MCP e conteúdo de skills. Pastas de teste, documentação e exemplos pesam menos.
  4. Uma IA leu o código de cada achado e marcou o resultado: confirmado ou alarme falso.
  5. Damos a nota de A a F pelos achados mais graves que continuam valendo depois da revisão.

Limites