Calibração de scanners de segurança

Bench de 35 scanners contra 3 alvos vulneráveis canônicos (DVWA, WebGoat, Juice-Shop) para definir as stacks estática e dinâmica a aplicar nos 25 924 containers de high-impact (high-pull-count ∪ high-dependency-weight) da metodologia Dr. Docker / DITector. Wall-time agregado: 2.7 h.

Calculadora interativa

Ajuste o número de containers e máquinas. Marque os scanners que entram na stack. O custo total se atualiza em tempo real. Premissa: distribuição uniforme da carga, sem overhead de orquestração.

Carga
containers a escanear25.924
máquinas em paralelo10
Presets
Modelo de tempo
Scanners ativos
Wall-time estimado
Tempo por imagem (max estáticos ⊕ max dinâmicos)
Pico de RAM em um nó
Findings totais estimados
Modelo de tempo (selecionável acima): paralelo — scanners do mesmo modo rodam concorrentes no nó (CPU-light/IO-bound), custo da fase = scanner mais lento: per_image = max(estáticos) + max(dinâmicos) + 10s. sequencial — um após o outro, custo = soma: per_image = Σ(estáticos) + Σ(dinâmicos) + 10s×N_din. Estático e dinâmico são sequenciais entre si em ambos (precisa docker run antes do scan dinâmico). Wall-time total: (N / M) × per_image. RAM mostrada é o pico de UM scanner — em paralelo, some as RAMs ativas para dimensionar o nó.

Onde cada scanner se posiciona

Cada bolha é um scanner. Eixo X: tempo médio por imagem (escala log). Eixo Y: findings totais nos 3 alvos (escala log). Tamanho: pico de RAM. Cor: modo. Canto inferior-direito = caro e pouco produtivo; canto superior-esquerdo = barato e produtivo.

estático dinâmico tamanho ∝ pico RAM
Leitura: Trivy e Grype dominam o canto produtivo (alto Y, X moderado). Dockle e TruffleHog aparecem como joias raras — alto sinal por baixo custo. Nuclei está no fundo direito (caro), mas cobre vetor que ninguém mais cobre. ZAP é o ponto crítico de RAM — bolha grande no topo direito.

Tempo de execução em escala

Wall-time esperado para cobrir N containers em M máquinas. Escala de cor logarítmica: claro = rápido (minutos/horas), escuro = lento (meses/anos).

Stack estática syft + grype + trivy + trufflehog + dockle
Stack dinâmica leve nmap + zap baseline (sem nuclei)
Stack dinâmica completa nmap + nuclei + zap baseline
Observação prática: a estática em 100 % do crawl (12M repos) é inviável bruto-força mesmo com 20 máquinas. Plano realista: amostragem por estrato (high-pull, high-weight, sample do resto) ou aproveitar o grafo IDEA já construído para deduplicar SBOMs em layers compartilhadas.

Severidade — quanto é ruído vs sinal

Cada card mostra o scanner com 3 barras (uma por alvo). Cor codifica severidade. Total à direita. Ler horizontalmente: o scanner tem comportamento estável entre alvos? Ler dentro da barra: qual a fração de criticidade real (vermelho/laranja) vs ruído (cinza/info)?

trivy static

Vuln (CVE+IaC+secrets+misconfig)
dvwa
1.575
juice-shop
98
webgoat
487

grype static

Vuln (CVE)
dvwa
2.097
juice-shop
93
webgoat
723

zap dynamic

Web App (DAST + proxy)
dvwa
21
juice-shop
15
webgoat
16

nuclei dynamic

Web Vuln (templates)
dvwa
29
juice-shop
8
webgoat
0

dockle static

Container Linter
dvwa
5
juice-shop
5
webgoat
3
Insights: DVWA acumula 254 CRITICAL e 551 HIGH no Trivy — base PHP/Apache antiga. Juice-Shop tem perfil oposto: poucos CVE de pacote, mas concentração em segredos vazados (90 detecções TruffleHog, incluindo chave RSA privada). Trivy e Grype divergem ~30 % nos mesmos alvos: bancos de CVE diferentes. Para o paper, manter os dois como OR set e investigar divergências.

