Ir para o conteúdo

Visão Geral

O Quorum (quorum-sec-scan, v0.8.3) é uma ferramenta CLI/Docker de consensus security scanning: ela orquestra um pool de 12 scanners de segurança open source (Trivy, Grype, Checkov, KICS, Terrascan, tfsec, Regula, Conftest, Dockle, Kubescape, Polaris, kube-score) sobre um alvo, normaliza todos os achados para um modelo canônico, resolve aliases de vulnerabilidade, correlaciona findings equivalentes entre as ferramentas e emite um único relatório que informa quantos e quais scanners detectaram cada problema — acrescido de um score de confiança derivado desse consenso. O Quorum não é mais um scanner: é a camada leve de correlação + consenso sobre as ferramentas que você já confia, projetada para rodar dentro de um pipeline de CI/CD e barrar um build via exit code. Uma camada consultiva opt-in (--advice) pode adicionalmente anexar remediação curada, referências OWASP e — quando explicitamente habilitada — recomendações de IA; ela é apenas de apresentação e nunca altera o núcleo determinístico. Este documento descreve objetivo, problema resolvido, público-alvo, personas, benefícios, diferenciais e casos de uso.

Referências de código verificadas para este documento: README.md, DESIGN.md, cmd/quorum/root.go, cmd/quorum/scan.go, internal/adapter/, crosswalk/.


1. Objetivo do sistema

O objetivo do Quorum é transformar múltiplos relatórios de scanners incompatíveis em um único relatório consolidado e priorizável, no qual cada finding carrega evidência de consenso (quantas e quais engines o detectaram) e um score de confiança calculado, de forma determinística e acionável em CI/CD.

Em termos operacionais, o Quorum entrega:

  1. Orquestração — roda os scanners suportados para o alvo em paralelo, com timeout por scanner.
  2. Normalização — converte a saída de cada ferramenta em um model.Finding canônico (uma única escala de severidade, PURLs para pacotes, AVD/CIS/categoria para controles).
  3. Resolução de aliases — unifica CVE-… e GHSA-… do mesmo bug (apenas para VULN) via aliases locais → cache local → OSV.dev (CVE preferido).
  4. Correlação — agrupa findings equivalentes por um correlationKey determinístico, específico por tipo.
  5. Consenso — calcula detectionCount e confidence (0..1) para cada grupo.
  6. Relatório — emite SARIF (primário), JSON ou XML, sempre com o status por scanner.
target → normalize → resolve aliases → correlate → score → report (SARIF/JSON/XML)

Pipeline conforme DESIGN.md §3 e o estágio-a-estágio descrito no README.md.


2. Problema resolvido

Diferentes scanners encontram problemas sobrepostos mas não idênticos e os reportam em formatos incompatíveis. Quem roda três ferramentas obtém três relatórios, findings duplicados e nenhum sinal sobre quais findings estão corroborados. Daí decorrem dores concretas:

