kolm  /  docs  /  cve audit in the k-score

CVE audit is part of the K-score.

Procurement asks "any known CVEs?" Every compile answers in the manifest itself. Two scanners cross-check the dependency tree at compile time, the result is signed into the artifact, and the K-score's V component refuses to clear the deploy gate if the audit is not clean.

Scanners Trivy + GrypeBound to manifest.dependencies.cve_auditGate K >= 0.85

Why this matters.

Regulated buyers do not trust prose. "No known CVEs" in a vendor questionnaire is a checkbox; "no known CVEs in the artifact's dependency tree at the moment of compile, signed into the manifest, replayable months later from the receipt" is evidence. The two read differently in a procurement review.

kolm runs vulnerability scanning at two points: in CI on every release (see /security section 07), and at compile time on every customer artifact. This page describes the compile-time step and how it folds into the K-score.

What runs at compile time.

Compile resolves the artifact's dependency tree (Node, Python, system libs in the base image) and passes the resulting bill of materials to two scanners independently:

  • Trivy (aquasec/trivy) scans OS packages, language ecosystems, and OCI layers. Output is CVE IDs grouped by severity.
  • Grype (anchore/grype) scans the same tree with a different vulnerability database (NVD + GitHub Security Advisories + OS-specific feeds). Output is the same shape.

Two scanners are run because a single scanner's false-negative is procurement risk. If they disagree on a CVE, the union is taken and the union is what gates the artifact.

What gets written to the manifest.

The compile pipeline writes a dependencies.cve_audit object into the manifest before signing. The object captures both scanners' findings, the scan timestamp, and a single ok boolean that the K-score gate reads:

{
  "dependencies": {
    "cve_audit": {
      "trivy": {
        "critical": 0,
        "high": 0,
        "medium": 2,
        "low": 5,
        "unknown": 0,
        "db_version": "2026-05-15T03:00:00Z"
      },
      "grype": {
        "critical": 0,
        "high": 0,
        "medium": 3,
        "low": 4,
        "unknown": 0,
        "db_version": "2026-05-15T02:14:00Z"
      },
      "scanned_at": "2026-05-15T10:42:11Z",
      "ok": true,
      "policy": "no critical, no high with patched-version available"
    }
  }
}

The shape is stable and forms part of the manifest schema (see manifest-v0.1.json). The ok value is the single field the K-score gate reads; the per-severity counts are surfaced for buyer reports.

How the K-score gate uses it.

The K-score's V (Verifiability) component requires cve_audit.ok === true for the artifact to clear the default K >= 0.85 deploy gate. If ok is false, V is forced to 0 regardless of receipt verifier agreement, which is enough to drag K under the gate even with a perfect A on the eval set.

The policy default for ok is: zero Critical, zero High where a patched version is available, and at most five Medium where a patched version is available. The policy is recorded next to the counts in the manifest so a procurement reviewer can read the exact bar that was applied.

Recipes can tighten the policy with --gate-cve-policy=strict (zero Critical, zero High, zero Medium with patched-version available) or relax to permissive for experimental workloads. Both options are recorded; neither hides the underlying counts.

kolm compile recipes/phi-redactor.yaml \
  --base llama-3.1-8b \
  --k-min=0.90 \
  --gate-cve-policy=strict

How a buyer verifies it.

The receipt re-emits the relevant cve_audit fields per inference so a long-running deploy can be audited later. Trivy and Grype databases get new entries over time; a clean compile yesterday is not a guarantee against a CVE disclosed today.

$ kolm inspect support-triage.kolm | jq '.manifest.dependencies.cve_audit'
{
  "trivy": { "critical": 0, "high": 0, "medium": 2, "low": 5 },
  "grype": { "critical": 0, "high": 0, "medium": 3, "low": 4 },
  "scanned_at": "2026-05-15T10:42:11Z",
  "ok": true,
  "policy": "no critical, no high with patched-version available"
}

# the V component on the receipt also surfaces the latest re-scan:
$ kolm inspect support-triage.kolm | jq '.receipt.k.V'
{
  "value": 0.94,
  "verifier_agreement_rate": 0.94,
  "cve_audit_ok": true,
  "cve_audit_rescanned_at": "2026-05-15T18:00:00Z"
}

The rescan job is part of the runtime container's health check; it runs once per 24 hours against the artifact's locked dependency tree. If a new CVE drops cve_audit_ok to false mid-deploy, the receipt records the drop and the dashboard surfaces a warning.

Cross-links.

Where this fits with the rest of the kolm trust surface:

  • /docs/k-score-methodology defines the full K = 0.40A + 0.15S + 0.15L + 0.15C + 0.15V formula; this page covers the cve sub-check inside V.
  • /security section 07 covers Trivy + Grype + npm audit + pip-audit + CodeQL on the kolm repo itself.
  • /sbom is the CycloneDX dependency tree that the scanners read at compile time.
  • /slsa is the build-provenance attestation that binds artifact bytes to source commit; CVE audit is bound through the same manifest.

Procurement reviewers who want a written attestation that a specific artifact passed a specific CVE policy can request one with the artifact's CID: mail security@kolm.ai; typical turnaround one business day.