Detalhes por scanner — vulnerabilidades completas

Cada aba abre o output bruto do scanner com filtros, sort, busca e drill-down por finding. Estatísticas e gráficos são específicos daquele scanner — não são comparáveis cross-tool por causa da heterogeneidade de schema.

Matriz de cobertura

Categorias monocobertura (apenas 1 scanner cobre) são insubstituíveis. Sobreposição alta significa redundância — manter um, descartar os demais ou usar como cross-validation.

scannermodoSBOMCVESecretsMisconfigIaCWeb/DASTNetworkReconMalware
clamavstatic········
docklestatic········
gitleaksstatic········
grypestatic·······
semgrepstatic·······
niktodynamic·······
nmapdynamic·······
nucleidynamic······
openvasdynamic·······
sqlmapdynamic········
syftstatic········
trivystatic····
trufflehogstatic········
wapitidynamic········
whatwebdynamic········
zapdynamic········
arachnidynamic········
cdxgenstatic········
checkovstatic·······
clairstatic········
dependency-checkstatic········
detect-secretsstatic········
govulncheckstatic········
guarddogstatic·········
hadolintstatic········
httpxdynamic·······
jaelesdynamic········
kube-linterstatic········
osvstatic·······
pip-auditstatic········
retirestatic········
secretscannerstatic········
testssldynamic········
whispersstatic········
yarastatic········

Stacks recomendadas para o paper

Baseado nos resultados do bench (35 scanners × 3 alvos canônicos). Decisões mapeadas para o pipeline DITector — fases I (crawl) e II (grafo IDEA) definidas; estes scanners alimentam a fase III (análise dos ~25 924 high-impact).

📦 Fase III-A — Estática (amortizável em todos os repos crawled)

Filesystem-only, paraleliza trivialmente. Custo médio < 4 min/imagem com toda a stack rodando concorrente.

  • Syft — SBOM canônico (1.691 componentes médios); insumo de Grype
  • Grype + Trivy ⭐ — CVE primário + secundário (2.913 + 2.160 findings; divergem ~30 % nos mesmos alvos — bancos diferentes, manter como OR-set)
  • OSV-Scanner ⭐ — DB ecosystem-native (Go/Rust/Cargo); 1.240 CVEs, muitas ortogonais ao NVD
  • Clair ⭐ — terceira opinião CVE layer-indexed (Quay); útil quando Trivy ≠ Grype
  • Semgrep ⭐ — único SAST do stack; 258 findings no source-code (SQLi/XSS/path-traversal/hardcoded), ~30 linguagens
  • TruffleHog — secrets verificados via API (116 confirmados; baixo FP)
  • detect-secrets ⭐ — baseline-diffable (2.571 hits — útil pra triagem inicial; alto ruído sem baseline)
  • Dockle + Hadolint ⭐ — hardening CIS + Dockerfile lint (13 + 9 findings)
  • Checkov ⭐ — IaC misconfig, 1000+ políticas (24 failed checks)
  • retire.js ⭐ — JS libs vendoradas fora do package.json (47 vulns)
  • OWASP Dependency-Check ⭐ — CPE-matching, forte em Java/Maven (NVD + OSS Index)

🌐 Fase III-B — Dinâmica (aplicar nos ~25 924 high-impact)

docker run + scan + docker rm. Mais caro: ZAP/Nuclei são minutos; OpenVAS são ~40 min/alvo.

  • Nmap — port + service + NSE vuln,safe (não-disruptivo)
  • Nuclei — CVEs web por templates YAML (37 findings; comunidade ativa, CVEs recentes)
  • ZAP baseline — DAST passivo (52 findings; padrão de mercado)
  • Arachni ⭐ — DAST cross-validation independente do ZAP (31 issues; archived 2017 mas plugins ainda úteis)
  • OpenVAS ⭐ — agora executado: 327 findings (2 high, 4 medium, 6 low, resto log; severity 8.1). Caveat: ~40 min/alvo — só viável com orquestração paralela séria a 25 k images
  • httpx ⭐ — recon enxuto (fingerprint + TLS/JARM/CDN); substitui WhatWeb

