15 KiB
Here’s a crisp, practical game plan to take your SBOM/VEX pipeline from “SBOM‑only” → “VEX‑ready” → “signed, provable evidence graph” with Rekor inclusion‑proof checks—plus an explainability track you can ship alongside it.
1) Freeze on SBOM specs (CycloneDX + SPDX)
- Adopt two inputs only: CycloneDX v1.6 (Ecma ECMA‑424) and SPDX 3.0.1. Lock parsers and schemas; reject anything else at ingest. (Ecma International)
- Scope notes: CycloneDX covers software/hardware/ML/config & provenance; SPDX 3.x brings a richer, granular data model. (CycloneDX)
Action:
Sbomer.Ingestaccepts*.cdx.jsonand*.spdx.jsononly.- Validate against ECMA‑424 (CycloneDX 1.6) and SPDX 3.0.1 canonical docs before storage. (Ecma International)
2) Wire VEX predicates (VEXer)
- Model: in‑toto Attestation layered as DSSE Envelope → in‑toto Statement → VEX predicate payload. (Legit Security)
- Why DSSE: avoids fragile canonicalization; standard across in‑toto/Sigstore. (Medium)
Action:
- Accept VEX as an attestation (JSON) with
statementType: in-toto,predicateType: VEX. Wrap/verify via DSSE at the edge. (Legit Security)
3) Sign every artifact & edge (Authority)
- Artifacts to sign: SBOM files, VEX attestations, and each evidence edge you materialize in the proof graph (e.g., “image X derives from build Y,” “package Z fixed in version…”)—all as DSSE envelopes. (in-toto)
- Sigstore/Cosign path: Sign + optionally keyless; publish signatures/attestations; send to Rekor. (Sigstore)
Action:
- Output:
{ artifact, DSSE-envelope, signature, Rekor UUID }per node/edge. - Keep offline mode by queueing envelopes; mirror later to Rekor.
4) Rekor inclusion‑proofs (Proof Service)
- Goal: For every submitted signature/attestation, store the Rekor UUID, log index, and verify inclusion proofs regularly. (Sigstore)
CLI contract (reference):
rekor-cli verify --rekor_server <url> --signature <sig> --public-key <pub> --artifact <path>(yields inclusion proof). (Sigstore)
Action:
- Background metrics: “% entries with valid inclusion proof,” “median verify latency,” “last inclusion‑proof age.” (Sigstore)
5) Deterministic evidence graph (Graph & Ledger)
- Store hash‑addressed nodes and signed edges; persist the DSSE for each.
- Export a deterministic ledger dump (stable sort, normalized JSON) to guarantee byte‑for‑byte reproducible rebuilds.
- Track provenance chain from container → build → source → SBOM → VEX.
6) Explainability: Smart‑Diff + Reachability + Scores
- Human‑readable proof trails: For every verdict, render the chain: finding → SBOM component → VEX predicate → reachability basis → runtime/CFG evidence → signature + Rekor proof.
- Smart‑Diff: Image‑to‑image diff includes env/config deltas; highlight changes that flip reachability (e.g., library upgrade, flag on/off).
- Call‑stack reachability: Add compositional call‑graph checks per language (Java/JS/Python/Go/C/C++/.NET) and label evidence origins.
- Deterministic scoring: Pin a formula (e.g.,
Score = weight(VEX status) + weight(Reachability) + weight(Exploit/EPSS) + weight(Runtime hit)), emit the formula + inputs in the UI. - Explicit UNKNOWNs: When data is missing, mark
UNKNOWNand run sandboxed probes to shrink unknowns over time; surface these as tasks. - Track Rekor verification latency as a UX health metric (evidence “time‑to‑trust”). (Sigstore)
7) Minimal .NET 10 module checklist (Stella Ops)
- Sbomer: strict CycloneDX/SPDX validation → normalize → hash. (Ecma International)
- Vexer: ingest DSSE/in‑toto VEX; verify signature; map to components. (Legit Security)
- Authority: DSSE signers (keyed + keyless) + Cosign integration. (Sigstore)
- Proof: Rekor submit/verify; store UUID/index/inclusion‑proof. (Sigstore)
- Scanner: reachability plugins per language; emit call‑chain evidence.
- UI: proof‑trail pages; Smart‑Diff; deterministic score panel; UNKNOWN badge.
8) Guardrails & defaults
- Only CycloneDX 1.6 / SPDX 3.0.1 at ingest. Hard fail others. (Ecma International)
- DSSE everywhere (even edges). (in-toto)
- For online mode, default to public Rekor; for air‑gap, queue and verify later against your mirror. (Sigstore)
- Persist inclusion‑proof artifacts so audits don’t require re-fetching. (Sigstore)
9) Tiny starter backlog (ready to copy into SPRINT)
- Ingest Freeze: Add format gate (CDX1.6/SPDX3.0.1 validators). (Ecma International)
- Attest API: DSSE verify endpoint for VEX statements. (Legit Security)
- Signer: Cosign wrapper for DSSE + push to Rekor; store UUID. (Sigstore)
- Proof‑Verifier:
rekor-cli verifyintegration + metrics. (Sigstore) - Graph Store: hash‑addressed nodes/edges; deterministic export.
- Explain UI: proof trail, Smart‑Diff, reachability call‑chains, UNKNOWNs.
If you want, I can turn this into concrete .csproj skeletons, validator stubs, DSSE signing/verify helpers, and a Rekor client wrapper next.
Stella Ops — what you get that “SBOM-only” tools don’t
1) Proof-carrying security decisions
Stella Ops doesn’t just compute a verdict (“CVE present / fixed / not affected”). It produces a verifiable story:
SBOM → VEX → Reachability/runtime evidence → policy decision → signature(s) → transparency-log proof
- Every artifact (SBOM, VEX, scan results, “edge” in the evidence graph) is wrapped as an in-toto attestation and signed (DSSE) (Cosign uses DSSE for payload signing). (Sigstore)
- Signatures/attestations are anchored in Rekor, and you can verify “proof of entry” with
rekor-cli verify. (Sigstore)
Advantage: audits, incident reviews, and partner trust become mechanical verification instead of “trust us”.
2) Noise reduction that’s accountable
VEX is explicitly about exploitability in context (not just “a scanner saw it”). CycloneDX frames VEX as a way to prioritize by real-world exploitability. (CycloneDX) OpenVEX is designed to be SBOM-agnostic and minimal, though it’s still marked as a draft spec. (GitHub)
Advantage: you can suppress false positives with receipts (justifications + signed statements), not tribal knowledge.
3) Version-aware interoperability (without chaos)
- CycloneDX’s current release is 1.7 (2025‑10‑21). (CycloneDX)
- The ECMA standard ECMA‑424 corresponds to CycloneDX v1.6. (Ecma International)
- SPDX has an official 3.0.1 spec. (SPDX)
Advantage: Stella Ops can accept real-world supplier outputs, while still keeping your internal model stable and upgradeable.
4) Deterministic evidence graph = fast “blast radius” answers
Because evidence is stored as a graph of content-addressed nodes/edges (hash IDs), you can answer:
- “Which deployed images include package X@version Y?”
- “Which builds were declared not affected by vendor VEX, and why?”
- “What changed between build A and build B that made CVE reachable?”
Advantage: incident response becomes query + verify, not archaeology.
5) Security improvements beyond vulnerabilities
CycloneDX 1.6 added stronger cryptographic asset discovery/reporting to help manage crypto posture (including agility and policy compliance). (CycloneDX) Advantage: Stella Ops can expand beyond “CVEs” into crypto hygiene, provenance, and operational config integrity.
Developer guidelines (two audiences)
A) Guidelines for app teams producing Stella-ready evidence
1) Pick formats + pin versions (don’t wing it)
SBOMs
- Prefer CycloneDX 1.7 going forward; allow 1.6 when you need strict ECMA‑424 alignment. (CycloneDX)
- Accept SPDX 3.0.1 as the SPDX target. (SPDX)
VEX
- Prefer OpenVEX for a minimal, SBOM-agnostic VEX doc (but treat it as a draft spec and lock to a versioned context like
…/v0.2.0). (GitHub)
Rule of thumb: “Versioned in, versioned out.” Keep the original document bytes, plus a normalized internal form.
2) Use stable identities everywhere
- Subjects: reference immutable artifacts (e.g., container image digest), not tags (
:latest). - Components: use PURLs when possible, and include hashes when available.
- VEX “products”: use the same identifiers your SBOM uses (PURLs are ideal).
3) Sign and attach evidence as attestations
Cosign supports SBOM attestations and in-toto predicates; it supports SBOM formats including SPDX and CycloneDX. (Sigstore) Example: attach an SPDX SBOM as an attestation (Sigstore sample policy shows the exact pattern): (Sigstore)
cosign attest --yes --type https://spdx.dev/Document \
--predicate sbom.spdx.json \
--key cosign.key \
"${IMAGE_DIGEST}"
OpenVEX examples in the ecosystem use a versioned predicate type like https://openvex.dev/ns/v0.2.0. (Docker Documentation)
(Your Stella Ops policy can accept either --type openvex or the explicit URI; the explicit URI is easiest to reason about.)
4) Always log + verify transparency proofs
Rekor’s CLI supports verifying inclusion proofs (proof-of-entry). (Sigstore)
rekor-cli verify --rekor_server https://rekor.sigstore.dev \
--signature artifact.sig \
--public-key cosign.pub \
--artifact artifact.bin
Team rule: releases aren’t “trusted” until signatures + inclusion proofs verify.
5) Write VEX like it will be cross-examined
A good VEX statement includes:
- status (e.g., not_affected / affected / fixed)
- justification (why)
- timestamp and author
- link to supporting evidence (ticket, code change, runtime data)
If you can’t justify a “not_affected”, use “under investigation” and make it expire.
B) Guidelines for Stella Ops contributors (platform developers)
1) Core principle: “Everything is evidence, evidence is immutable”
- Treat every ingest as untrusted input: strict schema validation, size limits, decompression limits, deny SSRF in “external references”, etc.
- Store artifacts as content-addressed blobs:
sha256(bytes)is the primary ID. - Never mutate evidence; publish a new node/edge with its own signature.
2) Canonical internal model + lossless preservation
Store three things per document:
- raw bytes (for audits)
- parsed form (for queries)
- normalized canonical form (for deterministic hashing & diffs)
Why: it lets you evolve internal representation without losing provenance.
3) Evidence graph rules (keep it explainable)
- Nodes:
Artifact,Component,Vulnerability,Attestation,Build,Deployment,RuntimeSignal - Edges:
DESCRIBES,AFFECTS,NOT_AFFECTED_BY,FIXED_IN,DERIVED_FROM,DEPLOYS,OBSERVED_AT_RUNTIME - Sign edges, not just nodes (edge = claim).
UI rule: every “status” shown to users must have a clickable proof trail ending in signatures + inclusion proof.
4) Attestation envelope standardization
Use in-toto statements in DSSE envelopes for everything you sign (SBOM, VEX, scan predicates). Cosign’s attestation flow is built on DSSE. (Sigstore)
Fail closed: if a policy requires an attestation and it’s missing/unverifiable, the decision should not silently pass.
5) Rekor proof lifecycle
Persist per entry:
- Rekor UUID
- log index
- integrated time
- inclusion proof data (when available)
And track health metrics:
- % verified proofs
- proof verification failures
- “proof age” since last verification
6) Versioning strategy (avoid future pain)
-
Maintain an explicit compatibility matrix:
- CycloneDX 1.6 (ECMA‑424) and 1.7 (current). (Ecma International)
- SPDX 3.0.1. (SPDX)
-
Add new versions behind feature flags and “upgrade playbooks”.
-
Include the media type + version in stored metadata (CycloneDX supports a
version=media type parameter). (CycloneDX)
7) “Definition of done” for any new scanner / evidence source
A new plugin isn’t complete unless it:
- outputs a stable, hashable predicate
- links evidence to subjects/components using stable identifiers
- emits reason codes + minimal repro info
- produces a signed attestation and (optionally) Rekor entry
- supports deterministic re-run (same inputs ⇒ same normalized output)
If you want a one-page “Stella Ops Developer Contract” template (API shapes + required fields for SBOM/VEX/attestations + policy expectations), I can draft it in a copy/paste form suitable for a repo docs/ folder.