Skip to content

13. AI (Artificial Intelligence)

Reference version: v0.8.3 — revision of 2026-07-04.

This document describes, faithfully to the code (as-is), the use of Artificial Intelligence in Quorum (quorum-sec-scan, v0.8.3). The one-sentence summary: Quorum's core does not use AI and is 100% deterministic; there is an opt-in advisory layer (--advice, off by default) that can query a local or remote model, and which never touches the core.

Core (always, no AI). There is no LLM/ML in the path that decides findings: the orchestration of the 12 OSS scanners, the canonical normalization, the correlationKey correlation, the crosswalk (crosswalk/*.yaml) and the consensus score are deterministic and rule-based. The Fingerprint = sha256(correlationKey) and the pass/fail gate decision are reproducible and independent of any model. The only external dependency that could be mistaken for "intelligence" is OSV.dev, a deterministic, non-ML HTTP API (see §2).

Deterministic OWASP retrieval (Phase 2, under --advice, no AI). Under --advice, in addition to the Phase 0 templates, Quorum runs RAG over a versioned, digest-pinned OWASP corpus (knowledge/owasp/corpus.yaml, package internal/rag) and attaches the most relevant passages as references. The default retrieval is lexical (deterministic, air-gapped, no model); there is a semantic path via embeddings when the corpus carries vectors (built with quorum advise-index) and a local endpoint is available — scan auto-picks semantic once the corpus is embedded. This is not LLM inference — it is retrieval over an immutable artifact.

Opt-in advisory layer with an LLM (Phase 1/3, off by default). When — and only when — the operator passes --advice --advice-provider=local, Quorum queries a local model (OpenAI-compatible endpoint, e.g. Ollama) to generate a natural-language recommendation and, under --fix=suggest, a verified patch (only shown if it survives a re-scan — verify-the-fix). This output is presentation-only, always labeled "AI-generated, advisory only", and does not change correlationKey/fingerprint/confidence/severity nor the gate. Without the flag, the report is byte-identical to a build with no AI. A remote provider (--advice-provider=remote) also exists and is gated far more tightly (see §4). The full design and guardrails are in 21-proposta-ia; the risk implications (the OWASP LLM Top 10 stops being N/A once the layer is enabled) are in §4.

Cross-links: DESIGN.md (data model, correlation matrix §6, consensus math, aliasing §7), README.md.


1. Verdict: why the core is AI-free (and AI stays opt-in)

Quorum is a correlation + consensus layer over open-source security scanners. In v0.8.3 there are 12 orchestrated scanners: Trivy, Grype, Checkov, KICS, Dockle, Kubescape, Polaris, kube-score (K8S_POSTURE), Terrascan, tfsec, Regula (MISCONFIG/IaC) and Conftest (policy-as-code, runs the Rego from ./policy). All adapters live in internal/adapter. It is CLI/Docker only, designed to run inside a CI/CD pipeline and to "gate" a build via exit code. In this design, determinism and reproducibility are first-order requirements: the same input must produce the same Fingerprint = sha256(correlationKey) on any run, so that GitHub code scanning / DefectDojo can deduplicate findings across runs.

Consensus, which in v0.2.3 was restricted to SCA, now also operates on MISCONFIG/K8S via a crosswalk derived from real scanner output (principle "false split > false merge") — crosswalk/aws.yaml, crosswalk/azure.yaml, crosswalk/gcp.yaml (AVD hub) and crosswalk/k8s.yaml (Kubescape C-#### hub). This remains deterministic rule matching, not model inference.

Generative AI is, by nature, probabilistic and non-deterministic, which would directly collide with:

  • the "false split > false merge" design principle (when in doubt, keep findings separate — a wrong merge hides risk);
  • the requirement of stable fingerprints across runs;
  • the auditability required of a security tool that decides whether a build passes or fails.

Because of this, the core carries no model, and the AI parts are strictly opt-in and off by default.

Evidence in the code (verified in v0.8.3):

  • go.mod declares only github.com/spf13/cobra and gopkg.in/yaml.v3 as direct dependencies (plus indirect pflag/mousetrap). No ML/LLM/vector library is vendored — the opt-in advisory layer talks to an external OpenAI-compatible endpoint over net/http and needs no model runtime in the binary.
  • The deterministic core path (orchestrate → normalize → alias → crosswalk → correlate → score → report) imports no AI code. Every AI-touching term (llm, embedding, rag, advice, advisor, openai) is confined to the opt-in packages internal/advisor, internal/rag, internal/enrich, internal/evals and test fixtures. The word "vector" in internal/adapter/testdata/sca_grype_alpine.json and sca_trivy_alpine.json is a CVSS vector string (e.g. CVSS:3.1/AV:N/AC:L/...), unrelated to AI.
  • Without --advice, none of the advisory code runs and the report is byte-identical to a build with no AI at all. The core's only network client remains internal/alias/osv.go — a net/http GET against https://api.osv.dev/v1/vulns/<id> (see §2).
flowchart LR
  T[target] --> O[orchestrator<br/>parallel fan-out]
  O --> S["12 OSS scanners<br/>(trivy/grype/checkov/kics/<br/>dockle/kubescape/polaris/<br/>kube-score/terrascan/tfsec/<br/>regula/conftest)"]
  S --> N[normalize<br/>model.Finding]
  N --> A["resolve aliases<br/>(OSV.dev — HTTP API)"]
  A --> X["crosswalk<br/>rule→canonicalControl<br/>(deterministic YAML)"]
  X --> C["correlate<br/>deterministic correlationKey"]
  C --> SC["score<br/>confidence (formula)"]
  SC --> R[report<br/>SARIF/JSON/XML + metrics]
  classDef ai fill:#fdd,stroke:#c00;
  classDef det fill:#dfd,stroke:#080;
  class O,S,N,X,C,SC,R det;
  class A det;

Note: the "resolve aliases" step uses the network (OSV.dev), but remains deterministic and non-ML. No box in the pipeline contains a model. The crosswalk is just rule matching loaded from versioned YAML. The opt-in advisory layer (--advice) is a separate, post-correlation presentation pass — it is not on this decision path.


2. The only external "intelligence": OSV.dev (deterministic, non-ML)

Alias resolution (internal/alias/) unifies vulnerability identifiers — for example, Grype's GHSA-… and Trivy's CVE-… for the same bug — so they correlate instead of splitting (DESIGN §7).

This is not AI. It is a three-layer lookup chain, with a deterministic preference for CVE:

flowchart TD
  ID[vuln id + scanner-local aliases] --> L1{CVE already present?}
  L1 -- yes --> OUT[return CVE]
  L1 -- no --> L2{local cache hit?<br/>~/.cache/quorum/aliases.json}
  L2 -- yes --> OUT2[return cached value]
  L2 -- no --> L3{--offline?}
  L3 -- yes --> DEG[degrade: best local id]
  L3 -- no --> OSV["OSV.dev GET /v1/vulns/&lt;id&gt;<br/>HTTP 8s timeout, 2 retries"]
  OSV -- ok --> PICK[preferCVE aliases → write cache]
  OSV -- network error --> DEG2[degrade gracefully]

Relevant properties (from internal/alias/resolver.go and osv.go, confirmed in v0.8.3):

Property Value Why it matters
Service type JSON HTTP API (api.osv.dev/v1/vulns/<id>) Alias-database lookup, not model inference
Determinism preferCVE: CVE > GHSA > first non-empty Same input → same output
ML involved None Curated community-database lookup
Network failure Graceful degradation (never fails the scan) DESIGN §7
Turn off --offline flag (passes osv=nil) Fully local/air-gapped run
Timeout/retries Timeout: 8s, MaxRetries=2, exponential backoff CI robustness
On-disk cache aliases.json with perm 0600 and schemaVersion Reproducibility and hygiene

Conclusion: OSV.dev is equivalent to a DNS/whois for vulnerabilities — deterministic reference data, not a model that "reasons".


3. AI-template items — status item by item

The table below covers each item expected in an enterprise AI section and states its status for Quorum as-is (v0.8.3). Because the advisory layer is opt-in and off by default, each item has two states: the default build (no --advice), and the build with --advice enabled.

Template item Default (no --advice) With --advice enabled
Language models (LLM) N/A — no LLM in the decision path Opt-in local/remote model, presentation-only (internal/advisor)
Model provider (OpenAI/Anthropic/etc.) N/A — no provider client active Any OpenAI-compatible endpoint (local, e.g. Ollama) or a remote API
Prompts / prompt templates N/A — no prompts Fixed system prompt; finding content passed as delimited UNTRUSTED DATA (internal/advisor/prompt.go)
RAG (Retrieval-Augmented Generation) N/A — no generation RAG-as-artifact over a digest-pinned OWASP corpus (internal/rag), deterministic
Embeddings / semantic search N/A — correlation is by deterministic correlationKey + YAML crosswalk Optional: cosine top-k over baked-in corpus vectors when embedded via quorum advise-index
Vector database (pgvector/Pinecone/etc.) N/A — no vector DB Still none: vectors live inline in the pinned corpus file, not a live DB
Fine-tuning / model training N/A — no model to train N/A — Quorum trains nothing; it only queries an external model
Inference / model serving N/A — no inference runtime (no ONNX/TF/PyTorch) Served outside the binary by the operator's endpoint; no runtime is vendored
MCP (Model Context Protocol) N/A — not an MCP client/server N/A — the advisory layer speaks OpenAI-compatible HTTP, not MCP
Agents / agentic orchestration N/A — "orchestrator" = goroutine fan-out to 12 scanners N/A — single request/response per finding; the only loop is verify-the-fix (a re-scan, not an agent)
Function-calling / model tool-use N/A — no model to invoke tools N/A — plain text completion; no tool-calling is used
Model guardrails / content moderation N/A — no model output Anti prompt-injection prompt, advisory-only labeling, --advice-max cap, output clamped
Model evaluation (evals) Adapter contract tests validate quality (CI coverage) internal/evals harness measures remediation coverage, OWASP reference relevance, and the verify-the-fix rate (runs in CI, no heavy model)
AI observability (token/cost tracing) N/A — no model calls; telemetry (--metrics, --log-format) is about execution Advisory metrics: quorum_advice_enriched{kind}, quorum_advice_provider{provider}, quorum_advice_fix{stage} (verified/proposed = the verify-the-fix rate)
Inference costs N/A — OSV.dev is free and deterministic Local: on-host compute only. Remote: whatever the external API charges (operator's account)
Model versioning / model registry N/A — versioning is of the binary/image (GoReleaser/GHCR, SLSA attestation + SBOM) Provider/model recorded on each Advice; the OWASP corpus is digest-pinned and gets its own SLSA provenance attestation each release
Privacy of data sent to models N/A — nothing sent to an LLM; only the vuln id goes to OSV.dev Local: nothing leaves the host. Remote: only the normalized finding is sent, never source code, and only with explicit consent (see §4)

4. AI risks — applicability with justification

With the advisory layer off (default), there is no AI component in the execution path and the AI-specific attack surface does not exist — the table below applies in full. When the operator enables --advice-provider=local, the OWASP LLM Top 10 items start to apply and are mitigated like this: finding content is sent as delimited untrusted data (the system prompt forbids treating it as instructions — anti prompt-injection); output is advisory-only and labeled, never changing the gate (bounds insecure output handling/excessive agency); the model is local (no code leaves the host); and every patch goes through verify-the-fix (a re-scan) before it appears (mitigates hallucination). The model artifact is a supply-chain dependency to pin/attest. See 21-proposta-ia §8.

Remote provider (Phase 3, --advice-provider=remote). Only here does data leave the host: the normalized findings (titles, paths, controls) go to an external API. That is why it is off by default and gated on explicit consent (--advice-allow-egress + QUORUM_ADVICE_API_KEY), blocked by --offline, and refuses --fix (it would upload source code). Only the normalized finding is sent — never the source. Sensitive information disclosure is thus limited to finding metadata, with consent.

AI risk (OWASP LLM Top 10 / similar) Default status Why (and how it is bounded when enabled)
Prompt injection (direct/indirect) N/A off Under --advice: finding content is delimited untrusted data; the system prompt forbids treating it as instructions
Jailbreak / system-prompt bypass N/A off Under --advice: output is advisory-only and cannot change correlation/gate, so a bypass yields at most bad prose
Data poisoning (training-data) N/A Quorum trains nothing; the OWASP corpus is digest-pinned and attested
Model poisoning / model supply chain N/A off Under --advice: the model artifact is an external, operator-pinned dependency; no model ships in the image/binary
Hallucination N/A off Under --advice: recommendations are advisory-only; every suggested patch must pass a verify-the-fix re-scan before it is shown
Insecure output handling N/A off Reports (SARIF/JSON/XML) are structured serialization; AI text is a labeled, clamped attachment that never drives the gate
Sensitive information disclosure via model N/A off Local: nothing leaves the host. Remote: only normalized finding metadata, gated on consent; secrets are redacted in outputs
Excessive agency N/A off Under --advice: no agent; the only action is proposing a patch, which is never auto-applied (verify-the-fix on a temp copy)
Model denial of service / runaway cost N/A off Under --advice: --advice-max caps findings; local compute is on-host; remote is off by default. Execution DoS caps: QUORUM_MAX_OUTPUT_BYTES (512MiB), QUORUM_MAX_TARGET_BYTES (20GiB)

Quorum's real risks (supply chain of the scanner images/binaries, MISCONFIG over-merge, false negatives from a malformed mount) are handled outside this section — see DESIGN §12 (supply chain), §12-security and the README ("Known limitations", "Security of the chain itself"). These are traditional-software risks, not AI risks.


5. Conformance checklist (current state — v0.8.3)

  • [x] Confirmed the core imports no LLM/AI provider (go.mod reviewed: only cobra + yaml.v3; the advisory layer talks to an external endpoint over net/http).
  • [x] Confirmed the core decision path has no RAG/embeddings/vector DB; the RAG under --advice is deterministic retrieval over a digest-pinned artifact (internal/rag).
  • [x] Confirmed there is no MCP/agent/function-calling anywhere.
  • [x] Confirmed there is no inference runtime vendored (no ONNX/TF/PyTorch); a local model is served by the operator's own endpoint.
  • [x] Confirmed the 12 adapters (internal/adapter) and the crosswalk (crosswalk/*.yaml) are deterministic rules, with no ML.
  • [x] Confirmed the core's only network client is OSV.dev (internal/alias/osv.go).
  • [x] Confirmed OSV.dev is switchable off via --offline (air-gapped mode), which also blocks the remote advice provider.
  • [x] Confirmed the advisory layer is opt-in and off by default; without --advice the report is byte-identical to an AI-free build.
  • [x] Confirmed no user source code leaves the host: local advice stays on-host; remote sends only normalized findings, is consent-gated (--advice-allow-egress), and refuses --fix.
  • [x] Confirmed evals (internal/evals) gate advisory quality in CI (remediation coverage, OWASP reference relevance, verify-the-fix rate).

6. The advisory layer (implemented — clearly separated from the core)

Everything in this section is presentation-only and off by default. It never touches the deterministic core (correlation, fingerprint, confidence, aggregated severity, or the fail-on gate). Without --advice, none of it runs.

📄 The detailed design lives in 21-proposta-ia.md — the opt-in advisory layer (local-first recommendations, two-tier remediation with verify-the-fix, and RAG-as-artifact over a pinned OWASP corpus). Phases 0–3 are now implemented.

The four phases, all shipped in v0.8.3:

  1. Phase 0 — deterministic enrichment (no model). Curated remediation templates + OWASP references, matched by canonicalControl/ruleId/category/type (package internal/enrich; data in knowledge/*.yaml). Populates MergedFinding.Remediation and References.
  2. Phase 2 — RAG-as-artifact (deterministic). Retrieval from a versioned, digest-pinned OWASP corpus (knowledge/owasp/corpus.yaml, internal/rag). Lexical by default; semantic when the corpus is embedded via quorum advise-index. Never generates text — it only retrieves.
  3. Phase 1 — opt-in local LLM. --advice-provider=local queries an on-host OpenAI-compatible endpoint for a recommendation; --fix=suggest proposes a patch that must pass a verify-the-fix re-scan (applied to a temp copy, re-scanned with the same scanner, kept only if the finding is gone and the file still parses; never auto-applied). Reproducible via temperature=0 + an on-disk cache keyed by fingerprint+provider+model.
  4. Phase 3 — opt-in remote provider. --advice-provider=remote calls an external API (auth via QUORUM_ADVICE_API_KEY); gated on --advice-allow-egress, blocked by --offline, and refuses --fix. Only the normalized finding is sent.

Guardrails (enforced in code):

Guardrail Rule
Explicit opt-in The whole layer is behind --advice, off by default
Untouchable core The LLM cannot change correlation, fingerprint, confidence or exit code
Gate determinism The pass/fail decision stays 100% deterministic
Privacy Local sends nothing off-host; remote sends only normalized findings, never raw source, and only with consent
Offline mode --offline disables the remote provider (as it already does OSV)
Anti prompt-injection Finding content is treated as delimited data, not instructions
Labeling Every model-generated attachment is marked "AI-generated, advisory only"
Auditability Provider/model recorded on each attachment; temperature=0 + cache for reproducibility
Cost/limits --advice-max cap, timeouts and graceful fallback (same posture as the OSV client)
Evals The internal/evals suite gates advisory quality in CI before release

Assumptions

  • The analysis reflects the repository state at v0.8.3, branch main, verified via go.mod and textual search for AI terms across the code.
  • "OSV.dev" is treated as a deterministic data service (alias lookup), not an ML system — consistent with internal/alias/osv.go and DESIGN §7.
  • The term "orchestrator" in Quorum refers to the parallel fan-out of the 12 scanners (internal/orchestrator), not an AI agent; this is assumed from the total absence of a model in the decision path.
  • The crosswalk (crosswalk/*.yaml) is assumed to be deterministic rule configuration derived from real scanner output, not a learned classifier — consistent with the adapters in internal/adapter.
  • The advisory layer is assumed to be presentation-only and off by default; every claim of "byte-identical without --advice" is assumed to hold because the advisory packages are only invoked when the flag is set.
  • Test fixtures (internal/adapter/testdata/) are assumed not to be part of the production execution path (they are contract-test data); the word "vector" that appears in them refers to CVSS vector strings, not embeddings.