🦠 Especializada — aplicar onde o sinal estático justifica

Não rodar em tudo; gatilhar por heurística.

  • ClamAV + YARA ⭐ — assinatura + regras custom (cryptominers, reverse-shells, chaves embedded; YARA: 15 matches; paper Dr. Docker achou 24 miners)
  • SQLMap — só em endpoints já sinalizados por ZAP/Nuclei (1 SQLi confirmada em Juice-Shop)
  • testssl.sh ⭐ — quando o alvo expõe HTTPS (no bench todos são HTTP → baseline "no TLS")
  • govulncheck ⭐ — imagens com binários Go (reachability; 0 no bench — alvos Node/PHP/Java)
  • pip-audit ⭐ — imagens com Python (0 no bench — sem requirements.txt detectável)
  • kube-linter ⭐ — imagens que bundlam manifests K8s/Helm (0 no bench — alvos não trazem YAML)
  • cdxgen ⭐ — SBOM CycloneDX 1.5 deep-monorepo (Maven/Gradle/Bazel); alt ao Syft quando build-tools presentes
  • GuardDog ⭐ — supply-chain malice em deps npm/PyPI (0 no bench — sem typosquatting; valioso em produção real)

❌ Excluir / sobrepostos / quebrados

Custo > benefício neste contexto, ou wrapper precisa de retrabalho.

  • Nikto — tecnologia anos 2000; 165 findings mas alto ruído em apps modernas; coberto por Nuclei
  • Wapiti — sobreposto a ZAP/Nuclei (33 findings; crawling fraco em SPAs)
  • WhatWeb — 0 fingerprints no bench (Host-header mismatch?); httpx substitui com vantagem
  • GitLeaks — sobreposto a TruffleHog (16 findings, regex puro sem verificação); manter só como fallback de RAM (TruffleHog usa ~2,3 GB)
  • SecretScanner (Deepfence) — binário exige AVX2; Illegal instruction em CPUs antigas (gpu1 e a9 caíram). Inviável sem garantir hardware
  • Jaeles — 0 findings; comunidade menor que Nuclei; templates exigem config init
  • Tsunami (Google) — image oficial só em GHCR privado; substituído por Arachni/Jaeles

Catálogo

Descrição, autor, link, prós e contras. Tempo e RAM são médias dos 3 alvos.

cdxgen static

SBOM (OWASP) · OWASP CycloneDX · repo
19stempo
898 MBRAM
1.748findings

Gerador SBOM CycloneDX 1.5 multi-language com VEX support.

+ Coverage profunda em Maven/Gradle/Bazel.

Requer toolchain do build instalada.

checkov static

IaC misconfig · Bridgecrew / Prisma · repo
1.2 mintempo
547 MBRAM
24findings

Checkov: 1000+ políticas de IaC + Dockerfile + SCA misconfig.

+ Coverage maior que Trivy/Dockle.

Heavy: 700MB image.

clair static

Vuln (CVE per layer) · Red Hat / Quay · repo
8stempo
RAM
0findings

Scanner CVE com arquitetura layer-by-layer indexed.

+ Layer-indexing dedup natural em registries.

clair-action standalone exige DB pré-baixado.

dependency-check static

Vuln (CPE matching) · OWASP · repo
31stempo
908 MBRAM
268findings

OWASP Dependency-Check: motor de correlação CPE-based contra NVD.

+ OWASP project. NVD + OSS Index dual-feed.

Lento (download NVD ~30+ min).

detect-secrets static

Secrets (baseline) · Yelp · repo
2.2 mintempo
734 MBRAM
2.571findings

Scanner de secrets baseline-diffable — emite JSON de estado atual e diff contra runs futuros.

+ Modelo baseline reduz noise drastically.

Não verifica live. Plugins podem ter FP altos.

dockle static

Container Linter · goodwithtech · repo
46stempo
25 MBRAM
0findings

Container Linter

+

grype static

Vuln (CVE) · Anchore · repo
2.6 mintempo
429 MBRAM
0findings

Vuln (CVE)

+

hadolint static

