Files
git.stella-ops.org/docs/modules/export-center/trivy-adapter.md
master 7b5bdcf4d3 feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules
- Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes.
- Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes.
- Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables.
- Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs.
2025-10-30 00:09:39 +02:00

11 KiB

Export Center Trivy Adapters

The Trivy adapters translate StellaOps normalized advisories into the format consumed by Aqua Security's Trivy scanner. They enable downstream tooling to reuse StellaOps' curated data without bespoke converters, while preserving Aggregation-Only Contract (AOC) boundaries. This guide documents bundle layouts, field mappings, compatibility guarantees, validation workflows, and configuration toggles introduced in Sprint 36 (EXPORT-SVC-36-001, EXPORT-SVC-36-002).

The current Export Center build is wiring the API and workers. Treat this document as the canonical interface for adapter implementation and update any behavioural changes during task sign-off.

1. Adapter overview

Variant Bundle Default profile Notes
trivy:db db.bundle trivy:db Core vulnerability database compatible with Trivy CLI >= 0.50.0 (schema v2).
trivy:java-db java-db.bundle Optional extension Java ecosystem supplement (Maven, Gradle). Enabled when ExportCenter:Profiles:Trivy:EnableJavaDb=true.

Both variants ship inside the export run under /export/trivy/. Each bundle is a gzip-compressed tarball containing:

