Requisitos Não Funcionais¶
Este documento especifica os Requisitos Não Funcionais (RNF) do Quorum
(quorum-sec-scan), versão v0.2.3. O Quorum é uma ferramenta de consensus
security scanning distribuída como CLI e imagem Docker — sem frontend web,
sem banco de dados, sem API REST, sem autenticação de usuário e sem IA/LLM. Ele
orquestra um pool de scanners OSS (Trivy, Grype, Checkov, KICS, Dockle,
Kubescape), normaliza tudo para um modelo canônico (model.Finding), resolve
aliases de vulnerabilidade, correlaciona findings equivalentes, calcula um score
de confiança (consenso) e emite SARIF/JSON/XML.
Por ser um binário/imagem de execução efêmera (não um serviço de longa duração), vários RNF clássicos de produtos SaaS não se aplicam diretamente. Onde for o caso, o requisito é declarado explicitamente como N/A com justificativa técnica, e — quando agregar valor — acompanhado de uma Proposta futura claramente separada. A natureza arquitetural do produto está descrita em 01-visao-geral.md e 04-arquitetura.md (crie-os se ainda não existirem); o modelo de dados, a matriz de correlação e a matemática do consenso estão em DESIGN.md.
Convenção de criticidade dos RNF: P0 = essencial (release bloqueia se violado), P1 = importante, P2 = desejável.
1. Panorama dos RNF¶
mindmap
root((RNF Quorum))
Performance
Fan-out paralelo
Timeout por scanner
Probe de versão 60s
Grype DB pré-cacheado
Escalabilidade
CLI stateless
Escala horizontal nos runners
Disponibilidade
N/A servico
Distribuicao GHCR/Releases
Seguranca
Supply chain
Imagens assinadas cosign
SLSA provenance
Sem segredos
Observabilidade
Logs stderr
Status por scanner
Auditoria
Relatorio como evidencia
Fingerprints
Conformidade
LGPD
PCI DSS
ISO 27001
OWASP ASVS / Top 10
Resiliencia
Degradacao graciosa
Continuidade
Stateless
Artefatos reproduziveis
| # | Categoria | Aplicabilidade | Prioridade | Resumo |
|---|---|---|---|---|
| 2 | Performance | Aplicável | P0 | Paralelismo, timeouts, DB pré-cacheado |
| 3 | Escalabilidade | Aplicável | P1 | CLI stateless, escala horizontal em CI |
| 4 | Disponibilidade | Reinterpretado | P1 | Não é serviço; vale a distribuição |
| 5 | Segurança | Aplicável | P0 | Supply chain, assinaturas, sem segredos |
| 6 | Observabilidade | Aplicável | P1 | Logs em stderr, status por scanner |
| 7 | Auditoria | Aplicável | P1 | Relatório como evidência, fingerprints |
| 8 | LGPD | Aplicável (por exclusão) | P1 | Sem PII processada |
| 9 | PCI DSS | N/A como produto | P2 | Pode auxiliar compliance |
| 10 | ISO 27001 | Mapeamento parcial | P2 | Controles aplicáveis ao binário/pipeline |
| 11 | OWASP ASVS | Subconjunto CLI | P1 | Controles relevantes a um CLI |
| 12 | OWASP Top 10 | Aplicável ao próprio artefato | P0 | Risco do binário/imagem, não do alvo |
| 13 | Resiliência | Aplicável | P0 | Degradação graciosa |
| 14 | Backup/DR/RTO/RPO | N/A (stateless) | P2 | Artefatos reproduzíveis |
| 15 | SLA/SLO/SLI | Definido | P1 | Uso em CI e pipeline de release |
2. Performance¶
O Quorum é dominado por I/O e por subprocessos (cada scanner é um binário
externo invocado via exec). O tempo de parede de um scan é, na prática,
max(tempo de cada scanner) + overhead de correlação/consenso, porque os
adapters rodam em paralelo.
2.1 Paralelismo (fan-out)¶
O orquestrador dispara uma goroutine por adapter e agrega os resultados sob
mutex (internal/orchestrator/orchestrator.go, Run):
flowchart LR
T[target] --> O[Orchestrator.Run]
O -->|goroutine| A1[trivy.Run]
O -->|goroutine| A2[grype.Run]
O -->|goroutine| A3[checkov.Run]
O -->|goroutine| A4[kics.Run]
O -->|goroutine| A5[dockle.Run]
O -->|goroutine| A6[kubescape.Run]
A1 & A2 & A3 & A4 & A5 & A6 --> W[wg.Wait + mutex agrega]
W --> C[Correlator.Enrich]
C --> M[consensus.Merge]
M --> R[Reporter SARIF/JSON/XML]
Implicações de performance:
- Escalonamento por scanner mais lento, não pela soma. Adicionar um scanner rápido a um conjunto que já contém um lento não altera muito o tempo total.
- A fase de correlação/consenso é in-process e CPU-leve (agrupamento por
correlationKeyem mapas,sha256por chave) — desprezível frente aos scanners. - A resolução de aliases pode adicionar latência de rede (OSV.dev). Mitigada
por cache local (
~/.cache/quorum/aliases.json) e desligável com--offline.
2.2 Timeout por scanner¶
Dois orçamentos de tempo distintos protegem o pipeline contra travamentos:
| Parâmetro | Default | Onde | Efeito ao estourar |
|---|---|---|---|
--timeout (PerScannerTime) |
5m | cmd/quorum/scan.go, Options.PerScannerTime |
Scanner marcado timeout; demais continuam |
ProbeTime (probe de versão) |
60s | orchestrator.defaultProbeTime |
Scanner marcado unavailable com diagnóstico |
O probe de versão de 60s é deliberadamente generoso: ferramentas pesadas (ex.: Checkov, um processo Python) demoram a inicializar a frio, especialmente quando todos os scanners sobem ao mesmo tempo num runner com pouca memória. O orquestrador distingue três falhas do probe e emite mensagem acionável:
- timeout do probe → "tool too slow to start or resource-starved (give the
container more memory, or scope
--scanners)"; - killed (OOM) —
signal: killed→ "likely out of memory; raise the container's memory limit"; - não instalado → "not installed/available".
Um timeout de execução nunca derruba o scan inteiro: o status do scanner vira
timeout/error e o relatório registra isso explicitamente — "0 findings is
not proof of safety".
2.3 Grype DB pré-cacheado¶
A imagem :full (Dockerfile.full) congela a base de vulnerabilidades do Grype
em build time:
ENV GRYPE_DB_CACHE_DIR=/opt/grype/db \
GRYPE_DB_AUTO_UPDATE=false
RUN grype db update && grype db status
Benefícios diretos de performance e resiliência:
- O primeiro scan funciona offline e não falha com "failed to load vulnerability db: database does not exist".
- Elimina o download da DB no caminho crítico de cada job de CI.
- Trade-off documentado: a DB é congelada na data do build — rebuild para
atualizar, ou
GRYPE_DB_AUTO_UPDATE=trueem runtime (requer rede).
2.4 Metas de performance (SLO de produto)¶
Metas-alvo; ainda não validadas por benchmark formal (ver Gaps).
| Métrica | Meta | Condição | Prioridade |
|---|---|---|---|
| Overhead do orquestrador (correlação+consenso+report) | ≤ 2s | ≤ 50k findings brutos | P1 |
| Tempo do probe de todos os scanners | ≤ 60s | imagem :full warm |
P0 |
| Latência de alias (cache hit) | ~0 (sem rede) | re-scan idempotente | P1 |
Tempo total de scan SCA (:full, imagem média) |
≤ tempo do scanner mais lento + 2s | runner 2 vCPU / 4 GB | P1 |
| Pico de memória do orquestrador (excluindo scanners) | ≤ 256 MB | ≤ 50k findings | P2 |
Checklist de performance:
- [ ] Rodar com
--offlineem CI quando a rede OSV não for desejada no caminho crítico. - [ ] Restringir
--scannersao necessário em runners pequenos. - [ ] Persistir
~/.cache/quorum/aliases.jsonentre jobs de CI. - [ ] Garantir memória suficiente ao container
:full(Checkov/KICS são pesados).
3. Escalabilidade¶
3.1 CLI stateless¶
Cada execução do Quorum é autocontida e sem estado compartilhado:
- Nenhum estado é persistido entre execuções além de caches opcionais (aliases em disco) que são idempotentes e reconstruíveis.
- Não há servidor, sessão, fila ou coordenação entre processos.
- A saída (SARIF/JSON/XML) é função determinística das entradas (alvo +
scanners + crosswalk + baseline), com os
correlationKey/Fingerprintpuros.
3.2 Escala horizontal nos runners de CI¶
flowchart TB
subgraph CI[Pipeline / CI fleet]
R1[Runner 1\nquorum scan repoA]
R2[Runner 2\nquorum scan repoB]
R3[Runner N\nquorum scan imageX]
end
R1 --> S1[(SARIF/JSON\nartefato)]
R2 --> S2[(SARIF/JSON\nartefato)]
R3 --> S3[(SARIF/JSON\nartefato)]
- A escala é embaraçosamente paralela: N execuções independentes em N runners, sem ponto central de contenção (exceto o registry/Releases na obtenção do artefato).
- O gargalo de escala é o recurso do runner (CPU/memória para os scanners), não o Quorum em si.
- Dependência externa única na execução: OSV.dev para aliases — mitigável com
--offlineou cache compartilhado.
| Vetor de escala | Mecanismo | Limite |
|---|---|---|
| Mais repositórios/imagens | mais jobs/runners paralelos | capacidade da frota de CI |
| Mais scanners por scan | fan-out de goroutines | memória do runner |
| Re-scans frequentes | cache de aliases | tamanho do cache (negligível) |
N/A: escalabilidade vertical de um serviço (auto-scaling de pods, sharding de banco, balanceamento de carga) — não há serviço de longa duração. Ver §4.
4. Disponibilidade¶
N/A como serviço. O Quorum não expõe endpoint, daemon ou processo de longa duração; portanto não há uptime de serviço a medir. O conceito é reinterpretado como disponibilidade da distribuição — a capacidade de obter e executar o artefato.
flowchart LR
Dev[Desenvolvedor / CI] -->|docker pull| GHCR[(GHCR\nghcr.io)]
Dev -->|download| REL[(GitHub Releases\nGoReleaser)]
Dev -->|api.osv.dev| OSV[(OSV.dev\nopcional)]
GHCR --> Run[quorum scan ...]
REL --> Run
OSV -. degradação graciosa .-> Run
| Dependência | Papel | Disponibilidade | Mitigação |
|---|---|---|---|
GHCR (ghcr.io) |
distribuição das imagens :full/:slim |
SLA do GitHub | pin por @sha256, mirror interno, cache de runner |
| GitHub Releases | binários nativos + checksums + assinaturas | SLA do GitHub | mirror interno, cópia versionada |
| OSV.dev | resolução de aliases (apenas VULN) | best-effort | --offline, cache local, degradação graciosa |
| Binários dos scanners | execução real | local (imagem :full) ou PATH (:slim) |
:full já embute tudo |
Metas de disponibilidade de distribuição:
- [ ] Imagens publicadas de forma reprodutível a cada tag semver (
release.yml). - [ ] Possível operar 100% offline com
:full(DB do Grype pré-cacheada + crosswalk embutido +--offline). - [ ] Recomendação enterprise: espelhar as imagens em registry interno e pinar por digest.
Proposta futura (claramente separada): não há plano de transformar o Quorum em serviço hospedado; caso surja, esta seção passaria a definir uptime/SLA de serviço real.
5. Segurança¶
A superfície de segurança do Quorum tem duas frentes: (a) segurança do próprio artefato e da sua cadeia de suprimentos, e (b) higiene de execução (não manusear segredos). O alvo escaneado é dado de entrada — o Quorum só o lê.
5.1 Cadeia de suprimentos (supply chain)¶
flowchart LR
src[Código fonte\nGo 1.26] --> rel[release.yml]
rel --> img[Imagens :full / :slim]
rel --> bin[Binários GoReleaser]
img --> cosign[cosign sign --yes\nkeyless OIDC]
bin --> cblob[cosign verify-blob\nchecksums.txt.sig]
img --> slsa1[attest-build-provenance\nSLSA v1]
bin --> slsa2[attest-build-provenance\nsubject-checksums]
cosign --> ver[Verify no release]
slsa1 --> ver
slsa2 --> ver
| Controle | Implementação | Evidência |
|---|---|---|
| Assinatura keyless de imagem | cosign sign via OIDC do GitHub (sem chaves) |
release.yml, README §Install |
| Atestação SLSA build-provenance | actions/attest-build-provenance@v2 (imagens e binários) |
release.yml |
| Verificação no próprio release | gh attestation verify oci://…@DIGEST falha o build se inválida |
release.yml (step "Verify provenance") |
| Assinatura de binários | checksums.txt + cosign verify-blob (.sig/.pem) |
README §Native binary |
| Pin de scanners por digest | FROM …@sha256: para Trivy/KICS; instaladores com checksum |
Dockerfile.full |
| GitHub Action verifica antes de rodar | action.yml faz cosign-verify da :full por padrão |
action.yml |
| Trigger de release restrito | tags semver v[0-9]+.[0-9]+.[0-9]+ apenas |
release.yml |
Tag móvel v0 para pin do action |
não dispara release; permite pin reprodutível | release.yml, README §CI/CD |
Verificação esperada do consumidor (recomendado em produção):
cosign verify ghcr.io/martinez1991/quorum-sec-scan:full \
--certificate-identity-regexp \
"https://github.com/Martinez1991/quorum-sec-scan/.github/workflows/release.yml@.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/martinez1991/quorum-sec-scan:full \
--repo Martinez1991/quorum-sec-scan
Nota de risco honesta: no
Dockerfile.full, Trivy e KICS são pinados por@sha256, mas alguns scanners (Grype/Syft/Dockle/Kubescape/Checkov) usam instaladores oficiais por versão com checksum, não por digest imutável de imagem. Endurecer todos para digest é uma melhoria recomendada (DESIGN §12, README §"Security of the chain itself"). Ver Gaps.
5.2 Ausência de segredos¶
| Aspecto | Estado | Justificativa |
|---|---|---|
| Credenciais de usuário | inexistentes | sem contas/autenticação |
| Tokens de API próprios | inexistentes | OSV.dev é endpoint público sem chave |
| Segredos em build/release | apenas GITHUB_TOKEN efêmero do runner |
escopo mínimo (contents, packages, id-token, attestations) |
| Persistência de segredos | nenhuma | nada é gravado além de cache de aliases (públicos) |
| Detecção de segredos no alvo | via adapter trivy (TypeSecret) |
findings reportados, nunca persistidos fora do relatório |
Princípios de execução segura:
- [ ] O Quorum não solicita nem armazena credenciais.
- [ ] Logs vão para stderr e não devem conter segredos (o conteúdo de segredos detectados pertence ao relatório controlado pelo usuário).
- [ ] Permissões do workflow de release seguem least privilege.
- [ ] Imagens devem ser verificadas antes do uso (cosign + provenance).
5.3 Modelo de ameaças resumido¶
| Ameaça | Vetor | Mitigação |
|---|---|---|
| Imagem adulterada | registry comprometido / tag mutável | assinatura cosign + SLSA + pin por digest |
| Binário de scanner trojanizado | upstream comprometido | pin por digest/checksum no build |
| Falso negativo silencioso | scanner não roda mas reporta 0 | status por scanner explícito (§6) |
| Bind mount malformado | -v errado escaneia /work vazio |
aviso na doc; resultado 0 ≠ seguro |
| Exfiltração de dados do alvo | rede em runtime | --offline; única chamada externa é OSV (somente IDs de vuln) |
6. Observabilidade¶
Sendo um CLI efêmero, a observabilidade é local ao processo: logs estruturados para humanos em stderr e status de máquina no próprio relatório.
6.1 Logs (stderr)¶
- Toda a telemetria de progresso vai para stderr com prefixo
[quorum](scan.go,logf), deixando stdout limpo para o relatório quando não há--output. --quiet/-qsuprime os logs de progresso e o sumário.- Eventos logados: alvo/tipo/contagem de regras do crosswalk, início/fim por scanner com duração, supressões de baseline/min-severity, e o disparo do gate.
[quorum] target=. type=repo crosswalk=42 rules (./crosswalk) offline=false
[quorum] run trivy (0.71.2) ...
[quorum] done trivy: 17 findings in 4.2s
[quorum] skip grype: does not support target repo
[quorum] filtered: 3 suppressed by baseline (5 entries), 2 below min-severity medium
[quorum] gate: found HIGH finding >= --fail-on high → exit 1
6.2 Status por scanner¶
Cada execução produz um ScannerRun (orchestrator.go) com status de máquina,
exposto no sumário (stderr) e no relatório:
| Status | Significado |
|---|---|
ran |
rodou e produziu resultados (mesmo que 0) |
skipped |
scanner não suporta o tipo de alvo |
unavailable |
binário ausente / probe falhou (timeout/OOM/não instalado) |
error |
erro de execução do scanner |
timeout |
execução excedeu --timeout |
O sumário ao final imprime status, contagem por severidade, findings multi-detectados e a frase âncora "0 findings is not proof of safety — see scanner statuses above." Isso transforma o status em sinal observável, não em ruído.
6.3 Lacunas e propostas¶
| Capacidade | Estado | Observação |
|---|---|---|
| Logs em stderr | ✅ Implementado | prefixados, com --quiet |
| Status por scanner | ✅ Implementado | no sumário e no relatório |
| Duração por scanner | ✅ Implementado | ScannerRun.Duration |
| Métricas estruturadas (Prometheus/OTel) | ❌ N/A | sem processo de longa duração para expor |
| Log estruturado JSON em stderr | ⚠️ Proposta futura | hoje é texto humano |
7. Auditoria¶
O relatório é a evidência de auditoria. Ele é reproduzível, carimba quem detectou o quê e fornece identidade estável por finding.
| Artefato de auditoria | Conteúdo | Onde |
|---|---|---|
| Status por scanner | ran/skipped/unavailable/error/timeout + versão + duração |
Result.Runs, relatório |
| Procedência da detecção | detectedBy[], detectionCount, confidence |
MergedFinding, SARIF properties |
| Identidade estável | Fingerprint = sha256(correlationKey) |
SARIF partialFingerprints["quorum/v1"], JSON fingerprint |
| Supressões | sempre logadas e contabilizadas, nunca descartadas em silêncio | baseline .quorumignore, filter.Apply |
| Versão dos scanners | ScannerVersion por finding / ScannerRun.Version |
relatório |
Propriedades de auditoria:
- Reprodutibilidade: mesma entrada → mesmo
correlationKey/Fingerprint(função pura). Permite diff temporal de relatórios. - Rastreabilidade de supressão: um finding suprimido pelo baseline é reportado como suprimido (com a entrada que o suprimiu), não some.
- Cadeia de custódia do artefato: SARIF/JSON pode ser arquivado como evidência de gate de CI; assinaturas/provenance (§5) atestam a origem do binário que o gerou.
Checklist de auditoria em CI:
- [ ] Arquivar o relatório (SARIF/JSON) como artefato do job.
- [ ] Versionar o
.quorumignore(cada supressão revisada e datada). - [ ] Reter a saída do sumário (status por scanner) junto ao artefato.
- [ ] Registrar a versão/digest da imagem Quorum usada.
8. LGPD (Lei Geral de Proteção de Dados)¶
Aplicável por exclusão — o Quorum não trata dados pessoais. A justificativa é técnica: os dados processados são metadados de software e infraestrutura, não dados de pessoas naturais.
| Categoria de dado | Processado? | Natureza |
|---|---|---|
| Identificadores de vulnerabilidade (CVE/GHSA) | Sim | dado técnico público |
| PURLs / versões de pacote | Sim | dado técnico |
| Caminhos de arquivo, recursos IaC/K8s | Sim | dado técnico do alvo |
| Conteúdo de segredos detectados (Trivy) | Possível | não é PII por definição; fica só no relatório do usuário |
| Dados pessoais (nome, CPF, e-mail, etc.) | Não | fora do escopo funcional |
Consequências:
- Sem PII ⇒ sem necessidade de base legal, consentimento, DPO ou DPIA atribuíveis ao Quorum como controlador/operador.
- A única chamada externa (OSV.dev) envia somente IDs de vulnerabilidade
(ex.:
CVE-2021-…) — não há dado pessoal no tráfego. Desligável com--offline. - Responsabilidade do usuário: se o alvo escaneado contiver PII (ex.: um segredo que seja um e-mail), o relatório gerado pode contê-la. O tratamento e a retenção desse relatório são responsabilidade de quem opera o Quorum, não do produto.
N/A: direitos do titular, portabilidade, anonimização interna — não há base de dados pessoais sob controle do Quorum.
9. PCI DSS¶
N/A como produto. O Quorum não armazena, processa ou transmite dados de cartão (CHD/SAD) e não faz parte de um Cardholder Data Environment (CDE) por construção. Logo, não está no escopo do PCI DSS como sistema.
Entretanto, o Quorum pode auxiliar a conformidade de quem opera um CDE, como ferramenta de apoio aos requisitos abaixo:
| Requisito PCI DSS v4.0 | Como o Quorum auxilia |
|---|---|
| 6.2 / 6.3 — desenvolver software seguro e gerir vulnerabilidades | consenso de SCA (Trivy+Grype) com confidence para priorização |
| 6.3.1 — identificar vulnerabilidades por fontes reconhecidas | IDs CVE via OSV; confirmação autoritativa pesa no score |
| 6.3.2 — inventário de componentes (bespoke/3rd-party) | PURLs por finding; SBOM via Syft na imagem :full |
| 6.4 / 6.5 — proteger aplicações e gerir mudanças | gate em CI por --fail-on; baseline auditável |
| 11.3 — varreduras de vulnerabilidade | varredura automatizável em pipeline, evidência em SARIF |
O Quorum não substitui um ASV scan externo nem um pentest. É um controle compensatório/preventivo no SDLC, não uma atestação de conformidade.
10. ISO/IEC 27001 (Anexo A)¶
Mapeamento dos controles aplicáveis ao Quorum (como ferramenta e como cadeia de build). Controles organizacionais amplos ficam a cargo de quem adota.
| Controle (ISO 27001:2022) | Aplicabilidade | Como o Quorum endereça |
|---|---|---|
| A.8.8 — Gestão de vulnerabilidades técnicas | ✅ Direta | núcleo do produto: detecção + consenso + gate |
| A.8.25 — Ciclo de vida de desenvolvimento seguro | ✅ Apoia | integra-se ao SDLC via CI |
| A.8.28 — Codificação segura | ✅ Apoia | findings IaC/MISCONFIG/SECRET acionáveis |
| A.8.29 — Testes de segurança em dev/aceite | ✅ Apoia | gate por exit code |
| A.8.30 — Desenvolvimento terceirizado | ⚙️ Parcial | scan de componentes 3rd-party (SCA) |
| A.8.31 — Separação de ambientes | ➖ Do adotante | execução isolada por job efêmero |
| A.8.15 — Logging | ⚙️ Parcial | logs em stderr + status por scanner |
| A.5.23 — Segurança em serviços cloud | ➖ Do adotante | N/A (sem serviço cloud próprio) |
| A.5.7 — Threat intelligence | ⚙️ Parcial | OSV/CVE como fonte de vulnerabilidade |
| Cadeia de suprimentos (A.5.19–A.5.23) | ✅ Própria | assinatura cosign + SLSA provenance (§5) |
Legenda: ✅ atende/apoia diretamente · ⚙️ parcial · ➖ responsabilidade do adotante.
11. OWASP ASVS (controles relevantes a um CLI)¶
A maioria dos capítulos do ASVS pressupõe uma aplicação web com sessão e autenticação — N/A aqui. Restam os controles aplicáveis a um binário/CLI:
| Domínio ASVS | Aplicabilidade | Estado no Quorum |
|---|---|---|
| V1 Arquitetura & threat modeling | ✅ | DESIGN.md + §5.3 deste doc |
| V5 Validação de entrada | ✅ | parsing de flags (cobra), parsers de adapter com contract tests |
| V7 Tratamento de erros & logging | ✅ | erros acionáveis, logs em stderr, sem vazar segredos |
| V10 Código malicioso / integridade | ✅ | assinatura, provenance, pin de dependências |
| V12 Arquivos & recursos | ⚙️ | lê alvo/crosswalk/baseline; escreve relatório com perms 0644/0755 |
| V14 Configuração | ✅ | defaults seguros (--offline opcional, crosswalk com fallback) |
| V2 Autenticação | ➖ N/A | sem autenticação |
| V3 Sessão | ➖ N/A | sem sessão |
| V4 Controle de acesso | ➖ N/A | sem multiusuário |
| V6 Criptografia armazenada | ➖ N/A | não armazena dado sensível |
| V8/V9 Dados/Comunicação | ⚙️ | OSV via HTTPS; sem dado sensível em trânsito |
| V13 APIs | ➖ N/A | não expõe API |
Checklist ASVS prática:
- [ ] Validar formato/severidade das flags e falhar com exit code
2em uso inválido. - [ ] Garantir que parsers de adapter tenham fixture/contract test versionado.
- [ ] Não emitir conteúdo de segredo em logs de progresso.
- [ ] Verificar integridade do binário/imagem antes de executar.
12. OWASP Top 10 (do próprio binário/imagem)¶
Escopo: riscos do artefato Quorum em si, não do alvo que ele escaneia (esse é o trabalho dos scanners). Mapeamento ao OWASP Top 10:2021.
| Risco | Relevância p/ o Quorum | Controle |
|---|---|---|
| A01 Broken Access Control | Baixa | sem controle de acesso (CLI local) |
| A02 Cryptographic Failures | Baixa | não guarda segredos; assinaturas via Sigstore |
| A03 Injection | Média | invoca scanners via exec; argumentos controlados pelo orquestrador, não shell-interpolados |
| A04 Insecure Design | Média | princípio "false split > false merge"; threat model em DESIGN |
| A05 Security Misconfiguration | Média | defaults seguros; aviso de bind mount; crosswalk com fallback |
| A06 Vulnerable & Outdated Components | Alta | deps Go + binários de scanner pinados; SBOM; o próprio Quorum deve ser escaneado |
| A07 Identification & Auth Failures | N/A | sem autenticação |
| A08 Software & Data Integrity Failures | Alta | cosign + SLSA provenance + pin por digest/checksum |
| A09 Logging & Monitoring Failures | Média | status por scanner evita falso negativo silencioso |
| A10 SSRF | Baixa | única saída de rede é OSV.dev (host fixo); --offline desliga |
Ações priorizadas:
- [ ] A06/A08: rebuild periódico para refrescar DB do Grype e bumps de versão de scanner.
- [ ] A08: converter tags mutáveis restantes para
@sha256noDockerfile.full. - [ ] A03: manter invocação de scanners por args (sem shell), revisada em code review.
13. Resiliência (degradação graciosa)¶
A resiliência é um princípio de design central: uma falha parcial degrada, não derruba, e a degradação é sempre visível.
flowchart TD
A[Scanner ausente] --> A1[status unavailable\nscan continua]
B[Probe lento / OOM] --> B1[status unavailable\nmensagem acionável]
C[Scanner estoura --timeout] --> C1[status timeout\ndemais continuam]
D[OSV.dev indisponível] --> D1[usa id original\ncache local; sem falhar]
E[Crosswalk ausente] --> E1[fallback /opt/quorum/crosswalk\nou finding unmapped]
F[Controle não mapeado] --> F1[finding isolado\nflag unmapped]
| Falha | Comportamento | Fonte |
|---|---|---|
| Scanner não instalado | unavailable, scan prossegue |
orchestrator.runOne |
| Probe lento / OOM | unavailable com diagnóstico (memória/scope) |
orchestrator.runOne |
| Timeout de execução | timeout, outros scanners continuam |
orchestrator + --timeout |
| Rede OSV indisponível | aliases degradam para id original; nunca falha o scan | alias/DESIGN §7 |
:full sem rede |
DB do Grype pré-cacheada + crosswalk embutido | Dockerfile.full |
| Crosswalk default ausente | fallback automático para /opt/quorum/crosswalk |
resolveCrosswalkDir |
| Controle não mapeável | finding fica isolado, flag unmapped (não chuta merge) |
DESIGN §6 |
Invariante de resiliência: "0 findings is not proof of safety" — toda degradação aparece como status, evitando que uma falha vire um falso "tudo certo".
14. Backup, DR, RTO e RPO¶
N/A — o Quorum é stateless. Não há dado de produção sob sua custódia que possa ser perdido. A continuidade depende de artefatos reproduzíveis, não de backup/restore.
| Conceito | Aplicabilidade | Justificativa |
|---|---|---|
| Backup de dados | N/A | sem armazenamento persistente de estado de negócio |
| Disaster Recovery (DR) | N/A (serviço) | não há serviço para recuperar |
| RTO | ~minutos, reinterpretado | "recuperar" = re-executar o scan em outro runner |
| RPO | 0, reinterpretado | nada a perder; cada scan é recomputável da fonte |
O que substitui backup/DR:
- Reprodutibilidade: imagens pinadas por digest + binários assinados + provenance permitem reconstruir/obter exatamente o mesmo artefato.
- Mirror de distribuição: espelhar imagens/binários em registry interno protege contra indisponibilidade do GHCR/Releases.
- Cache de aliases: descartável; reconstruído a partir do OSV/scanner.
Único item recuperável de fato: o relatório arquivado como evidência (§7) — sua retenção/backup é responsabilidade do pipeline que o gera, não do Quorum.
Proposta futura (separada): se um modo com cache persistente compartilhado for adotado em larga escala, definir política de backup/retenção desse cache.
15. SLA / SLO / SLI¶
Não há SLA contratual de serviço (não é serviço). Definimos SLO/SLI para dois contextos operacionais reais: uso em CI e pipeline de release.
15.1 Uso em CI (o binário/imagem como dependência do pipeline)¶
| SLI | Definição | SLO alvo | Como medir |
|---|---|---|---|
| Confiabilidade do scan | % de jobs que terminam com exit 0/1 (sem 2) |
≥ 99% | exit codes do job |
| Determinismo | % de re-scans da mesma entrada com mesmo fingerprint set | 100% | diff de relatórios |
| Latência de overhead | overhead do orquestrador (sem scanners) | ≤ 2s p95 | sumário/Duration |
| Resiliência a falha de rede | scans concluídos com OSV indisponível | 100% (degrada) | execução --offline |
| Cobertura de execução | % de scanners suportados com status ran |
≥ 95% em :full |
status por scanner |
15.2 Pipeline de release (publicação do artefato)¶
| SLI | Definição | SLO alvo | Como medir |
|---|---|---|---|
| Sucesso de publicação | % de tags semver que publicam imagens+binários | 100% | release.yml |
| Integridade verificada | % de releases com cosign+provenance verificados no próprio build | 100% | step "Verify provenance" |
| Reprodutibilidade do build | build determinístico (-trimpath, deps pinadas) |
100% | Dockerfile.full/GoReleaser |
| Tempo de release | tag → imagens+binários publicados | ≤ 30 min | duração do workflow |
Distinção importante de SLA do produto vs. integridade: a disponibilidade de publicação depende do GitHub/GHCR (não controlado por nós), mas a integridade (assinatura + provenance verificadas) é bloqueante no próprio release — um artefato com atestação quebrada falha o build.
Premissas¶
- Os números/metas em §2.4 e §15 são alvos de engenharia, ainda não validados por benchmark formal neste repositório.
- Assume-se que o consumidor em produção verifica imagem/binário (cosign +
gh attestation verify) e, idealmente, pina por digest — o produto fornece os meios, a aplicação é do adotante. - O
--offlineé o modo recomendado quando a política de CI proíbe egressos de rede; com isso a única dependência externa em runtime (OSV.dev) é eliminada. - "Sem PII" pressupõe que o produto não é configurado para tratar dados pessoais; PII eventualmente presente no alvo é responsabilidade do operador do relatório.
- Mapeamentos de PCI DSS, ISO 27001, ASVS e OWASP Top 10 são interpretativos, baseados no comportamento as-is do código (v0.2.3), e não constituem atestação de conformidade.
- A disponibilidade da distribuição depende de serviços de terceiros (GitHub GHCR/Releases, OSV.dev), cujos SLAs não são controlados por este projeto.
- A imagem
:fullélinux/amd64(scanners amd64); cenários arm64 usam:slimcom scanners no PATH, o que altera o perfil de performance/disponibilidade local.
Lacunas conhecidas (gaps)¶
- Não há benchmark de performance versionado para sustentar os SLOs alvo.
- Nem todos os scanners no
Dockerfile.fullestão pinados por digest imutável (alguns por versão+checksum); endurecer para@sha256é recomendado. - Não há logging estruturado (JSON) nem métricas/telemetria exportáveis — observabilidade é texto em stderr por design.
- Não há mecanismo nativo de mirror/retenção de artefatos; é responsabilidade do adotante.