Dockerfile lint · Lukas Martinelli · repo
2stempo
RAM
9findings

Hadolint: linter de Dockerfile com regras de boas-práticas e shellcheck.

+ Shellcheck nas RUNs detecta classes de bugs únicos.

Reconstrução via history perde COPY/ADD targets.

osv static

Vuln (OSV.dev) · Google · repo
1.5 mintempo
214 MBRAM
1.240findings

Scanner que casa pacotes contra a base OSV.dev — agregador de advisories ecosystem-native.

+ DB ecosystem-native. Mantida pelo Google.

Coverage menor de SO packages vs Trivy/Grype.

retire static

Vuln JS (hash/version) · Erlend Oftedal · repo
10stempo
86 MBRAM
47findings

retire.js: detecta libs JS vulneráveis casando hash/version dos arquivos .js.

+ Detecta libs vendored fora do dependency manifest.

Só JS client-side.

semgrep static

SAST (código-fonte) · Semgrep Inc. (r2c) · repo
2.8 mintempo
1.0 GBRAM
258findings

Semgrep: análise estática de código-fonte com regras de pattern + dataflow. Único SAST do stack — todo o resto inspeciona container/binário/serviço, nenhum lê código.

+ Único SAST OSS no stack. ~30 linguagens. Registry de regras enorme e curado. CWE/OWASP mapping. Rápido (não compila).

Pattern-based: não pega tudo que análise full-compile pega (CodeQL/SonarQube). FP em regras genéricas sem tuning.

syft static

SBOM · Anchore · repo
2.0 mintempo
527 MBRAM
0findings

SBOM

+

trivy static

Vuln (CVE+IaC+secrets+misconfig) · Aqua Security · repo
6.6 mintempo
308 MBRAM
0findings

Vuln (CVE+IaC+secrets+misconfig)

+

trufflehog static

Secret (verificado) · Truffle Security · repo
53stempo
2.3 GBRAM
0findings

Secret (verificado)

+

clamav static

Antivírus · Cisco Talos · repo
4.5 mintempo
1.1 GBRAM
0findings

Antivírus

+

gitleaks static

Secret (regex) · Zachary Rice · repo
1.8 mintempo
82 MBRAM
0findings

Secret (regex)

+

govulncheck static

Vuln Go (reachability) · Google (Go team) · repo
2stempo
RAM
0findings

Scanner de CVE para Go com reachability analysis.

+ Único scanner reachability-aware no stack.

Só Go.

guarddog static

Supply-chain malware · Datadog · repo
20stempo
256 MBRAM
0findings

Detecta supply-chain malice em pacotes npm/PyPI.

+ Único scanner do stack focado em malice (não vulnerabilidade).

Limitado a npm e PyPI.

kube-linter static

K8s manifest issues · StackRox / Red Hat · repo
0stempo
RAM
0findings

StackRox kube-linter: lint de YAMLs Kubernetes para best practices.

+ K8s-specific.

Skip silently se imagem não traz YAML.

pip-audit static

Vuln Python (PyPA) · PyPA · repo
8stempo
71 MBRAM
0findings

pip-audit: scanner de CVE Python autoritativo (PyPA Advisory DB).

+ Autoridade direta (PyPA).

Só Python.

whispers static

Secrets (configs) · Adam Listek · repo
27stempo
163 MBRAM
6.034findings

Whispers: parser de configs estruturados (YAML/JSON/Dockerfile).

+ Structured-aware: menos FP que regex em YAML/JSON.

Sensibilidade alta gera ruído.

yara static

Malware/pattern · VirusTotal · repo
23stempo
48 MBRAM
15findings

Engine genérico de pattern-matching para classificar binários e textos.

+ Extensível com regras próprias. Padrão da indústria malware-research.

Rules precisam ser escritas/curadas.

arachni dynamic

Web App (DAST) · Sarosys · repo
2.1 mintempo
506 MBRAM
31findings

Arachni: framework Ruby DAST com checks profundos para SQLi/XSS/RFI/LFI.

+ Suite completa similar a ZAP.

Projeto archived (último release 2017).

httpx dynamic