metadata.json
trivy.db                # BoltDB file with vulnerability/provider tables
packages/*.json         # Only when schema requires JSON overlays (language ecosystems)

The adapters never mutate input evidence. They only reshape normalized advisories and copy the exact upstream references so consumers can trace provenance.

2. Bundle layout

trivy/
  db.bundle
    +-- metadata.json
    +-- trivy.db
  java-db.bundle        # present when Java DB enabled
    +-- metadata.json
    +-- trivy-java.db
    +-- ecosystem/...
signatures/
  trivy-db.sig
  trivy-java-db.sig

metadata.json aligns with Trivy's expectations (schemaVersion, buildInfo, updatedAt, etc.). Export Center adds an stella block to capture profile id, run id, and policy snapshot hints.

Example metadata.json (trimmed):

{
  "schemaVersion": 2,
  "buildInfo": {
    "trivyVersion": "0.50.1",
    "vulnerabilityDBVersion": "2025-10-28T00:00:00Z"
  },
  "updatedAt": "2025-10-29T11:42:03Z",
  "stella": {
    "runId": "run-20251029-01",
    "profileId": "prof-trivy-db",
    "tenant": "acme",
    "policySnapshotId": "policy-snap-42",
    "schemaVersion": 2
  }
}

3. Field mappings

3.1 Namespace resolution

Stella field Trivy field Notes
advisory.source.vendor namespace Canonicalized to lowercase; e.g. Ubuntu -> ubuntu.
advisory.source.product distribution / ecosystem Mapped via allowlist (Ubuntu 22.04 -> ubuntu:22.04).
package.ecosystem package.ecosystem OSS ecosystems (npm, pip, nuget, etc.).
package.nevra / package.evr package.version (OS) RPM/DEB version semantics preserved.

If a record lacks a supported namespace, the adapter drops it and logs adapter.trivy.unsupported_namespace.

3.2 Vulnerability metadata

Stella field Trivy field Transformation
advisory.identifiers.cve[] vulnerability.CVEIDs Array of strings.
advisory.identifiers.aliases[] vulnerability.CWEIDs / References CVE -> CVEIDs, others appended to References.
advisory.summary vulnerability.Title Stripped to 256 chars; rest moved to Description.
advisory.description vulnerability.Description Markdown allowed, normalized to LF line endings.
advisory.severity.normalized vulnerability.Severity Uses table below.
advisory.cvss[] vulnerability.CVSS Stored as {"vector": "...", "score": 7.8, "source": "NVD"}.
advisory.published vulnerability.PublishedDate ISO 8601 UTC.
advisory.modified vulnerability.LastModifiedDate ISO 8601 UTC.
advisory.vendorStatement vulnerability.VendorSeverity / VendorVectors Preserved in vendor block.

Severity mapping:

Stella severity Trivy severity
critical CRITICAL
high HIGH
medium MEDIUM
low LOW
none / info UNKNOWN

3.3 Affected packages

Stella field Trivy field Notes
package.name package.name For OS distros uses source package when available.
package.purl package.PURL Copied verbatim.
affects.vulnerableRange package.vulnerableVersionRange SemVer or distro version range.
remediations.fixedVersion package.fixedVersion Latest known fix.
remediations.urls[] package.links Array; duplicates removed.
states.cpes[] package.cpes For CPE-backed advisories.

The adapter deduplicates entries by (namespace, package.name, vulnerableRange) to avoid duplicate records when multiple upstream segments agree.

Example mapping (Ubuntu advisory):

// Stella normalized input
{
  "source": {"vendor": "Ubuntu", "product": "22.04"},
  "identifiers": {"cve": ["CVE-2024-12345"]},
  "severity": {"normalized": "high"},
  "affects": [{
    "package": {"name": "openssl", "ecosystem": "ubuntu", "nevra": "1.1.1f-1ubuntu2.12"},
    "vulnerableRange": "< 1.1.1f-1ubuntu2.13",
    "remediations": [{"fixedVersion": "1.1.1f-1ubuntu2.13"}]
  }]
}

// Trivy vulnerability entry
{
  "namespace": "ubuntu",
  "package": {
    "name": "openssl",
    "version": "< 1.1.1f-1ubuntu2.13",
    "fixedVersion": "1.1.1f-1ubuntu2.13"
  },
  "vulnerability": {
    "ID": "CVE-2024-12345",
    "Severity": "HIGH"
  }
}

3.4 Java DB specifics

The Java supplement only includes ecosystems maven, gradle, sbt. Additional fields:

Stella field Trivy Java field Notes
package.group GroupID Derived from Maven coordinates.
package.artifact ArtifactID Derived from Maven coordinates.
package.version Version Compared with semver-lite rules.
affects.symbolicRanges[] VulnerableVersions Strings like [1.0.0,1.2.3).

4. Compatibility matrix

Trivy version Schema version Supported by adapter Notes
0.46.x 2 Yes Baseline compatibility target.
0.50.x 2 Yes Default validation target in CI.
0.51.x+ 3 Pending Adapter throws ERR_EXPORT_UNSUPPORTED_SCHEMA until implemented.

Schema mismatches emit adapter.trivy.unsupported_schema_version and abort the run. Operators can pin the schema via ExportCenter:Adapters:Trivy:SchemaVersion.

5. Validation workflow

  1. Unit tests (StellaOps.ExportCenter.Tests):
    • Mapping tests for OS and ecosystem packages.
    • Severity conversion and range handling property tests.
  2. Integration tests (EXPORT-SVC-36-001):
    • Generate bundle from fixture dataset.
    • Run trivy module db import <bundle> (Trivy CLI) to ensure the bundle is accepted.
    • For Java DB, run trivy java-repo --db <bundle> against sample repository.
  3. CI smoke (DEVOPS-EXPORT-36-001):
    • Validate metadata fields using jq.
    • Ensure signatures verify with cosign.
    • Check runtime by invoking trivy fs --cache-dir <temp> --skip-update --custom-db <bundle> fixtures/image.

Failures set the run status to failed with errorCode="adapter-trivy" so Console/CLI expose the reason.

6. Configuration knobs

ExportCenter:
  Adapters:
    Trivy:
      SchemaVersion: 2           # enforce schema version
      IncludeJavaDb: true        # enable java-db.bundle
      AllowEmpty: false          # fail when no records match
      MaxCvssVectorsPerEntry: 5  # truncate to avoid oversized payloads
  Distribution:
    Oras:
      TrivyRepository: "registry.example.com/stella/trivy-db"
      PublishDelta: false
    Download:
      FilenameFormat: "trivy-db-{runId}.tar.gz"
      IncludeMetadata: true
  • AllowEmpty=false converts empty datasets into ERR_EXPORT_EMPTY.
  • MaxCvssVectorsPerEntry prevents extremely large multi-vector advisories from bloating the DB.
  • PublishDelta works in tandem with the planner's delta logic; when true, only changed blobs are pushed.
  • FilenameFormat lets operators align downloads with existing mirror tooling.
  • IncludeMetadata toggles whether metadata.json is stored alongside the bundle in the staging directory for quick inspection.

7. Distribution guidelines

  • Download profile: db.bundle placed under /export/trivy/ and signed. Recommended filename trivy-db-<runId>.tar.gz.
  • OCI push: ORAS artifact with annotations:
    • org.opencontainers.artifact.description=StellaOps Trivy DB
    • io.stella.export.profile=trivy:db
    • io.stella.export.run=<runId>
    • io.stella.export.schemaVersion=2
  • Offline Kit: When offlineBundle.includeTrivyDb=true, the exporter copies the latest full bundle plus the last N deltas (configurable) with manifests for quick import.

Consumers should always verify signatures using trivy-db.sig / trivy-java-db.sig before trusting the bundle.

Example verification flow:

cosign verify-blob \
  --key tenants/acme/export-center.pub \
  --signature signatures/trivy-db.sig \
  trivy/db.bundle

trivy module db import trivy/db.bundle --cache-dir /tmp/trivy-cache

8. Troubleshooting

Symptom Likely cause Remedy
ERR_EXPORT_UNSUPPORTED_SCHEMA Trivy CLI updated schema version. Bump SchemaVersion, extend mapping tables, regenerate fixtures.
adapter.trivy.unsupported_namespace Advisory namespace not in allowlist. Extend namespace mapping or exclude in selector.
trivy import fails with "invalid bolt page" Corrupted bundle or truncated upload. Re-run export; verify storage backend and signatures.
Missing Java advisories IncludeJavaDb=false or no Java data in Findings Ledger. Enable flag and confirm upstream connectors populate Java ecosystems.
Severity downgraded to UNKNOWN Source severity missing or unrecognized. Ensure upstream connectors populate severity or supply CVSS scores.
ERR_EXPORT_EMPTY returned unexpectedly Selectors yielded zero records while AllowEmpty=false. Review selectors; set AllowEmpty=true if empty exports are acceptable.

9. References

Imposed rule: Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.