Pipeline de ingestão, consulta RAG de CVEs, scan de segurança com Checkmarx One e correção automática de código via LLM — tudo com MongoDB como vector store, LM Studio como backend e API documentada em OpenAPI 3.0.
O projeto consome a base pública do CVEProject/cvelistV5, organiza os dados em disco por mês/ano, sincroniza com MongoDB e disponibiliza uma interface RAG para consultas em linguagem natural, detecção de CVEs em relatórios, geração de PDFs técnicos e correção automática de vulnerabilidades diretamente no repositório GitLab via FixAgent.
O sistema segue a arquitetura hexagonal (Ports & Adapters): o núcleo de domínio é isolado de frameworks e infraestrutura por portas explícitas. O diagrama completo está em docs/fluxo_arquitetura.mmd.
╔══════════════════╗ ╔════════════════════════════════════════════════╗ ╔══════════════════╗
║ ADAPTADORES ║ ║ ⬡ NÚCLEO HEXAGONAL ⬡ ║ ║ ADAPTADORES ║
║ PRIMÁRIOS ║ ║ ║ ║ SECUNDÁRIOS ║
║ (entrada) ║ ║ ┌────────────────────────────────────────┐ ║ ║ (saída) ║
║ ║ ║ │ DOMÍNIO │ ║ ║ ║
║ REST API ──────╫─────╫─►│ RAG Engine Workaround Cascade │ ║ ║ MongoDB ║
║ (Flask) ║ ║ │ CVEIndexer PDF Generator │ ║ ║ (Vector Store) ║
║ ║ ║ │ Text Extractor Code Fixer (LLM) │ ║ ║ ║
║ CLI ──────╫─────╫─►│ │ ║ ║ LM Studio ║
║ (--cve) ║ ║ └──────────────┬──────────────────────────┘ ║ ║ LLM + Embeddings║
║ ║ ║ │ ║ ║ ║
╚══════════════════╝ ║ ┌──────────────▼──────────────────────────┐ ║ ║ DuckDuckGo ║
║ │ CASOS DE USO │ ║ ║ cve.org · NVD ║
║ │ CVEConsultant (LangGraph 4 nós) │───╫────►║ CIRCL · OSV ║
║ │ LiteConsultant (Cascata 4 etapas) │ ║ ║ ║
║ │ CVEAgent (detecção + PDF) │ ║ ║ Checkmarx One ║
║ │ CheckmarxAgent (LangGraph 7 nós) │ ║ ║ GitLab API ║
║ │ FixAgent (LangGraph 9 nós) ★ │ ║ ║ ║
║ │ CVEUpdater (pipeline incremental) │ ║ ║ CVEProject ZIP ║
║ └─────────────────────────────────────────┘ ║ ╚══════════════════╝
╚════════════════════════════════════════════════╝
flowchart TD
%% ── Entradas ──
REST(["REST API\nFlask / OpenAPI"])
CLI(["CLI\n--cve CVE-YYYY-XXXX"])
%% ── Pipelines ──
subgraph INGEST["📥 Ingestão POST /atualizar_cves"]
I1["CVEUpdater\n(incremental: desde_ano)"] --> I2["CVEIndexer\n(ThreadPoolExecutor)"]
I2 --> I3["cve_resolver\n(UUIDs + headers)"] --> I4["sincronizar()"] --> I5["vetorizar()"]
end
subgraph FULL["🔍 Pipeline Principal POST /consultar_cve*"]
F1["buscar_documentos\n(MongoDB × 3 queries)"] --> F2["gerar_resposta\n(LLM)"]
F2 --> F3["fallback_online\n(cve.org se não encontrado)"] --> F4["enriquecer_workaround\nNVD·CIRCL·OSV·Web·LLM"]
end
subgraph LITE["⚡ Pipeline Lite POST /lite/*"]
L1{"MongoDB\nID exato · semântica"} -->|encontrado| LOUT["JSON + fonte"]
L1 -->|não encontrado| L2{"sugestao_correcao?"}
L2 -->|sim| LOUT
L2 -->|não| L3{"descricao?"}
L3 -->|sim| LOUT
L3 -->|não| L4["DuckDuckGo → LLM"] --> LOUT
end
subgraph FIX["🔧 FixAgent POST /fix_pipeline"]
FX1["[1] autenticar\nGitLab project_id"] --> FX2["[2] obter_vulnerabilidades\nCheckmarx · lista direta"]
FX2 --> FX3["[3] planejar_fixes\nLLM: arquivo + ação"] --> FX4["[4] ler_arquivos\nGitLab API"]
FX4 --> FX5["[5] gerar_solucoes\nLLM por vuln"] --> FX6["[6] gerar_codigo\nLLM: código corrigido"]
FX6 --> FX7["[7] criar_branch\nagent/fix-cve-YYYYMMDD"] --> FX8["[8] gerar_relatorio\nReportLab PDF"]
FX8 --> FX9["[9] commit_e_push\natômico: código + PDF"]
end
%% ── Infraestrutura compartilhada ──
MONGO[("MongoDB\ncve_rag.cves")]
LLM["LM Studio\nLLM + Embeddings"]
EXT["APIs Externas\ncve.org · NVD · CIRCL\nCheckmarx · GitLab"]
%% ── Conexões ──
REST --> INGEST
REST --> FULL
REST --> LITE
REST --> FIX
CLI --> FULL
I5 --> MONGO
F1 --> MONGO
L1 --> MONGO
F2 --> LLM
F4 --> LLM
L2 --> LLM
L3 --> LLM
FX3 --> LLM
FX5 --> LLM
FX6 --> LLM
F3 --> EXT
F4 --> EXT
FX2 --> EXT
FX4 --> EXT
FX9 --> EXT
%% ── Saídas ──
F4 -->|"JSON Response"| RJSON["JSON\n(workaround · refs)"]
LOUT -->|"JSON Response"| RLITE["JSON\n(workaround · fonte)"]
FX9 -->|"branch + PDF + SHA"| RGIT["GitLab\nagent/fix-cve-* branch"]
%% ── Estilos ──
classDef pipeline fill:#1d3557,color:#fff,stroke:#457b9d,stroke-width:2px
classDef node fill:#2d4a6e,color:#fff,stroke:#4a7fb5
classDef infra fill:#2d6a4f,color:#fff,stroke:#1b4332
classDef out fill:#e9c46a,color:#333,stroke:#e76f51
classDef entry fill:#457b9d,color:#fff,stroke:#1d3557
class REST,CLI entry
class MONGO,LLM,EXT infra
class RJSON,RLITE,RGIT out
Modo completo (primeira carga) — processa todos os ~350k arquivos do dataset:
main.zip → extrair → CVEIndexer (desde_ano=None) → cve_resolver → sincronizar → vetorizar → MongoDB
Modo incremental (atualizações rotineiras) — detecta automaticamente o último ano indexado e processa apenas os arquivos desse ano em diante (~10% do dataset):
main.zip → extrair → CVEIndexer (desde_ano=último_ano) → cve_resolver → sincronizar → vetorizar → MongoDB
↑
ThreadPoolExecutor
(cpu×2 workers, chunksize auto)
START
│
▼
buscar_documentos ──► MongoDB (3 queries paralelas)
│ └── DuckDuckGo (fallback se ≤1 resultado)
▼
gerar_resposta ──────► LLM → JSON estruturado
│
▼
fallback_online ─────► cve.org API (só se encontrado=false)
│ └── salva no MongoDB para consultas futuras
▼
enriquecer_workaround → solucao MongoDB
│ → NVD ‖ CIRCL ‖ OSV (paralelo)
│ → URLs de referência do CVE
│ → DuckDuckGo → LLM
│ → LLM forçado (nunca retorna vazio)
▼
END → JSON Response
Sem chamadas a APIs externas de CVE. Ideal quando o relatório já traz contexto suficiente.
Por vulnerabilidade recebida:
│
├─1─► MongoDB (ID exato → semântica) ──────────────────► fonte: "mongodb"
│ └── não encontrado
│
├─2─► sugestao_correcao presente? → LLM elabora ────────► fonte: "sugestao"
│ └── não
│
├─3─► descricao disponível? → LLM infere ───────────────► fonte: "descricao"
│ └── não
│
└─4─► DuckDuckGo → LLM sintetiza ────────────────────────► fonte: "internet"
Corrige vulnerabilidades diretamente no código-fonte do repositório GitLab, faz commit em nova branch e gera relatório PDF.
[1] autenticar ──► GitLab project_id
[2] obter_vulnerabilidades ──► lista fornecida ou CheckmarxAgent.escanear()
[3] planejar_fixes ──► LLM: { arquivo, acao, descricao } por vuln
[4] ler_arquivos ──► GitLab API: conteúdo de cada arquivo na branch_origem
[5] gerar_solucoes ──► LLM: descrição de solução por vulnerabilidade
[6] gerar_codigo ──► LLM: código corrigido por arquivo (agrupa múltiplas vulns)
[7] criar_branch ──► GitLab: agent/fix-cve-YYYYMMDD ← branch_origem
[8] gerar_relatorio ──► ReportLab: PDF com vulns + soluções + diff
[9] commit_e_push ──► commit atômico: código corrigido + PDF → push
Comparativo entre os pipelines:
| Característica | Principal | Lite | Fix |
|---|---|---|---|
| Consulta MongoDB | Sim | Sim | Não |
| API cve.org / NVD / CIRCL | Sim | Não | Não |
| Busca web (DuckDuckGo) | Sim | Último recurso | Não |
| Sugestão de correção | Não | Sim | Não |
| Corrige código-fonte | Não | Não | Sim ★ |
| Cria branch no GitLab | Não | Não | Sim ★ |
| Commit + push automático | Não | Não | Sim ★ |
| Geração de PDF | /analise_extracao_relatorio |
/lite/analise_extracao_relatorio |
Incluído no commit |
| Saída | JSON com refs | JSON com fonte |
SHA + branch + PDF |
src/
├── config/
│ ├── prompt_config.py # Prompts LLM, schemas JSON, semáforo _LLM_SEM, invocar_llm/invocar_chain
│ └── token_tracker.py # Contagem tiktoken, ContextVar por request, truncar/extrair seções de código
│
├── loader/
│ ├── cve_loader.py # Download e extração do main.zip
│ ├── cve_indexer.py # Parse e indexação de todos os CVEs por mês/ano
│ └── cve_updater.py # Pipeline completo de atualização via API (upload zip)
│
├── searcher/
│ └── cve_resolver.py # UUIDs por registro + header JSON (LangGraph async)
│
├── rag/
│ ├── cve_rag_mongo.py # Conexão MongoDB, sincronizar(), vetorizar(), retriever
│ ├── cve_rag.py # Retriever, scoring, buscar(), responder(), cve_tools
│ ├── cve_consultant.py # Consulta completa via LangGraph (CLI + API)
│ └── lite_consultant.py # Pipeline lite: MongoDB → sugestão → descrição → internet
│
└── agent/
├── cve_agent.py # Detecção de CVEs em texto + orquestração em lote
├── text_extractor.py # Extração de texto de PDF, DOCX, TXT, JSON, CSV, XLSX, XML
├── pdf_generator.py # Geração de relatório técnico em PDF via LLM + ReportLab
└── fix_agent.py # FixAgent: corrige código no GitLab via LangGraph (9 nós)
Fonte única de verdade para toda a comunicação com o LLM:
_LLM_SEM—threading.Semaphore(1)compartilhado por todos os módulos. Como o LM Studio processa uma requisição por vez, todas as chamadas ao LLM devem adquirir este semáforo antes de invocar o modelo.invocar_llm(model, msgs)— wrapper que adquire_LLM_SEM, invoca o modelo e registra tokens automaticamente viatoken_tracker. Substituiwith _LLM_SEM: model.invoke(msgs)em todos os módulos.invocar_chain(chain, inputs)— wrapper equivalente para chains do tipoprompt | model | parser.- Schemas JSON — contratos de saída dos LLMs:
SCHEMA_CVE_DETECTADO,SCHEMA_CVE_RESPOSTA,SCHEMA_RELATORIO,SCHEMA_FX_PLANO - Prompt templates (
ChatPromptTemplate) —PROMPT_CVE_AGENT,PROMPT_CVE_RESPOSTA,PROMPT_CVE_BATCH,PROMPT_PDF_RELATORIO,PROMPT_RAG_RESPOSTA,PROMPT_FX_PLANEJAR - Message builders — funções que retornam listas de tuplas:
msgs_traducao(),msgs_extrair_workaround(),msgs_workaround_forcado(),msgs_workaround_web_search(),msgs_enriquecer_workaround(),msgs_workaround_de_sugestao(),msgs_corrigir_codigo(),msgs_descrever_fix()
Infraestrutura de rastreamento e redução de tokens por requisição Flask:
nova_requisicao()— inicializa um_Acumuladorviacontextvars.ContextVar, armazenado emg.token_accpelobefore_requestdo Flask.registrar(response, msgs)— extraiprompt_tokens/completion_tokensdousage_metadatada resposta ou estima via tiktoken quando ausente.stats_da_requisicao()— retorna{prompt_tokens, completion_tokens, total_tokens, llm_calls, estimado}. Injetado automaticamente como chave"tokens"em todas as respostas JSON quandollm_calls > 0.contar_tokens(texto)— contagem exata viacl100k_base(tiktoken) com fallbacklen/4.truncar_por_tokens(texto, max_tokens)— truncação tiktoken-exata, não por caracteres.extrair_secao_codigo(conteudo, linha, janela=60, max_tokens=3000)— extrai ±60 linhas ao redor da vulnerabilidade antes de enviar ao LLM, reduzindo 70–90% dos tokens em arquivos grandes.compactar_lista_textos(textos, budget)— distribui um budget de tokens entre múltiplos textos, evitando overflow em operações em batch.
Campo tokens na resposta:
{
"resultado": "...",
"tokens": {
"prompt_tokens": 450,
"completion_tokens": 120,
"total_tokens": 570,
"llm_calls": 3,
"estimado": false
}
}Responsável exclusivamente por:
- Baixar o
main.zipdo repositório oficial do CVEProject no GitHub - Verificar se o ZIP mudou (hash SHA-256) para evitar re-extração desnecessária
- Extrair os arquivos para
loader/datasets/cves/
- Varre os arquivos JSON extraídos pelo loader
- Parseia CVEs e extrai:
cve_registro,data_criacao,Year,Month,descricao,solucao - Extrai
severidadedos métricas CVSS (preferindo CNA sobre ADP; fallback:"Unknown") - Organiza os registros em
database/{year}/cve_database_MM_YYYY.json
Orquestra o pipeline de atualização via upload da API com detecção automática de modo:
| Etapa | Ação |
|---|---|
validar() |
Verifica estrutura interna do zip cvelistV5 |
ja_processado() |
Compara SHA-256 para evitar reprocessamento |
extrair() |
Descompacta para loader/datasets/cves/ |
processar() |
Detecta modo (completo vs incremental) e executa o pipeline sequencial |
atualizar_readme() |
Atualiza automaticamente a seção de estatísticas no README |
Detecção de modo em processar():
- Se
database/não existir → modo completo (desde_ano=None): indexa todos os ~350k arquivos - Se
database/existir → modo incremental (desde_ano=último_ano): indexa apenas arquivos do último ano indexado em diante (~10% do total)
Pipeline sequencial:
extrair → CVEIndexer.index(desde_ano) → cve_resolver → sincronizar → vetorizar
Pipeline assíncrono (LangGraph + asyncio) que:
- Lê todos os arquivos
cve_database_*.jsondo diretóriodatabase/ - Gera UUIDs aleatórios para registros sem
id - Adiciona/atualiza o header de cada JSON com
year,month,mes_ano,gerado_emetotal_cves - Migra automaticamente o formato legado para o novo formato (
header+cves[]) - Normaliza as chaves
Year/Monthparayear/month
Formato JSON resultante:
{
"header": {
"year": 2026,
"month": 4,
"mes_ano": "04_2026",
"gerado_em": "2026-05-31T...",
"total_cves": 42
},
"cves": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"cve_registro": "CVE-2026-12345",
"Year": 2026,
"Month": 4,
"descricao": "...",
"solucao": "...",
"severidade": "High"
}
]
}sincronizar()— Lê todos os JSONs dedatabase/e salva um documento MongoDB por arquivo (mes_ano), com os CVEs como array aninhado no campocves:- Chave única:
mes_ano(ex:"04_2026") - Usa
$setOnInsert— documentos existentes não são sobrescritos
- Chave única:
vetorizar()— Calcula embeddings (modelotext-embedding-qwen3-embedding-0.6bvia LM Studio) para cada CVE sem embedding dentro dos documentos mês/ano, usando o operador posicional$set cves.<idx>.embeddingMongoDBCVERetriever— Faz unwind dos CVEs em memória, calcula score composto ponderado e filtra porscore >= 0.6
Schema do documento MongoDB:
{
"mes_ano": "04_2026",
"year": 2026,
"month": 4,
"cves": [
{
"cve_registro": "CVE-2026-12345",
"data_criacao": "2026-04-15T...",
"Year": 2026,
"Month": 4,
"descricao": "...",
"solucao": "...",
"severidade": "High",
"embedding": [0.123, "..."]
}
]
}Centraliza a lógica de recuperação e geração:
coseno(a, b)— Similaridade coseno entre dois vetores NumPycalcular_score(...)— Score composto normalizado [0, 1] com pesos: CVE-ID (4) > semântica (3) > ano (2) > mês (1)MongoDBCVERetriever— Retriever LangChain com scoring ponderado, threshold 0.6, filtro por anobuscar(query, k)— Busca os k documentos mais relevantes no MongoDBresponder(pergunta)— Pipeline RAG completo: busca + geração de resposta pelo LLM@tool buscar_workarounds_cve+cve_tools— Ferramenta exposta para uso por agentes LLM
Orquestrador completo via LangGraph com 4 nós em sequência:
| Nó | Função |
|---|---|
buscar_documentos |
Gera 3 queries estáticas internamente e consulta o MongoDB em paralelo. Se ≤ 1 resultado, faz busca web (DuckDuckGo) filtrando por score > 0.6 |
gerar_resposta |
Sintetiza os documentos em JSON estruturado via LLM; inclui referências MongoDB (mes_ano, score) |
fallback_online |
Se encontrado: false, busca na API pública cveawg.mitre.org. Tradução PT-BR e busca de workaround executadas em paralelo |
enriquecer_workaround |
Se workaround for null: cascata de fontes até garantir valor não-nulo |
Grafo LangGraph:
START → buscar_documentos → gerar_resposta → fallback_online → enriquecer_workaround → END
Busca de workaround — cascata de fontes (workaround nunca é nulo):
- Campo
solucaojá gravado no MongoDB - Campo
workaroundsdo JSON da API cve.org - NVD / CIRCL / OSV — consultados em paralelo, retorna ao primeiro resultado
- URLs de referência do próprio CVE (fetch + extração via LLM)
- Busca web DuckDuckGo → LLM sintetiza em PT-BR
- LLM forçado com descrição da vulnerabilidade (nunca retorna vazio)
- Fallback estático com recomendações genéricas (garantia absoluta)
Saída JSON:
{
"cve": "CVE-2026-12345",
"encontrado": true,
"descricao": "Descrição em PT-BR",
"severidade": "High",
"workaround": "Passos de mitigação em PT-BR...",
"referencias": [
"https://nvd.nist.gov/...",
"MongoDB[cve_rag.cves/04_2026]: CVE-2026-12345 (score: 0.91)"
]
}Uso via CLI:
python src/rag/cve_consultant.py --cve CVE-2026-12345consultar_multiplos — fluxo em lote (não usa o grafo LangGraph):
| Fase | Ação | Paralelismo |
|---|---|---|
| 1. Busca de documentos | Executa buscar_documentos para todos os CVEs no MongoDB |
8 workers em paralelo |
| 2. Chamadas ao LLM | Agrupa CVEs em batches de CVE_BATCH_SIZE e envia um batch por chamada |
Sequencial (serializado por _LLM_SEM) |
| 3. Fallback + enriquecimento | Executa fallback_online e enriquecer_workaround só para CVEs que precisam |
3 workers em paralelo |
O contexto por CVE no batch é limitado a 10000 ÷ batch_size caracteres para respeitar o context window do modelo.
Uso via API:
from src.rag.cve_consultant import CVEConsultant
consultant = CVEConsultant()
# Consulta individual (usa LangGraph completo)
resultado = consultant.consultar("CVE-2026-12345")
# Consulta em lote com batch LLM (recebe payload do CVEAgent)
resultados = consultant.consultar_multiplos([
{"cve_id": "CVE-2026-12345", "severidade": "High"},
{"cve_id": "CVE-2026-67890", "severidade": "Unknown"},
])Pipeline simplificado para extração de correções sem dependência de APIs externas de CVE.
Classe LiteConsultant:
| Método | Descrição |
|---|---|
consultar(vuln_id, descricao, sugestao_correcao, severidade) |
Consulta individual com lógica em cascata |
consultar_lista(vulnerabilidades) |
Processa lista em paralelo (I/O) com LLM serializado |
Ordem de consulta por vulnerabilidade:
| Passo | Condição | Fonte reportada |
|---|---|---|
| 1 | MongoDB — ID exato (cve_registro) com solucao preenchida |
"mongodb" |
| 2 | MongoDB — similaridade semântica (score composto ≥ 0.6) com solucao |
"mongodb" |
| 3 | sugestao_correcao fornecida → msgs_workaround_de_sugestao() → LLM elabora |
"sugestao" |
| 4 | descricao disponível → msgs_workaround_forcado() → LLM infere |
"descricao" |
| 5 | DuckDuckGo → LLM sintetiza (último recurso) | "internet" |
O campo fonte no JSON de saída indica qual caminho foi percorrido, facilitando auditoria e fine-tuning.
Diferença em relação ao CVEConsultant: não consulta cve.org, NVD, CIRCL, OSV nem URLs de referência do CVE. Ideal quando o relatório de scan já fornece sugestões de correção (Checkmarx One, Snyk, Veracode) — o LLM as elabora localmente, sem chamadas externas.
Saída JSON por item:
{
"id": "CVE-2021-44228",
"nome": "Log4Shell",
"descricao": "Desserialização insegura no Log4j 2 permite RCE via JNDI.",
"severidade": "Critical",
"workaround": "Atualizar Log4j para 2.17.1+. Definir log4j2.formatMsgNoLookups=true...",
"fonte": "sugestao"
}Agente de detecção e orquestração:
CVEAgent.analisar(input_text)— Recebe texto livre (log, relatório, código, mensagem) e usa LLM para identificar todos os CVEs mencionados e suas severidadesCVEAgent.gerar_relatorio(texto)— Detecta CVEs, consulta detalhes viaCVEConsultante delega geração do PDF aopdf_generator- Retorna JSON estruturado com array
cves_detected
Fluxo típico de uso:
from src.agent.cve_agent import CVEAgent
from src.rag.cve_consultant import CVEConsultant
agent = CVEAgent()
consultant = CVEConsultant()
# 1. Detecta CVEs no texto
deteccao = agent.analisar(texto_do_sistema)
# {"cves_detected": [{"cve_id": "CVE-2026-0049", "severidade": "Medium"}, ...]}
# 2. Consulta todos em lote
resultados = consultant.consultar_multiplos(deteccao["cves_detected"])
# [{"cve": "CVE-2026-0049", "encontrado": true, "workaround": "...", ...}, ...]Saída do CVEAgent.analisar():
{
"cves_detected": [
{"cve_id": "CVE-2026-0049", "severidade": "Medium"},
{"cve_id": "CVE-2026-1115", "severidade": "High"}
]
}Extração de texto de múltiplos formatos de arquivo:
| Extensão | Biblioteca |
|---|---|
.pdf |
pypdf |
.docx / .doc |
python-docx |
.xlsx |
openpyxl |
.xml |
xml.etree.ElementTree / lxml (fallback) |
.json |
json stdlib |
.csv |
csv stdlib |
.txt / .md |
decode UTF-8 direto |
Geração de relatórios técnicos em PDF:
gerar_estrutura(contexto, detalhes_cves)— Chama LLM com schema padronizado e retorna JSON estruturado do relatóriorenderizar_pdf(estrutura)— Renderiza o JSON em PDF via ReportLab com layout completo (capa, cabeçalho, rodapé, badges de severidade coloridos)
Agente de correção automática de vulnerabilidades em repositórios GitLab.
Classe FixAgent:
| Método | Descrição |
|---|---|
executar(gitlab_url, gitlab_token, branch_origem, vulnerabilidades) |
Executa o pipeline completo via LangGraph |
Grafo LangGraph — 9 nós sequenciais:
| Nó | Log prefix | Responsabilidade |
|---|---|---|
autenticar |
[1/9] |
Valida token, obtém project_id, define branch_fix = agent/fix-cve-YYYYMMDD |
obter_vulnerabilidades |
[2/9] |
Usa lista fornecida ou aciona CheckmarxAgent.escanear() |
planejar_fixes |
[3/9] |
LLM analisa vulns → {vuln_id, arquivo, acao, descricao} |
ler_arquivos |
[4/9] |
GitLab API: GET /repository/files/{path}?ref=branch_origem |
gerar_solucoes |
[5/9] |
LLM: descrição de solução por vulnerabilidade (para o relatório) |
gerar_codigo |
[6/9] |
LLM: código corrigido por arquivo (agrupa todas as vulns do arquivo) |
criar_branch |
[7/9] |
GitLab: POST /repository/branches {ref: branch_origem} |
gerar_relatorio |
[8/9] |
ReportLab: PDF com vulns, soluções, diff resumido |
commit_e_push |
[9/9] |
GitLab Commit API: commit atômico de código + PDF |
Prompt para correção de código (msgs_corrigir_codigo):
- Fornece ao LLM: arquivo, todas as vulnerabilidades do arquivo, código original completo
- Instrui: não alterar nada além do necessário, manter lógica de negócio, gerar código funcional
- Guia específico por tipo: SQL Injection → prepared statements; XSS → escape; secrets → env vars
Saída de executar():
{
"branch": "agent/fix-cve-20260603",
"commit_sha": "a1b2c3d4e5f6...",
"vulnerabilidades_encontradas": 8,
"vulnerabilidades_corrigidas": 6,
"arquivos_modificados": ["pom.xml", "src/main/java/UserRepo.java"],
"pdf_path": "relatorio_final_20260603.pdf",
"erro": null
}O retriever usa um score composto normalizado para rankear os CVEs recuperados:
score = (4 × cve_id_match + 3 × coseno_semântico + 2 × year_match + 1 × month_match) / 10
| Componente | Peso | Critério |
|---|---|---|
cve_id_match |
4 | CVE ID exato presente na query |
coseno_semântico |
3 | Similaridade coseno entre embeddings |
year_match |
2 | Ano do CVE presente na query |
month_match |
1 | Mês do CVE presente na query |
Apenas documentos com score >= 0.6 são retornados. Limite padrão: k=6 documentos.
Quando o MongoDB retorna ≤ 1 documento, o pipeline dispara busca web (DuckDuckGo) e só inclui resultados com score de embedding >= 0.6.
| Decisão | Valor | Motivo |
|---|---|---|
temperature LLM (RAG chain) |
0.0 |
Respostas factuais devem ser determinísticas |
temperature LLM (consulta/fallback) |
0.0 |
Idem — sem criatividade em dados de CVE |
temperature LLM (PDF generator) |
0.3 |
Geração de texto técnico aceita leve variação |
| Threshold de score | >= 0.6 |
Balanceia precisão e cobertura |
Semáforo _LLM_SEM |
Semaphore(1) em prompt_config.py |
LM Studio processa uma requisição por vez; evita timeout em cascata |
consultar_multiplos — busca |
8 workers paralelos (I/O, sem LLM) | Busca MongoDB de todos os CVEs antes de acionar o LLM |
consultar_multiplos — LLM |
CVE_BATCH_SIZE CVEs por chamada |
Reduz N chamadas para ⌈N/batch_size⌉ |
consultar_multiplos — fallback |
3 workers paralelos | Fallback/enriquecimento apenas nos CVEs que precisam |
| Índices MongoDB | Criados no load do módulo | Evita recriação a cada sincronizar() |
Hash de conteúdo (MD5) |
descricao + solucao + severidade + data_criacao |
Detecta mudanças reais, ignora campos de infra |
| Re-vetorização | $unset embedding ao atualizar |
Forçada automaticamente na próxima vetorizar() |
| Indexação incremental | desde_ano = último ano em database/ |
Reduz ~350k arquivos para ~30-50k em atualizações rotineiras |
| Parsing paralelo | ThreadPoolExecutor(min(cpu×2, 32)) |
Maximiza I/O em datasets com centenas de milhares de arquivos JSON |
| Vetorização paralela | EMBED_WORKERS=2 workers |
Aproveita APIs de embedding que aceitam múltiplas requisições |
| Token tracking | ContextVar por request + invocar_llm wrapper |
Rastreia uso real sem alterar assinaturas dos módulos |
| Redução de tokens (código) | extrair_secao_codigo(±60 linhas) em fix_agent |
70–90% menos tokens enviados ao LLM em arquivos grandes |
| Truncação exata | truncar_por_tokens(texto, max) via tiktoken |
Evita overflow silencioso por contagem de chars |
- Python 3.11+
- MongoDB rodando localmente (padrão:
localhost:27017) - LM Studio com os modelos carregados:
- LLM: configurado via
LLM_MODELno.env(padrão:meta-llama-3-8b-instruct) - Embeddings:
text-embedding-qwen3-embedding-0.6b(fixo emcve_rag_mongo.py)
- LLM: configurado via
MONGO_DB_USER=
MONGO_DB_PASSWORD=
MONGO_DB_HOST=
MONGO_DB_PORT=
MONGO_DB_CLUSTER=
MONGO_DB_COLLECTION=
LM_STUDIO_API_KEY= # Opcional; fallback para OPENAI_API_KEY ou "unused"
LLM_MODEL=meta-llama-3-8b-instruct
CVE_BATCH_SIZE=5 # CVEs por chamada ao LLM em consultar_multiplos (padrão: 5)python -m venv venv
venv\Scripts\activate
pip install -r requirements.txtpython app.py
# Swagger UI: http://localhost:3000/openapi/swagger
# OpenAPI spec: http://localhost:3000/openapi/openapi.jsonExecute cada etapa em sequência:
# 1. Download e extração
python src/loader/cve_loader.py
# 2. Indexação por mês/ano
python src/loader/cve_indexer.py
# 3. Geração de UUIDs e headers JSON
python src/searcher/cve_resolver.py
# 4. Sincronização com MongoDB + embeddings
python src/rag/cve_rag_mongo.py
# 5. Consulta individual (CLI)
python src/rag/cve_consultant.py --cve CVE-2026-12345Ou via API, envie o main.zip para /atualizar_cves — o pipeline completo (etapas 1–4) é executado automaticamente pelo CVEUpdater.
| Biblioteca | Uso |
|---|---|
| LangChain | Chains, prompts, retrievers, output parsers |
| LangGraph | Orquestração do pipeline de consulta (grafo de nós) |
| PyMongo | Driver MongoDB |
| OpenAI SDK | Compatibilidade com LM Studio (LLM + embeddings) |
| NumPy | Cálculo de similaridade coseno |
| python-dotenv | Configuração via .env |
| requests | Fallback para APIs externas (cve.org, NVD, CIRCL, OSV) |
| ddgs | Busca web DuckDuckGo (fallback de documentos e workaround) |
| pypdf | Extração de texto de arquivos PDF |
| python-docx | Extração de texto de arquivos DOCX/DOC |
| openpyxl | Extração de texto de planilhas XLSX |
| lxml | Parser XML alternativo (fallback do stdlib) |
| ReportLab | Renderização de relatórios técnicos em PDF |
| tiktoken | Contagem de tokens (cl100k_base), truncação precisa e redução de contexto LLM |
| flask-openapi3 | Swagger UI + validação OpenAPI 3.0 integrados ao Flask |
Pipeline Principal (CVE / RAG):
| Método | Rota | Tag | Descrição |
|---|---|---|---|
| POST | /consultar_cve | CVE | Consulta detalhes de um CVE via RAG + LangGraph |
| POST | /consultar_cve_lista | CVE | Consulta múltiplos CVEs em batch |
| POST | /atualizar_cves | Ingestão | Atualiza a base via upload de main.zip |
| POST | /analisar_relatorio | Agent | Extrai CVEs de relatório (PDF, DOCX, TXT, JSON, CSV, XLSX, XML) |
| POST | /extrair_relatorio | Agent | Texto → PDF técnico de vulnerabilidades |
| POST | /analise_extracao_relatorio | Agent | One-shot: arquivo → PDF técnico |
| POST | /checkmarx_pipeline | Agent | Scan Checkmarx One + GitLab → JSON classificado |
Pipeline Lite (/lite):
| Método | Rota | Tag | Descrição |
|---|---|---|---|
| POST | /lite/consultar_vulnerabilidades | Lite | Lista estruturada → workaround por item |
| POST | /lite/analisar_relatorio | Lite | Arquivo → workaround via pipeline lite |
| POST | /lite/analise_extracao_relatorio | Lite | One-shot lite: arquivo → PDF |
| POST | /lite/checkmarx_pipeline | Lite | Scan Checkmarx + workaround (sem APIs CVE externas) |
Pipeline Fix:
| Método | Rota | Tag | Descrição |
|---|---|---|---|
| POST | /fix_pipeline | Fix | Corrige código no GitLab, cria branch, commita PDF e código corrigido |
- Data: 2026-06-03 21:11 UTC
- CVEs indexados: 98
- Inseridos/atualizados no MongoDB: 0
- Vetorizados: 0
- Total no banco: 354663