Web fingerprint · ProjectDiscovery · repo
24stempo
182 MBRAM
3findings

httpx: prober web fast — fingerprint, TLS, JARM, CDN.

+ Fast. Multi-feature em um binário.

Apenas fingerprint, não scan de vulns.

nmap dynamic

Network Scanner · Gordon Lyon (Fyodor) · repo
50stempo
35 MBRAM
0findings

Network Scanner

+

nuclei dynamic

Web Vuln (templates) · ProjectDiscovery · repo
22.9 mintempo
1.1 GBRAM
0findings

Web Vuln (templates)

+

openvas dynamic

Network Vuln (NASL) · Greenbone · repo
41.9 mintempo
5.1 GBRAM
327findings

Greenbone Vulnerability Manager. 100k+ plugins NASL. Equivalente open-source ao Nessus.

+ Cobertura imensa de CVEs em serviços de rede. Padrão em compliance.

Setup pesado: bootstrap + sync de feed leva 20-30 min. Scan completo ~39 min para um alvo.

zap dynamic

Web App (DAST + proxy) · OWASP · repo
3.5 mintempo
11.1 GBRAM
0findings

Web App (DAST + proxy)

+

jaeles dynamic

Web Vuln (signatures) · j3ssie · repo
1.1 mintempo
564 MBRAM
0findings

Jaeles: scanner web template-driven, similar a Nuclei.

+ Template-driven.

Comunidade menor que Nuclei.

sqlmap dynamic

SQLi especializado · Bernardo Damele · Miroslav Stampar · repo
13stempo
40 MBRAM
0findings

SQLi especializado

+

testssl dynamic

TLS/SSL audit · Dirk Wetter · repo
20stempo
20 MBRAM
6findings

testssl.sh: auditoria abrangente de TLS/SSL via OpenSSL.

+ Mais detalhado que Nessus/OpenVAS para TLS.

Targets HTTP retornam baseline 'no TLS'.

nikto dynamic

Web Vuln (legado) · Chris Sullo · repo
6.3 mintempo
67 MBRAM
0findings

Web Vuln (legado)

+

wapiti dynamic

Web Vuln (DAST) · Nicolas Surribas · repo
54stempo
201 MBRAM
0findings

Web Vuln (DAST)

+

whatweb dynamic

Web Fingerprint · urbanadventurer · repo
10stempo
RAM
0findings

Web Fingerprint

+

secretscanner static

Secrets (container) · Deepfence · repo
1stempo
RAM
0findings

Scanner de secrets focado em containers. ~140 regras YARA-style.

+ Container-native, sem precisar exportar FS.

Binário precisa AVX2 — falha em CPUs antigas.

Defeitos do bench

Pontos que o leitor deve saber antes de tirar conclusões. São limitações do dataset/execução, não necessariamente dos scanners.

