Checklists¶
This document gathers five actionable checklists for the Quorum
(quorum-sec-scan, v0.8.3) lifecycle: Development, QA, Security,
Deploy/Release and Production/Operation. Every item is specific to the project's
real flow — a CLI/Docker consensus security scanning tool written in
Go 1.26, distributed as signed images on GHCR and native binaries via
GoReleaser. Items are verifiable (with a command or acceptance criterion) and
anchored to the behavior of the code (cmd/quorum, internal/*) and the
workflows (.github/workflows/{ci,e2e,release,tag-major}.yml, action.yml).
Principle that runs through all checklists: "false split > false merge" and "0 findings is not proof of safety". An item is only "done" when you can prove the scanners ran (status
ran) — not when the report came back empty.
Useful cross-links: Overview · Architecture · DevOps · Infrastructure · Observability · Roadmap.
Flow map (where each checklist acts)¶
flowchart LR
DEV["1. Development\n(branch + code + local tests)"]
PR["Pull Request → main"]
CI["CI: ci.yml + e2e.yml\n(vet, test -race, coverage, build, real consensus)"]
QA["2. QA\n(functional verification + contract tests)"]
SEC["3. Security\n(trust boundary, supply chain)"]
MERGE["Merge into main"]
TAG["Semver tag vX.Y.Z"]
REL["4. Deploy/Release\nrelease.yml: images + binaries\ncosign + SLSA + SBOM attested"]
OPS["5. Production/Operation\nmount, socket, fail-on, baseline, verification"]
DEV --> PR --> CI
CI --> QA
CI --> SEC
QA --> MERGE
SEC --> MERGE
MERGE --> TAG --> REL --> OPS
OPS -. feedback / baseline triage .-> DEV
| Real stage | Trigger | Workflow / artifact | Checklist |
|---|---|---|---|
| Code on a branch | local work | make test/vet/build |
1. Development |
PR to main |
pull_request |
ci.yml, e2e.yml |
2. QA |
| Chain review | PR / pre-release | release.yml, action.yml, Dockerfile.full |
3. Security |
Tag vX.Y.Z |
push of a semver tag |
release.yml (images+binaries) |
4. Deploy/Release |
Moving tag v0/v0.8 |
published release |
tag-major.yml (auto-advances) |
4. Deploy/Release |
| Pipeline usage | docker run / action |
:full/:slim image |
5. Production/Operation |
1. Development Checklist¶
Goal: ensure a change is faithful to Quorum's architecture, passes the local
gates before the PR and honors the adapters' contracts. Reproduces locally what
ci.yml requires.
1.1 Setup and branch¶
- [ ] Go 1.26+ installed (
go version) — this is the version pinned inci.yml,e2e.ymlandrelease.yml. - [ ] Work done on a branch off
main(never a direct commit tomain); the flow is always via PR. - [ ] Required OSS scanners on
PATHfor manual end-to-end testing, or use of the:fullimage. There are 12 adapters registered (internal/adapter/*.go, viainit()/Register): - [ ] VULN/SCA:
trivy,grype. - [ ] MISCONFIG/IaC:
trivy,checkov,kics,terrascan,tfsec,regula(+conftestfor policy-as-code). - [ ] K8S_POSTURE:
kubescape,polaris,kube-score. - [ ] IMG_HARDENING:
dockle. - [ ] SECRET:
trivy(with redaction ofMatch). - Missing tools are reported as
unavailable, and do not break the build.
1.2 Architecture adherence (as-is)¶
- [ ] The change respects package boundaries:
cmd/quorum(cobra CLI) vs.internal/{adapter,orchestrator,correlate,consensus,alias,cache,crosswalk,filter,model,purl,report,severity}. - [ ] Nothing introduces a dependency on a web frontend, relational database or REST API — out of the product's scope (CLI/Docker only).
- [ ] The deterministic core stays AI-free: any AI/LLM lives in the opt-in
advisory layer (
internal/{enrich,rag,advisor}), is off by default, and is presentation-only — it never touchescorrelationKey,fingerprint,confidence, aggregated severity or the fail-on gate. - [ ] New output/normalization converges to the canonical model
model.Finding(no raw scanner format leaks out of the adapter). New advisory fields (Remediation,References,Advice) hang offMergedFindingand are populated only under--advice. - [ ] If the change affects correlation, the
correlationKeystays deterministic per type (VULN/MISCONFIG/K8S_POSTURE/etc —DESIGN §6) and the false split > false merge principle holds (when in doubt, isolate and markunmapped). - [ ] The Trivy secret/
Matchis redacted before it leaves the adapter (do not leak a credential into the report).
1.3 Adapters (when applicable)¶
- [ ] The adapter implements the full
Adapterinterface:Name/Version/Supports/Capabilities/Run. - [ ] A contract test exists against a versioned fixture in
internal/adapter/testdata(a format change must break the test before it breaks production). - [ ]
Version(ctx)is light enough for the 60s probe (Options.ProbeTime) and correctly distinguishes absence vs. slowness. - [ ]
Supports(target)reflects the scanner's real targets (e.g.grypedoes not supportk8s;dockle/kube-scoreare single-target;trivysupports all three types). - [ ] Passthrough honored: the adapter appends
extraArgs(<name>)(read fromQUORUM_<NAME>_ARGS) to its arguments, without breaking the output parse. - [ ] stdout buffer capped by
QUORUM_MAX_OUTPUT_BYTES(default 512 MiB) — output above that is aborted with a clear error (anti-OOM).
1.4 Advisory layer (when applicable)¶
- [ ] Phase 0 (deterministic, no model): curated remediation templates + OWASP
references matched by
canonicalControl/ruleId/category/type(packageinternal/enrich; data inknowledge/*.yaml— aws/azure/gcp/k8s/image/categories). New/edited templates keep the output byte-identical when--adviceis off. - [ ] Phase 2 (RAG-as-artifact, deterministic): retrieval from a versioned,
digest-pinned OWASP corpus (
knowledge/owasp/corpus.yaml, packageinternal/rag). Lexical retrieval by default (no model); semantic only when the corpus is embedded viaquorum advise-index, andscanauto-picks semantic when the corpus has vectors — the digest pin is preserved. - [ ] Phase 1 (opt-in local LLM,
internal/advisor): reproducible viatemperature=0+ an on-disk cache keyed byfingerprint+provider+model;--fix=suggestmust pass a verify-the-fix re-scan (apply to a temp copy, re-scan with the same scanner, keep only if the finding is gone and the file parses) and never auto-applies. Graceful degradation: if the model is unreachable the report ships without AI advice and the scan never fails. - [ ] Phase 3 (opt-in remote provider): sends only the normalized finding, never
source code; gated on
--advice-allow-egress, blocked by--offline, and refuses--fix. - [ ] Every AI attachment is labeled "AI-generated, advisory only".
- [ ] Evals updated when advisory behavior changes:
internal/evalsmeasures deterministic remediation coverage, OWASP reference relevance and the verify-the-fix rate (runs in CI, no heavy model).
1.5 Local gates (mirror ci.yml)¶
- [ ]
make vet(orgo vet ./...) with no findings. - [ ]
make test/go test -race ./...green (unit + contract + eval tests); coverage reported in CI. - [ ]
make build/go build -trimpath -o dist/quorum ./cmd/quorumcompiles. - [ ] Smoke:
./dist/quorum list-scannerslists the 12 registered adapters. - [ ] Manual functional test:
./dist/quorum scan <target> --format jsonproduces a report and the stderr summary shows per-scanner status. - [ ] Advisory smoke (optional):
./dist/quorum scan <target> --adviceattaches deterministic remediation/references without altering the fingerprints; the same scan without--adviceproduces byte-identical output.
1.6 PR hygiene¶
- [ ] New/changed crosswalk in
crosswalk/*.yamlfollows the schema and the hub per cloud/platform family: - [ ]
aws.yaml/azure.yaml/gcp.yaml— AVD hub (S3/IAM/EBS/SG/RDS/ KMS/CloudTrail/VPC-flow-logs; Azure Storage/Key Vault; GCP bucket/ firewall/SQL). - [ ]
k8s.yaml— C-#### (kubescape) hub correlatingkubescape×polaris×kube-score(privilege-escalation, privileged, non-root, cpu/mem limits, probes, read-only-fs, linux-hardening, automount-SA, network-policy, host-network, host-PID/IPC, capabilities, secrets). - A rule with no mapping is not "guessed" (it stays
unmapped); the crosswalk is derived from real output (favors false split over false merge). - [ ] A change to
./policy(Rego) forconftestships with a test —conftesthas no rules of its own, it evaluates YOUR Rego (default./policy). - [ ] Documentation updated when behavior changes (
README.md,README.pt-BR.md,DESIGN.md, thisdocs/and the docs published on GitHub Pages via MkDocs Material). - [ ] PR opened against
main; waits forci.ymlande2e.ymlgreen.
2. QA Checklist¶
Goal: validate Quorum's observable behavior — real consensus, exit codes, formats
and status transparency — not just "the unit tests passed". Anchored to e2e.yml,
which runs real scanners (not fixtures).
2.1 Automated suite (PR)¶
- [ ]
ci.ymlgreen: vet +go test -race ./...+ coverage + build + smoke. - [ ]
e2e.ymlgreen on the consensus scenarios: - [ ] IaC/MISCONFIG (Trivy + Checkov/KICS/tfsec/terrascan/regula over
examples/terraform) withsummary.multiDetected >= 1. - [ ] SCA/VULN (Trivy + Grype over
alpine:3.10) withsummary.multiDetected >= 1. - [ ] K8S_POSTURE (kubescape × polaris × kube-score) correlating
via
crosswalk/k8s.yaml. - [ ] Adapter contract tests cover the updated fixture of the tool's real version.
2.2 Execution transparency (per-scanner status)¶
- [ ] The report exposes per-scanner status:
ran | skipped | unavailable | error | timeout. - [ ] The "tool missing" scenario produces
unavailableand does not fail the scan. - [ ] The "per-scanner timeout" scenario (short
--timeout) produces statustimeoutand an associated error message, notran. - [ ]
conftestwith no policies in./policyreportserror(expected — policy-as-code is opt-in), notranwith 0 findings. - [ ] Manually validate that "0 findings" comes with the statuses — a 0 with
everything
ranis different from a 0 with everythingunavailable.
2.3 Exit codes (gate)¶
| Test scenario | Command | Expected exit |
|---|---|---|
No --fail-on, or nothing hits the threshold |
scan … |
0 |
Finding ≥ --fail-on |
scan … --fail-on high |
1 |
| Usage / runtime error | scan with no target, invalid --type, invalid --log-format |
2 |
- [ ]
0when no finding hits--fail-on(or the flag is absent). - [ ]
1when there is a finding with severity ≥--fail-on(gate fires, loggate: found … >= --fail-on … → exit 1). - [ ]
2on a usage/runtime error (e.g. invalid--fail-on, invalid--format,--log-formatother thantext|json, a non-existent baseline passed explicitly via--baseline, a target starting with-refused, a target aboveQUORUM_MAX_TARGET_BYTES, an invalid--advice-provider, or--advice-provider=remotewithout--advice-allow-egress).
2.4 Output formats and telemetry¶
- [ ] SARIF (default): contains
partialFingerprints["quorum/v1"]=sha256(correlationKey)andproperties.detectedBy/detectionCount/confidence. - [ ] JSON: field
fingerprint,summary.multiDetected,scanners[]with status and count, severity rollup. - [ ] XML: the same structure serialized (legacy/JUnit-like pipelines).
- [ ]
--output/-owrites to a file: the path goes throughfilepath.Clean, creates the parent directory if needed and writes with perm0600(the report may contain sensitive detail); without-oit writes to stdout. - [ ]
--metrics <file>writes metrics in Prometheus text format (textfile collector), perm0644(non-sensitive counts). - [ ]
--log-format text|jsoncontrols the progress log on stderr (jsonemits{ts,level,msg}).
2.5 Severity, baseline and min-severity¶
- [ ]
--min-severityremoves findings below the threshold from the report and from gating; suppressions are logged (filtered: … below min-severity <sev>). - [ ]
--baseline/.quorumignoresuppresses byfingerprintorcorrelationKey; suppressions are always logged (never silently dropped; the log carries the count of entries and of suppressed items). - [ ] A comment line (
#) and blank lines in.quorumignoreare ignored correctly.
2.6 Alias resolution¶
- [ ] With network:
CVE-…(Trivy) andGHSA-…(Grype) for the same bug correlate (local alias → cache~/.cache/quorum/aliases.json→ OSV.dev, CVE preferred). The OSV id is validated and passes throughurl.PathEscape. - [ ]
--offline: no call to OSV; graceful degradation (uses local aliases + cache). - [ ] A simulated network failure does not bring down the scan (graceful degradation).
- [ ] The alias cache is written with perm
0600and loads a compatibleschemaVersion(a corrupted/old-version file is ignored, does not break).
2.7 Advisory layer (only under --advice)¶
- [ ] Byte-identical without
--advice: the same scan with and without the flag produces identical output (advisory is presentation-only; it never touchescorrelationKey/fingerprint/confidence/severity/the gate). - [ ] Phase 0 attaches deterministic
Remediation/Referencesmatched by control/rule/category/type; no network needed. - [ ] Phase 2: lexical retrieval works with the digest-pinned corpus offline;
after
quorum advise-index,scanauto-picks semantic retrieval. - [ ]
--advice-provider=localdegrades gracefully when the endpoint is unreachable (report ships without AI advice, scan does not fail); reproducible viatemperature=0+ fingerprint cache. - [ ]
--fix=suggestonly keeps a patch that passes the verify-the-fix re-scan (finding gone + file still parses) and never auto-applies. - [ ]
--advice-provider=remotesends only the normalized finding (titles, paths, controls — never source), requires--advice-allow-egress, is blocked by--offline, and refuses--fix. - [ ] Every AI attachment is labeled "AI-generated, advisory only".
- [ ] Metrics under
--advicepresent when--metricsis used:quorum_advice_enriched{kind=remediation|references|recommendation},quorum_advice_provider{provider},quorum_advice_fix{stage=proposed|verified}(verified/proposed = the verify-the-fix rate).
3. Security Checklist¶
Goal: treat Quorum's own chain as a trust boundary and validate the supply-chain
guarantees (DESIGN §12). Covers both what Quorum produces and what it consumes
(packaged scanner binaries).
3.1 Release supply chain¶
- [ ] Images are keyless-signed with cosign (OIDC), over the manifest digest, with retry — verify before use:
- [ ] SLSA build-provenance attestation present and verifiable (image):
- [ ] Attested SPDX SBOM (
actions/attest-sbom, via syft) verifiable — in addition to thesbom: trueattestation from BuildKit: - [ ] Native binaries:
checksums.txt+ cosign signature (cosign verify-blob) + SLSA attestation bysubject-checksums(gh attestation verify quorum_<ver>_<os>_<arch>.tar.gz --repo …) + per-binary SPDX SBOM (GoReleaser/syft). - [ ] Knowledge pack attested: the advisory knowledge pack + crosswalk get a
SLSA build-provenance attestation each release (
release.ymlknowledgejob) — verify the corpus before trusting the advisory layer offline: - [ ]
release.ymlitself re-verifies the attestation (image and binary) as a release step, with retry — a release with a broken attestation must fail.
3.2 CI permissions and identity¶
- [ ]
release.ymlkeeps minimalpermissions:contents: read(jobimages),packages: write,id-token: write(cosign keyless),attestations: write(SLSA + SBOM + knowledge pack). - [ ] Job
binariesusescontents: writeonly to create the release (plusid-token/attestations: write). - [ ] The release trigger is restricted to semver tags
v[0-9]+.[0-9]+.[0-9]+— moving tags (v0,v0.8, used to pin the action) do not trigger a build; they are advanced bytag-major.ymlon thereleaseevent.
3.3 Composite GitHub Action (action.yml)¶
- [ ] By default
verify: "true"→ cosign-verifies the:fullimage before running it (installs cosign if absent). - [ ] In production,
imageis pinned by@sha256:<digest>(not a moving tag) and the action is pinned by@<sha>. - [ ]
docker-socketreviewed: fortype: imagethe socket/var/run/docker.sockis auto-mounted (avoids a false-zero when scanning a freshly-built local image);offdisables even for image,trueforces it for other types. Without the socket, a local-image scan emits a warning. - [ ] Passthrough inputs (
trivy-args,grype-args,checkov-args,kics-args,dockle-args,kubescape-args) reviewed — they can carry secrets (e.g.checkov --bc-api-keyfor Prisma/Bridgecrew) and so are not echoed in the log. - [ ] Advisory inputs reviewed:
advice,advice-provider,advice-endpoint,advice-model,advice-embed-model,advice-max,advice-cache,advice-allow-egress,advice-api-key,fix. Forlocalthe action auto-addshost-gateway; forremotetheadvice-api-keyis forwarded via env (never on the command line) and egress needs explicit consent. - [ ] Sensitive inputs (
baseline,crosswalk,offline) reviewed for security impact (e.g. a baseline is not suppressing a real risk).
3.4 Packaged scanner binaries (:full image)¶
- [ ] Acknowledged that the packaged OSS binaries are part of the consumer's
trust boundary (
THIRD_PARTY_NOTICES.mdlists the licenses). - [ ] Image bases pinned by
@sha256; scanner downloads (kubescape,tfsec,terrascan,regula,conftest) verified by checksum inDockerfile.full. - [ ] Grype DB pre-cached in
:full, from a trusted source (Anchore), built withGRYPE_DB_VALIDATE_AGE=false(does not expire on runners without egress) — the version matches the supported schema.
3.5 Secure by default (hardening)¶
- [ ]
--offlineavailable for egress-less environments (turns off OSV and blocks--advice-provider=remote). - [ ] AI egress is off by default and opt-in:
--advice-provider=remoterequires explicit--advice-allow-egress, sends only the normalized finding (never source), and refuses--fix.--advice-provider=localand the deterministic phases never leave the host. - [ ] Argument injection blocked: a target starting with
-is refused (use./-name). - [ ] DoS caps active:
QUORUM_MAX_OUTPUT_BYTES(512 MiB) andQUORUM_MAX_TARGET_BYTES(20 GiB) — override/disable by env. - [ ]
--outputnormalized (filepath.Clean) and written with perm0600; metrics with0644. - [ ] Suppressions (
--baseline,--min-severity) are auditable: always logged; review ensures no entry is masking an active finding. - [ ] Alias cache (
~/.cache/quorum/aliases.json, perm0600, withschemaVersion) treated as untrusted/derived data (can be deleted without loss of correctness); the advisory cache (--advice-cache) is likewise derived and safe to delete. - [ ] The Trivy secret (
Match) is redacted — the report does not leak a credential. - [ ] False negatives from a malformed mount are prevented (see
checklist 5.1) — an empty
/workreports 0 findings.
4. Deploy/Release Checklist¶
Goal: run a reproducible, signed release. The release is triggered by a push of a
semver tag vX.Y.Z; release.yml builds/publishes images (:full, :slim) and
binaries (GoReleaser), signs and attests everything (cosign + SLSA + SBOM SPDX +
knowledge pack).
4.1 Pre-tag¶
- [ ]
mainis green (ci.yml+e2e.yml) on the commit to be tagged. - [ ] The chosen version follows strict semver
vX.Y.Z(e.g.v0.8.3) — therelease.ymlonly fires forv[0-9]+.[0-9]+.[0-9]+. - [ ] CHANGELOG/notes checked; GoReleaser has full history
(
fetch-depth: 0) to generate the changelog. - [ ] The packaged crosswalk reviewed (
crosswalk/{aws,azure,gcp,k8s}.yaml) — it is bundled into/opt/quorum/crosswalkin the images and binaries. - [ ] Rego policies in
./policy(if any) reviewed — they ship along forconftestuse. - [ ] The advisory knowledge pack reviewed (
knowledge/*.yaml,knowledge/owasp/corpus.yaml) — the corpus digest pin is intact and the pack ships bundled for offline Phase 0/2.
4.2 Triggering the release¶
- [ ] Tag created and pushed:
- [ ] The
release.ymlworkflow started for the tag (not for a moving tag).
4.3 Images (job images)¶
- [ ]
:fullpublished onlinux/amd64with tags:full,:<version>,:<version>-full,:latest(all 12 scanners packaged; Grype DB pre-cached). - [ ]
:slimpublished onlinux/amd64,linux/arm64with tags:slim,:<version>-slim(orchestrator only). - [ ]
provenance: trueandsbom: trueon the build-push (BuildKit). - [ ]
cosign sign(with retry) applied to the manifest digest (covers all the tags that point to it). - [ ]
actions/attest-build-provenancegenerated and pushed the SLSA attestation to GHCR. - [ ]
actions/attest-sbomgenerated and pushed the attested SPDX SBOM (syft →sbom.spdx.json). - [ ] The "Verify provenance attestation" step passed (end-to-end re-check, with retry).
4.4 Binaries (job binaries, tag-only)¶
- [ ] GoReleaser published archives per OS/arch +
checksums.txt+ cosign signature, with per-binary SPDX SBOMs (syft). - [ ] SLSA attestation by
subject-checksums: dist/checksums.txtgenerated. - [ ] The verification step ("spot-check" of one artifact) passed (with retry).
4.5 Knowledge pack (job knowledge)¶
- [ ] The advisory knowledge pack + crosswalk got a SLSA build-provenance attestation this release — verify before trusting the advisory layer:
4.6 GitHub Action / moving tag¶
- [ ] Moving tag
v0(andv0.8) auto-advanced bytag-major.ymlon thereleaseevent — action pinuses: Martinez1991/quorum-sec-scan@v0. - [ ] Moving
v0/v0.8does not trigger a new release build (the trigger is semver-restricted).
4.7 Post-publication validation (consumer side)¶
- [ ]
cosign verifyof the freshly-published image OK (see 3.1). - [ ]
gh attestation verifyof the image (provenance and SBOM), of a binary, and of the knowledge corpus OK. - [ ]
docker run --rm … :full list-scannerslists the 12 packaged scanners. - [ ] Real smoke: a scan of a known target produces consensus (
detectionCount > 1on at least one finding).
sequenceDiagram
participant Dev
participant GH as GitHub (tag vX.Y.Z)
participant REL as release.yml
participant GHCR
participant Sigstore as Sigstore/OIDC
Dev->>GH: git push origin vX.Y.Z
GH->>REL: trigger (semver only)
REL->>GHCR: build & push :full / :slim (+SBOM/provenance BuildKit)
REL->>Sigstore: cosign sign (digest, keyless, retry)
REL->>GHCR: attest SLSA build-provenance
REL->>GHCR: attest SBOM SPDX (syft)
REL->>GHCR: attest knowledge pack (SLSA)
REL->>GHCR: gh attestation verify (re-check, retry) ✓
REL->>GH: GoReleaser release (binaries + checksums + sig + SBOM)
GH->>GH: tag-major.yml advances v0 / v0.8
5. Production/Operation Checklist¶
Goal: run Quorum correctly in pipelines, avoid the classic false negative (wrong
mount / missing socket) and operate the gate with confidence. Applies to a direct
docker run, to container:/CI, and to the composite action.
5.1 Correct mount and Docker socket (the #1 mistake)¶
- [ ] Source mounted at
/workwith the correct colon of thehost:containerseparator: - [ ] Linux/macOS:
-v "$PWD:/work" - [ ] PowerShell:
-v "${PWD}:/work" - [ ] cmd.exe:
-v "%cd%:/work" - [ ] Do not use a malformed mount like
-v "%cd%/work"(no:), which mounts an empty/work→ reports 0 findings for everything (false negative). - [ ] Container workdir coherent (
-w /work) when the target is.. - [ ] Local image scan (
--type imageof a freshly-built image): mount the host daemon socket, otherwise the image is invisible from inside the container → false-zero: - [ ]
docker run:-v /var/run/docker.sock:/var/run/docker.sock. - [ ] Action: auto-mounted for
type: image(opt-outdocker-socket: "off", force with"true"). - [ ] Anti-false-negative validation: confirm in the summary that scanners are
ran(notunavailable) and that the number of analyzed files makes sense.
5.2 Verify before running¶
- [ ] Image cosign-verified before use (or
verify: truein the action) — see 3.1. - [ ] SLSA + SBOM verified when policy requires it (
gh attestation verifyfor provenance and for the SPDX SBOM); verify the knowledge corpus attestation when relying on the offline advisory layer. - [ ] In production, the image is pinned by
@sha256:<digest>and the action by@<sha>.
5.3 Scan configuration¶
- [ ] Correct
--type(image|repo|k8s) or confirmed that inference (existing path →repo, otherwiseimage) hits the right target. - [ ]
--scannerssets the desired pool (or is omitted for all that support the target) — remember thatgrypedoes not dok8sanddockle/kube-scoreare single-target. - [ ]
--crosswalk: using the bundled/opt/quorum/crosswalk(auto-detected in the image when./crosswalkis absent) or pointing at your own mappings; the initial log showscrosswalk=N rules (<dir>). - [ ]
conftest: Rego policies in./policy(orQUORUM_CONFTEST_ARGS="--policy <dir>") — without them the scanner iserror, which is expected. - [ ] Per-scanner passthrough via
QUORUM_<SCANNER>_ARGSwhen you need to broaden coverage or unlock policies (e.g.QUORUM_CHECKOV_ARGS="--bc-api-key <key> …"). Treat as a secret (do not echo). - [ ]
--timeoutper scanner suited to the runner (default5m); if there isunavailablefrom a slow/OOM probe (60s), increase the container memory or reduce--scanners. - [ ] DoS caps adjusted if needed:
QUORUM_MAX_OUTPUT_BYTES(512 MiB),QUORUM_MAX_TARGET_BYTES(20 GiB).
5.4 Build gate¶
- [ ]
--fail-on <sev>set per policy (the gate fires exit1). - [ ] The pipeline handles the exit codes correctly:
0ok ·1gate ·2error (do not confuse1with2). - [ ]
--min-severityused to reduce noise without masking the gate (review that the threshold does not hide the--fail-onseverity).
5.5 Baseline and continuous triage¶
- [ ]
.quorumignoreversioned, with one fingerprint/correlationKey per line + a justification comment + a revision date. - [ ] Fingerprints copied from the report itself
(
partialFingerprints["quorum/v1"]in SARIF /fingerprintin JSON). - [ ] Suppressions reviewed periodically (every suppression is logged — audit the CI log).
5.6 Integration, artifacts and telemetry¶
- [ ] SARIF published to GitHub code scanning / DefectDojo (free dedupe via
partialFingerprints). - [ ] The report (
-o quorum.sarif/.json/.xml, perm0600) saved as a pipeline artifact (always, including on a gate failure). - [ ]
--metrics <file>exported to the Prometheus textfile collector when observability exists (counts per scanner/severity; plusquorum_advice_*when--adviceis on). - [ ]
--log-format jsonenabled when the log aggregator consumes NDJSON. - [ ] Egress-less environment:
--offlineon (turns off OSV and blocks remote advice; alias consensus falls back to the local cache). Grype DB on:fulldoes not expire.
5.7 Optional advisory layer¶
- [ ] Advisory is off by default; enable with
--advicewhen you want human-readable remediation/references attached — output stays presentation-only and never changes the gate. - [ ] Phase 0/2 run offline and deterministically (curated templates + the
digest-pinned OWASP corpus);
quorum advise-indexembeds the corpus for semantic retrieval, preserving the pin. - [ ]
--advice-provider=localpoints at an on-host OpenAI-compatible endpoint (e.g. Ollama via--advice-endpoint); reproducible (temperature=0+--advice-cache); degrades gracefully if the model is unreachable. - [ ]
--advice-provider=remoteused only with explicit consent (--advice-allow-egress,QUORUM_ADVICE_API_KEY), is blocked by--offline, refuses--fix, and sends only the normalized finding. - [ ]
--fix=suggestproposals are treated as suggestions only (verify-the-fix re-scan, never auto-applied); a human still reviews and applies them. - [ ] Every AI attachment is read as "AI-generated, advisory only".
5.8 Operation and diagnosis¶
- [ ] The stderr summary (
── quorum summary ──) inspected: per-scanner status, multi-detected count, severities,elapsed. - [ ]
unavailable/timeout/errorstatuses treated as a signal — not as "clean". Remember: "0 findings is not proof of safety". - [ ] On OOM (
version probe killed/signal: killedor output above the cap): raise the container memory limit or the cap. - [ ]
quorum list-scannersused to confirm which of the 12 adapters are registered/packaged in the image in use.
Assumptions¶
- Reference version: documentation written for Quorum v0.8.3
(revision 2026-07-04), based on the current state of the repository (
README.md,DESIGN.md,cmd/quorum/{root,scan,advise_index}.go,internal/adapter/*.go,internal/orchestrator/orchestrator.go,internal/{enrich,rag,advisor,evals},knowledge/*.yaml,.github/workflows/{ci,e2e,release,tag-major}.yml,action.yml,Dockerfile.full,.goreleaser.yaml,crosswalk/*.yaml). Items marked as behavior (exit codes, status, flags, env) reflect the code as-is. - Product scope: CLI/Docker only is assumed. Checklist items that in enterprise templates would deal with a web frontend, relational database or REST API are N/A by design and were deliberately omitted (there is no corresponding surface in the code). AI/LLM is not out of scope, but it lives strictly in the opt-in advisory layer (off by default, presentation-only); the deterministic core has no AI.
- Owner/repo: the verification commands use
ghcr.io/martinez1991/quorum-sec-scanandMartinez1991/quorum-sec-scan, as inREADME.md/action.yml/release.yml. In forks, adjust the owner/cosign certificate identity. - Typical production environment: execution in a CI/CD pipeline is assumed
(GitHub Actions, GitLab CI or
docker run), not a cluster runtime — Quorum has no resident component. "Production/Operation" items refer to operating the scanner in a pipeline. RBAC via kubescape is single-engine (needs cluster context) and is documented as such. - Platforms:
:fullislinux/amd64only (scanner binaries are amd64);:slimcoversamd64+arm64. Mount/execution checklists assume a host capable of running the target image (e.g. emulation for arm64). - Version probe: the 60s value (
Options.ProbeTime/defaultProbeTime) is treated as fixed; if exposed via a flag in future versions, item 5.3 must be updated. - Version in the binary:
main.versiondefaults to0.1.0, overridden at build-time via-ldflags "-X main.version=…"in the release; v0.8.3 here refers to the published product version, not a literal hard-coded in the code.