Dor sem o Quorum Como o Quorum resolve
N scanners → N relatórios em formatos distintos Modelo canônico único (model.Finding) + um relatório consolidado
Findings duplicados (o mesmo CVE em Trivy e Grype) Correlação por correlationKey determinístico + dedup
GHSA-… (Grype) e CVE-… (Trivy) tratados como bugs diferentes Alias Resolver unifica para a forma canônica (CVE preferido)
Misconfig de IaC igual em Checkov/KICS/Terrascan/tfsec/Regula sem sinal de convergência Crosswalk regra → controle canônico (hub AVD) correlaciona entre engines
Postura de K8s repetida em Kubescape/Polaris/kube-score sem consolidação Crosswalk k8s.yaml (hub C-#### do Kubescape) correlaciona os três engines
Sem sinal de corroboração entre ferramentas detectionCount + detectedBy + confidence por finding
"0 findings" interpretado como "está seguro" Status por scanner explícito (ran/skipped/unavailable/error/timeout)
Dedup temporal manual entre execuções de CI partialFingerprints["quorum/v1"] = sha256(correlationKey) no SARIF
Imagens/binários de scanner como vetor de supply chain Distribuição assinada keyless (cosign) + atestação SLSA build-provenance + SBOM SPDX atestada

Princípio orientador: false split > false merge. Na dúvida, o Quorum mantém os findings separados e os marca como unmapped — um merge errado esconde risco. (Ver DESIGN.md §6, "Regra do não-match".)

O que o problema NÃO é (escopo)

O Quorum não se propõe a ser:

  • um scanner novo (ele reusa scanners OSS existentes);
  • uma solução de runtime security (modelo de stream, fora de escopo — proposta futura no roadmap);
  • uma plataforma com painel web, daemon ou serviço persistente.

A camada consultiva não muda esse escopo: é opt-in, apenas de apresentação e desligada por padrão. Sem --advice, a saída é byte-idêntica, o núcleo determinístico não tem IA e qualquer recomendação de IA é estritamente opt-in (ver §7 Diferenciais e §9 Premissas).


3. Público-alvo

O Quorum é destinado a equipes que já operam scanners OSS e precisam consolidar e priorizar resultados dentro de pipelines automatizados:

  • Equipes de AppSec / DevSecOps que mantêm security gates em CI/CD.
  • Times de plataforma / engenharia de produtividade que padronizam tooling de segurança entre repositórios.
  • Engenheiros de Cloud/IaC que validam Terraform e manifests K8s multi-cloud (AWS/Azure/GCP) antes do apply.
  • Tech Leads / mantenedores que precisam de um sinal confiável (consenso) para decidir o que bloqueia um merge.
  • Auditores de compliance que precisam de evidência rastreável (controles canônicos AVD/CIS, status por scanner, fingerprints estáveis).

O Quorum é CLI/Docker only: não há frontend web, banco relacional nem API REST HTTP. O núcleo determinístico não tem IA/LLM; uma camada consultiva opt-in (local ou remota) pode ser habilitada, mas fica desligada por padrão (ver §7 Diferenciais e §9 Premissas). O público é, portanto, técnico e centrado em automação.


4. Personas

Persona Objetivo principal Como usa o Quorum Métrica de sucesso
AppSec / DevSecOps Engineer Reduzir ruído e priorizar o que é real Configura --fail-on, --min-severity, .quorumignore; analisa confidence e detectionCount; opcionalmente --advice para remediação Menos falsos positivos no gate; findings corroborados priorizados
Tech Lead / Mantenedor Decidir o que bloqueia o merge sem virar gargalo Usa o gate de PR (exit code 1) e o resumo por severidade no stderr PRs barrados apenas quando há risco corroborado
Auditor de Compliance Evidência rastreável e mapeada a controles Lê SARIF/JSON com partialFingerprints, controles canônicos (AVD/CIS) e status por scanner Trilha de auditoria reproduzível; supressões sempre logadas
Plataforma / CI/CD Padronizar o scan entre N repositórios sem instalar scanners Usa a imagem :full ou o GitHub Action composite (cosign-verificado; socket auto-montado em type: image) Onboarding de repositórios sem instalar tooling local
Engenheiro de Cloud/IaC Validar Terraform/K8s multi-cloud antes do apply quorum scan . --type repo / --type k8s, crosswalk regra→controle (AWS/Azure/GCP + K8s) Misconfig e postura de IaC correlacionadas entre múltiplas engines

5. Benefícios

  • Sinal em vez de ruído. O consenso (detectionCount + confidence) separa findings corroborados de detecções isoladas; a contagem bruta não é confiança — a fórmula pesa diversidade de engine, severidade e confirmação autoritativa (DESIGN.md §9).
  • Consenso além de SCA. A corroboração cruzada não é mais só de vulnerabilidades: cobre misconfig de IaC multi-cloud (Checkov × KICS × Terrascan × tfsec × Regula × Trivy) e postura de Kubernetes (Kubescape × Polaris × kube-score), via crosswalk derivado de output real.
  • Um relatório, vários formatos. SARIF (primário, para GitHub code scanning/DefectDojo), JSON (para processamento) e XML (pipelines legados/JUnit-like).
  • Telemetria opcional. --metrics grava métricas em formato textfile do Prometheus; --log-format json emite logs de progresso estruturados (um objeto por linha) no stderr.
  • Dedup temporal grátis. partialFingerprints["quorum/v1"] permite que ferramentas externas reconheçam o mesmo finding entre execuções.
  • Resiliência operacional. Scanner ausente vira unavailable e é pulado — o scan nunca falha só porque uma ferramenta não está instalada. Timeout/OOM são distinguidos de "não instalado" via probe de versão. Caps de DoS limitam saída (QUORUM_MAX_OUTPUT_BYTES, 512 MiB) e tamanho de alvo (QUORUM_MAX_TARGET_BYTES, 20 GiB).
  • Honestidade sobre cobertura. "0 findings is not proof of safety" é parte do produto: o status por scanner deixa explícito se algo de fato rodou.
  • Gate de CI direto. Exit code: 0 = ok / nenhum finding atingiu --fail-on; 1 = gate disparou; 2 = erro de uso/runtime.
  • Camada consultiva opt-in. --advice anexa templates de remediação curados + referências OWASP (determinístico, sem modelo) e, opcionalmente, uma recomendação em linguagem natural de um provedor local ou remote — sempre rotulada como "AI-generated, advisory only". É apenas de apresentação: nunca toca em correlationKey, fingerprint, confidence, severidade agregada ou o gate de fail-on.
  • Cadeia de suprimentos verificável. Imagens e binários assinados keyless com cosign (OIDC) + atestação SLSA build-provenance + SBOM SPDX atestada, verificáveis no release. O knowledge pack + crosswalk também recebem uma atestação SLSA build-provenance a cada release.
  • Determinismo. correlationKey e Fingerprint = sha256(correlationKey) são funções puras dos dados normalizados → relatórios reproduzíveis.

6. Diagrama de contexto

flowchart TB
    subgraph atores["Atores e gatilhos"]
        dev["Dev / Tech Lead<br/>(PR)"]
        ci["Pipeline CI/CD<br/>(GitHub Action / GitLab)"]
        appsec["AppSec / DevSecOps"]
        auditor["Auditor de Compliance"]
    end

    subgraph quorum["Quorum (CLI / Docker)"]
        orch["Orchestrator<br/>fan-out + timeout + probe"]
        norm["Normalização<br/>model.Finding"]
        alias["Alias Resolver<br/>(VULN)"]
        corr["Correlator<br/>correlationKey"]
        cons["Consensus<br/>detectionCount + confidence"]
        adv["Camada consultiva<br/>(--advice, opt-in)"]
        rep["Reporters<br/>SARIF / JSON / XML"]
    end

    subgraph scanners["Pool de 12 scanners OSS"]
        sca["VULN<br/>trivy · grype"]
        iac["MISCONFIG / IaC<br/>trivy · checkov · kics<br/>terrascan · tfsec · regula · conftest"]
        img["IMG_HARDENING<br/>dockle"]
        k8s["K8S_POSTURE<br/>kubescape · polaris · kube-score"]
    end

    subgraph ext["Serviços e dados externos"]
        osv["OSV.dev<br/>(aliases, opcional)"]
        cw["Crosswalk YAML<br/>aws/azure/gcp/k8s<br/>regra → controle canônico"]
        pol["Rego local<br/>./policy (conftest)"]
        know["Knowledge pack<br/>+ corpus OWASP<br/>(--advice)"]
        llm["Provedor de advice<br/>local/remote (opt-in)"]
        cache[("Cache local<br/>~/.cache/quorum")]
        ghcr["GHCR<br/>imagens assinadas + SLSA + SBOM"]
    end

    subgraph consumidores["Consumidores do relatório"]
        gh["GitHub code scanning"]
        dd["DefectDojo / SIEM"]
        prom["Prometheus<br/>(--metrics)"]
        gate["Build gate (exit code)"]
    end

    dev --> ci
    ci --> orch
    appsec --> orch
    orch --> scanners
    scanners --> norm
    pol --> iac
    norm --> alias
    alias <-->|opcional| osv
    alias <--> cache
    alias --> corr
    cw --> corr
    corr --> cons
    cons --> adv
    know -.->|opt-in| adv
    llm -.->|opt-in| adv
    adv --> rep
    rep --> gh
    rep --> dd
    rep --> prom
    rep --> gate
    gate --> ci
    auditor --> rep
    ghcr -.distribui.-> quorum

7. Diferenciais

Diferencial O que é Onde se vê no produto
Consenso + score detectionCount e confidence (0..1) por finding; confiança pondera diversidade de engine, severidade e confirmação autoritativa properties.detectedBy/detectionCount/confidence no SARIF; DESIGN.md §9
Consenso multi-domínio Corroboração cruzada em VULN, MISCONFIG/IaC multi-cloud e postura K8s — não só SCA Crosswalk aws/azure/gcp.yaml (hub AVD) e k8s.yaml (hub C-#### Kubescape) derivados de output real
false split > false merge Na dúvida, não une findings; controle sem mapeamento fica isolado e unmapped "Regra do não-match", DESIGN.md §6
Transparência de status por scanner Todo relatório expõe ran/skipped/unavailable/error/timeout; probe de versão distingue timeout/OOM/não-instalado Resumo no stderr (cmd/quorum/scan.go, printSummary); "0 findings is not proof of safety"
Correlação determinística correlationKey por tipo + Fingerprint = sha256(correlationKey); partialFingerprints["quorum/v1"] no SARIF DESIGN.md §6, §11
Alias resolution com degradação graciosa CVE/GHSA unificados via OSV.dev; falha de rede não derruba o scan; --offline desliga OSV; cache aliases.json com perm 0600 e schemaVersion DESIGN.md §7; cmd/quorum/scan.go
Camada consultiva opt-in --advice anexa remediação + referências OWASP (determinístico, corpus DIGEST-PINNED) e advice de IA local/remoto opcional; --fix=suggest propõe um patch que deve passar por um re-scan verify-the-fix e nunca aplica sozinho internal/enrich, internal/rag, internal/advisor; docs/13-ia.md
Policy-as-code opt-in conftest avalia o seu Rego de ./policy (ou QUORUM_CONFTEST_ARGS); sem políticas, é reportado como error — opt-in explícito internal/adapter/conftest.go
Passthrough por scanner QUORUM_<SCANNER>_ARGS anexa argumentos ao comando (ex.: QUORUM_CHECKOV_ARGS --bc-api-key destrava políticas Prisma) README.md seção Scanners; inputs *-args na Action
Supply chain assinado e atestado Imagens :full/:slim e binários assinados keyless (cosign/OIDC) + SLSA build-provenance + SBOM SPDX atestada; bases pinadas por sha256; scanners verificados por checksum; o knowledge pack + crosswalk carregam sua própria atestação SLSA; Action composite cosign-verifica antes de rodar README.md seção Install/CI/CD; release.yml, .goreleaser.yaml
Crosswalk plugável YAML regra → controle canônico (AVD/CIS); bundled em /opt/quorum/crosswalk com fallback automático DESIGN.md §8; resolveCrosswalkDir em cmd/quorum/scan.go
Baseline auditável .quorumignore por fingerprint/correlationKey; supressões sempre logadas, nunca descartadas em silêncio README.md seção Baseline; filter.Apply

8. Casos de uso

8.1 Gate de Pull Request (consenso em CI)

Barrar um PR quando houver finding corroborado igual ou acima de um limiar, aceitando riscos já triados via baseline.

# GitHub Actions — via Action composite (cosign-verifica a imagem :full)
- uses: Martinez1991/quorum-sec-scan@v0   # tag móvel v0 avançada por release; pin por @<sha> em produção
  with:
    target: .
    type: repo
    fail-on: high
  • [ ] Defina --fail-on (ex.: high ou critical).
  • [ ] Crie/mantenha .quorumignore para riscos aceitos (com comentário e data).
  • [ ] Faça upload do SARIF para o GitHub code scanning.
  • [ ] Trate exit code 1 como gate e 2 como erro de pipeline.

8.2 Scan de imagem (SCA / vulnerabilidades)

Consenso de SCA sobre uma imagem de container, com aliases CVE/GHSA unificados.

quorum scan myimage:1.2.3 --type image --scanners trivy,grype --fail-on critical
  • [ ] Use trivy + grype para corroboração de VULN.
  • [ ] Mantenha --offline se o ambiente não puder acessar a OSV.dev (usa aliases locais + cache).
  • [ ] Para imagem local via :full/Action, compartilhe o socket do Docker (auto-montado em type: image na Action) — sem isso, o scan cai em pull e reporta falso-zero.

8.3 Infraestrutura como Código (IaC / misconfig multi-cloud)

Consenso de misconfig sobre Terraform (AWS/Azure/GCP), com SARIF para code scanning.

quorum scan . --type repo --format sarif -o quorum.sarif
  • [ ] Aproveite o consenso entre Checkov, KICS, Terrascan, tfsec, Regula e Trivy (tfsec emite AVD nativo e auto-correlaciona com Trivy).
  • [ ] Garanta que o crosswalk (crosswalk/{aws,azure,gcp}.yaml) mapeie as regras para o controle canônico (AVD).
  • [ ] Opcional: adicione seu Rego em ./policy para acionar conftest (policy-as-code).
  • [ ] Opcional: adicione --advice para anexar remediação + referências OWASP por finding (determinístico; nenhum dado sai do host).
  • [ ] Lembre-se: regra sem mapeamento fica unmapped (não é chutada).

8.4 Postura de Kubernetes (K8s posture, multi-engine)

Avaliação de postura sobre manifests K8s, com consenso entre três engines.

quorum scan ./k8s --type k8s --format json -o quorum.json
  • [ ] Use --type k8s para acionar kubescape, polaris e kube-score (crosswalk k8s.yaml, hub C-#### do Kubescape).
  • [ ] O crosswalk cobre privilege-escalation, privileged, non-root, limites de CPU/memória, probes, read-only-fs, linux-hardening, automount de service account, network-policy, host-network, host-PID/IPC, capabilities e secrets.
  • [ ] RBAC segue single-engine (o RBAC do Kubescape exige contexto de cluster; documentado).
  • [ ] Processe o JSON (findings + resumo por scanner + rollup de severidade) downstream.

8.5 Telemetria em CI (métricas Prometheus)

Exportar métricas do scan para observabilidade.

quorum scan . --type repo --metrics quorum.prom --log-format json
  • [ ] Colete quorum.prom como textfile do node_exporter/pushgateway.
  • [ ] Use --log-format json para ingestão estruturada dos logs de progresso.
  • [ ] Sob --advice, surgem métricas extras (quorum_advice_enriched, quorum_advice_provider, quorum_advice_fix) — incluindo a taxa verify-the-fix.

Distribuição: imagem :full (todos os 12 scanners, linux/amd64, grype DB pré-cacheado que não expira) para CI self-contained; :slim (orquestrador apenas, amd64+arm64) quando os scanners já estão no PATH. Binários nativos via GoReleaser. Todas as imagens/binários são assinados (cosign) e atestados (SLSA + SBOM SPDX).


9. Premissas

  • Versão. Documento alinhado à v0.8.3 (revisão 2026-07-04); flags, exit codes, scanners e comandos refletem cmd/quorum/scan.go, cmd/quorum/root.go e internal/adapter/ lidos no momento da redação (a versão é injetada no build/release).
  • Escopo de produto. O Quorum é CLI/Docker only. Não há frontend web, banco de dados relacional, API REST HTTP nem autenticação/contas de usuário. Itens correspondentes em templates enterprise são tratados como N/A por decisão de arquitetura (orquestrador stateless que se integra a CI/CD, não um serviço).
  • O núcleo não tem IA; a camada consultiva é opt-in. O núcleo determinístico não tem IA. Uma camada consultiva opt-in (--advice) pode anexar remediação curada + referências OWASP (determinístico, sem modelo) e, quando explicitamente habilitada, recomendações de IA local (--advice-provider=local) ou remota (--advice-provider=remote). Ela fica desligada por padrão, é apenas de apresentação e nunca toca em correlationKey/fingerprint/confidence/severidade agregada/o gate de fail-on; sem --advice a saída é byte-idêntica (ver docs/13-ia.md).
  • Runtime security é N/A no presente. Modelo de stream (Falco/Tetragon) está fora de escopo; aparece apenas como proposta futura no roadmap do README.md/DESIGN.md.
  • Consenso por domínio. VULN é compartilhado por grype + trivy; MISCONFIG/IaC por trivy + checkov + kics + terrascan + tfsec + regula (+ conftest, policy-as-code); K8S_POSTURE por kubescape + polaris + kube-score; IMG_HARDENING é dockle-only (sem par para consenso ainda). O RBAC do Kubescape segue single-engine por exigir contexto de cluster.
  • Policy-as-code é opt-in. O conftest não tem regras embutidas: sem Rego em ./policy (ou via QUORUM_CONFTEST_ARGS), ele é reportado como error — comportamento esperado.
  • Dependência opcional de rede. A resolução de aliases via OSV.dev é opcional e degrada graciosamente; --offline a desabilita. O scan não depende de conectividade para concluir. Da mesma forma, os provedores de IA da camada consultiva são opcionais: se o modelo estiver inacessível, o relatório sai sem advice de IA e o scan nunca falha; o remote exige consentimento explícito (--advice-allow-egress) e é bloqueado por --offline.
  • Catálogos derivados de output real. Os mapeamentos do crosswalk (AVD/CKV, UUIDs de KICS, C-#### de Kubescape) foram derivados de output real dos scanners em demos Terraform/K8s sob a regra false split > false merge, mas devem ser conferidos contra os catálogos oficiais antes de produção (conforme nota no README.md e DESIGN.md §8).
  • Cadeia de suprimentos como fronteira de confiança. Binários de scanner embutidos na imagem :full fazem parte do trust boundary; a release endurece isso com bases pinadas por sha256, scanners verificados por checksum, assinatura cosign, atestação SLSA build-provenance e SBOM SPDX. O knowledge pack + crosswalk carregam sua própria atestação SLSA (verifique com gh attestation verify knowledge/owasp/corpus.yaml). Para produção, recomenda-se pinar por digest e verificar assinaturas/atestações.
  • confidence/correlationKey determinísticos. Os valores de confiança e as chaves de correlação são funções dos dados normalizados; mudanças de versão de scanner podem alterar a entrada e, consequentemente, a saída.
  • Caps de DoS. Saída por scanner é limitada por QUORUM_MAX_OUTPUT_BYTES (512 MiB) e o tamanho do alvo em disco por QUORUM_MAX_TARGET_BYTES (20 GiB; 0 desabilita).