OpenVAS executado nos 3 alvos. 327 findings totais (juice-shop 70, DVWA 161, WebGoat 96; severity máx 8.1; severidades dominadas por "Log" — informacionais). Wall time ~39 min/alvo após sync de NVT (~20 min, uma vez). Tomou 5 iterações de fix até estabilizar: TLS-mode em vez de socket, docker exec --user gvm, port_list resolvido por nome, SKIPSYNC=false, sem GVMD_ARGS multi-palavra (bug no single.sh do immauss). Não escalável a 25 k images sem orquestração paralela séria — ~2,5 h só de OpenVAS por lote de 3.
5 scanners sem findings no bench — mas por ausência de input, não bug: govulncheck (0 — alvos são Node/PHP/Java, nenhum binário Go), pip-audit (0 — nenhum requirements.txt detectável), kube-linter (0 — nenhum manifest K8s), guarddog (0 — nenhuma dep com indicador de typosquatting/install-script malicioso), jaeles (0 — signatures não casaram). Todos gravam um JSON-sentinela explicando. Em imagens reais do domínio deles produzem sinal.
SecretScanner (Deepfence) não roda nas máquinas do bench. O binário exige instrução AVX2; Illegal instruction em CPUs sem (gpu1 e a9). Status registrado como error. Inviável sem garantir hardware com AVX2 — único scanner do stack com requisito de CPU.
WhatWeb retornou 0 fingerprints em todos os alvos. Provável mismatch de Host-header ou janela de amostragem do coletor de métricas abaixo da duração da execução (~10 s). httpx (substituto recomendado) fingerprinta os mesmos alvos sem problema.
Ruído alto em alguns secret/SAST scanners: Whispers 6 034 findings, detect-secrets 2 571, Semgrep 258 — vs 116 do TruffleHog (verificado via API). Whispers/detect-secrets/Semgrep precisam de baseline ou tuning de regras antes de virar gate; TruffleHog já é low-FP por verificar.
Heterogeneidade de schema entre scanners. Severidades em HIGH (Trivy), High (Grype), high (Nuclei), "Medium (Medium)" (ZAP), Critical/Alarm/Log (OpenVAS), ERROR/WARNING/INFO (Semgrep). Agregação cross-tool exige normalização explícita — o relatório normaliza só para os gráficos, não para um score unificado.
Dataset misto. Os 14 scanners originais vieram de uma corrida anterior (reports-scanners-20260507T175432Z); os 21 novos (incluindo Semgrep) rodaram em gpu1+a9 e foram mesclados no layout reports/scans-output/<alvo>/<scanner>/. Wall-times não são estritamente comparáveis entre as duas levas (hardware/condições diferentes).

Varredura em massa — corpus LabVulnerabilities (145 containers)

145 imagens de container vulneráveis varridas pela bateria estática distribuída em duas máquinas (pipeline ChimangoScan/scanners). Dos 8 scanners agendados, 6 produziram achadossyft, trivy, grype, osv, dockle, trufflehog — e cada finding traceia para a imagem e o IP do container. Abaixo, um painel por scanner no mesmo formato da aba Por scanner: cards, donut de severidade, distribuição CVSS, severidade × container, por ecossistema, top pacotes, top CVE e a tabela.

containers escaneados
145 / 145
todos com IP de container resolvido
findings consolidados
475.937
após dedup cross-scanner
críticos · altos
15.811 · 65.731
+ 191.006 médios · 62.617 baixos
scanners com saída
6 / 8
semgrep falhou (erro de config) · clamav parcial (removido por lentidão)
relógio de parede
1.89 h
77 containers/h · 5.54× paralelismo efetivo
CPU-segundos de scanner
37.680
10.5 h-CPU somadas · mediana 171 s/container

Severidade × categoria — corpus consolidado

Distribuição dos findings consolidados por severidade (linhas) × categoria de detecção (colunas). O grosso é vulnerabilidade de pacote (CVE); sbom-component aparece só como info.

severidadepkg-vulnsecretimage-configsbom-componenttotal
critical15.8074··15.811
high65.50877146·65.731
medium187.7313.129146·191.006
low62.084·533·62.617
info40.304··43.55383.857
unknown56.915···56.915
total428.3493.21082543.553475.937
Por que image-config soma 825 e o painel do Dockle mostra 636? 825 é o total da categoria no corpus consolidado (inclui misconfigs reportadas por outros scanners); o painel do Dockle é o subconjunto found_by ⊇ dockle — bate com scanner_stats.dockle.merged_findings = 636.

Detalhes por scanner — corpus de 145 containers

Cada aba abre os achados daquele scanner sobre os 145 containers, com cards, gráficos específicos e a tabela (amostra de até 500 linhas por scanner — o conjunto completo está em findings.jsonl e em out/<container>/<scanner>/). Estatísticas e gráficos são específicos daquele scanner — não são comparáveis cross-tool por heterogeneidade de schema.

DIT — varredura em andamento live

Estado em tempo (quase) real das varreduras de produção sobre imagens do Docker Hub, executadas pelo pipeline ChimangoScan/scanners em três máquinas. Os números abaixo vêm de dit-live.json, atualizado automaticamente a cada 30 min a partir dos coordenadores de fila.

Carregando estado da varredura…
Atualiza a cada 30 min. Detalhe por scanner do corpus de 145 containers: aba “Varredura em massa”. Pipeline: github.com/ChimangoScan/scanners.