Files
git.stella-ops.org/docs/product-advisories/26-Nov-2025 - From SBOM to VEX - Building a Transparent Chain.md
master e950474a77
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
up
2025-11-27 15:16:31 +02:00

22 KiB
Raw Blame History

Im sharing this because it closely aligns with your strategy for building strong supplychain and attestation moats — these are emerging standards youll want to embed into your architecture now.

Image

Image

Image

DSSE + intoto: The eventspine

  • The Dead Simple Signing Envelope (DSSE) spec defines a minimal JSON envelope for signing arbitrary data — “transparent transport for signed statements”. (GitHub)
  • The intoto Attestation model builds on DSSE as the envelope, with a statement + predicate about the artifact (e.g., build/cohort metadata). (Legit Security)
  • In your architecture: using DSSEsigned intoto attestations across Scanner → Sbomer → Vexer → Scorer → Attestor gives you a unified “event spine” of provenance and attestations.
  • That means every step emits a signed statement, verifiable, linking tooling. Helps achieve deterministic replayability and auditintegrity.

Image

Image

Image

CycloneDX v1.7: SBOM + cryptography assurance

  • Version 1.7 of CycloneDX was released October 21, 2025 and introduces advanced cryptography, dataprovenance transparency, and IP visibility for the software supply chain. (CycloneDX)
  • It introduces a “Cryptography Registry” to standardize naming / classification of crypto algorithms in BOMs — relevant for PQC readiness, global cryptographic standards like GOST/SM, etc. (CycloneDX)
  • If you emit SBOMs in CycloneDX v1.7 format (and include CBOM/crypto details), youre aligning with modern supplychain trust expectations — satisfying your moat #1 (cryptosovereign readiness) and #2 (deterministic manifests).

Image

Image

Image

Sigstore Rekor v2: Logging the provenance chain

  • Rekor v2 reached GA on October102025; the redesign introduces a “tilebacked transparency log implementation” to simplify ops and reduce costs. (Sigstore Blog)
  • Rekor supports auditing of signing events, monitors to verify appendonly consistency, and log inclusion proofs. (Sigstore)
  • By bundling your provenance/SBOM/VEX/scores and recording those in Rekor v2, youre closing your chain of custody with immutable log entries — supports your “ProofofIntegrity Graph” moat (point #4).

Why this matters for your architecture

  • With each scan or stage (Scanner → Sbomer → Vexer → Scorer → Attestor) producing a DSSEsigned intoto statement, you have a canonical spine of events.
  • Emitting SBOMs in CycloneDX v1.7 ensures you not only list components but crypto metadata, attestation pointers, and versions ready for futureproofing.
  • Recording all artifacts (attestations, SBOM, VEX, scores) into Rekor v2 gives you external public verifiability and auditability — minimal trust surface, maximal transparency.
  • These standards map directly to several of your moats: cryptosovereign readiness, deterministic replayable scans, provenance graphs, trustledger.

If you like, I can pull together mappings of your internal modules (Scanner, Sbomer, Vexer, etc) to these standards and provide a reference implementation skeleton in .NET10 (you indicated youre working with that).

Got it — lets turn your vision into something devs can actually build against.

Below is a concrete implementation plan you can paste into an internal doc / ticketing system and refine into epics & stories.


0. Assumptions & Target EndState

Assumptions

  • Services: Scanner → Sbomer → Vexer → Scorer → Attestor (plus shared infra).

  • Language: .NET (8/10) for your services.

  • You want:

    • DSSEsigned intoto attestations as the event “spine”. (GitHub)
    • CycloneDX 1.7 SBOM + VEX for inventory + exploitability. (CycloneDX)
    • Rekor v2 as the transparency log, with Sigstore bundles for offline verification. (Sigstore Blog)

Target picture

For every artifact A (image / binary / model):

  1. Each stage emits a DSSEsigned intoto attestation:

    • Scanner → scan predicate
    • Sbomer → CycloneDX 1.7 SBOM predicate
    • Vexer → VEX predicate
    • Scorer → score predicate
    • Attestor → final decision predicate
  2. Each attestation is:

    • Signed with your keys or Sigstore keyless.
    • Logged to Rekor (v2) and optionally packaged into a Sigstore bundle.
  3. A consumer can:

    • Fetch all attestations for A, verify signatures + Rekor proofs, read SBOM/VEX, and understand the score.

The rest of this plan is: how to get there stepbystep.


1. Core Data Contracts (Must Be Done First)

1.1 Define the canonical envelope and statement

Standards to follow

  • DSSE Envelope from securesystemslab (envelope.proto). (GitHub)
  • Intoto Attestation “Statement” model (subject + predicateType + predicate). (SLSA)

Deliverable: internal spec

Create a short internal spec (Markdown) for developers:

  • ArtifactIdentity

    • algorithm: sha256 | sha512 | etc.
    • digest: hex string.
    • Optional: name, version, buildPipelineId.
  • InTotoStatement<TPredicate>

    • type: fixed: https://in-toto.io/Statement/v1
    • subject: list of ArtifactIdentity.
    • predicateType: string (URL-ish).
    • predicate: generic JSON (stagespecific payload).
  • DsseEnvelope

    • payloadType: e.g. application/vnd.in-toto+json
    • payload: base64 of the JSON InTotoStatement.
    • signatures[]: { keyid, sig }.

1.2 Implement the .NET representation

Tasks

  1. Generate DSSE envelope types

    • Use envelope.proto from DSSE repo and generate C# types; or reuse the Grafeas Envelope class which is explicitly aligned with DSSE. (Google Cloud)
    • Project: Attestations.Core.
  2. Define generic Statement & Predicate types

    In Attestations.Core:

    public record ArtifactIdentity(string Algorithm, string Digest, string? Name = null, string? Version = null);
    
    public record InTotoStatement<TPredicate>(
        string _Type,
        IReadOnlyList<ArtifactIdentity> Subject,
        string PredicateType,
        TPredicate Predicate
    );
    
    public record DsseSignature(string KeyId, byte[] Sig);
    
    public record DsseEnvelope(
        string PayloadType,
        byte[] Payload,
        IReadOnlyList<DsseSignature> Signatures
    );
    
  3. Define predicate contracts for each stage

    Example:

    public static class PredicateTypes
    {
        public const string ScanV1   = "https://example.com/attestations/scan/v1";
        public const string SbomV1   = "https://example.com/attestations/sbom/cyclonedx-1.7";
        public const string VexV1    = "https://example.com/attestations/vex/cyclonedx";
        public const string ScoreV1  = "https://example.com/attestations/score/v1";
        public const string VerdictV1= "https://example.com/attestations/verdict/v1";
    }
    

    Then define concrete predicates:

    • ScanPredicateV1
    • SbomPredicateV1 (likely mostly a pointer to a CycloneDX doc)
    • VexPredicateV1 (pointer to VEX doc + summary)
    • ScorePredicateV1
    • VerdictPredicateV1 (attest/deny + reasoning)

Definition of done

  • All services share a single Attestations.Core library.
  • There is a test that serializes + deserializes InTotoStatement and DsseEnvelope and matches the JSON format expected by intoto tooling.

2. Signing & Key Management Layer

2.1 Abstraction: decouple from crypto choice

Create an internal package: Attestations.Signing.

public interface IArtifactSigner
{
    Task<DsseEnvelope> SignStatementAsync<TPredicate>(
        InTotoStatement<TPredicate> statement,
        CancellationToken ct = default);
}

public interface IArtifactVerifier
{
    Task VerifyAsync(DsseEnvelope envelope, CancellationToken ct = default);
}

Backends to implement:

  1. KMSbacked signer (e.g., AWS KMS, GCP KMS, Azure Key Vault).

  2. Sigstore keyless / cosign integration:

    • For now you can wrap the cosign CLI, which already understands intoto attestations and Rekor. (Sigstore)
    • Later, replace with a native HTTP client against Sigstore services.

2.2 Key & algorithm strategy

  • Default: ECDSA P256 or Ed25519 keys, stored in KMS.
  • Wrap all usage via IArtifactSigner/IArtifactVerifier.
  • Keep room for PQC migration by never letting services call crypto APIs directly; only use the abstraction.

Definition of done

  • CLI or small test harness that:

    • Creates a dummy InTotoStatement,
    • Signs it via IArtifactSigner,
    • Verifies via IArtifactVerifier,
    • Fails verification if payload is tampered.

3. ServicebyService Integration

For each component well define inputs → behavior → attestation output.

3.1 Scanner

Goal For each artifact, emit a scan attestation with normalized findings.

Tasks

  1. Extend Scanner to normalize findings to a canonical model:

    • Vulnerability id (CVE / GHSA / etc).
    • Affected package (purl, version).
    • Severity, source (NVD, OSV, etc).
  2. Define ScanPredicateV1:

    public record ScanPredicateV1(
        string ScannerName,
        string ScannerVersion,
        DateTimeOffset ScanTime,
        string ScanConfigurationId,
        IReadOnlyList<ScanFinding> Findings
    );
    
  3. After each scan completes:

    • Build ArtifactIdentity from the artifact digest.
    • Build InTotoStatement<ScanPredicateV1> with PredicateTypes.ScanV1.
    • Call IArtifactSigner.SignStatementAsync.
    • Save DsseEnvelope to an Attestation Store (see section 5).
    • Publish an event scan.attestation.created on your message bus with the attestation id.

Definition of done

  • Every scan results in a stored DSSE envelope with ScanV1 predicate.
  • A consumer service can query by artifact digest and get all scan attestations.

3.2 Sbomer (CycloneDX 1.7)

Goal Generate CycloneDX 1.7 SBOMs and attest to them.

CycloneDX provides a .NET library and tools for producing and consuming SBOMs. (GitHub) CycloneDX 1.7 adds cryptography registry, dataprovenance and IP transparency. (CycloneDX)

Tasks

  1. Add CycloneDX .NET library

    • NuGet: CycloneDX.Core (and optional CycloneDX.Utils). (NuGet)
  2. SBOM generation process

    • Input: artifact digest + build metadata (e.g., manifest, lock file).

    • Generate a CycloneDX 1.7 SBOM:

      • Fill metadata.component, bomRef, and dependency graph.
      • Include crypto material using the Cryptography Registry (algorithms, key sizes, modes) when relevant. (CycloneDX)
      • Include data provenance (tool name/version, timestamp).
  3. Storage

    • Store SBOM documents (JSON) in object storage: sboms/{artifactDigest}/cyclonedx-1.7.json.
    • Index them in the Attestation DB (see 5).
  4. SbomPredicateV1

    public record SbomPredicateV1(
        string Format,           // "CycloneDX"
        string Version,          // "1.7"
        Uri   Location,          // URL to the SBOM blob
        string? HashAlgorithm,
        string? HashDigest       // hash of the SBOM document itself
    );
    
  5. After SBOM generation:

    • Create statement with PredicateTypes.SbomV1.
    • Sign via IArtifactSigner.
    • Store DSSE envelope + publish sbom.attestation.created.

Definition of done

  • For any scanned artifact, you can fetch:

    • A CycloneDX 1.7 SBOM, and
    • A DSSEsigned intoto SBOM attestation pointing to it.

3.3 Vexer (CycloneDX VEX / CSAF)

Goal Turn “raw vulnerability findings” into VEX documents that say whether each vulnerability is exploitable, using CycloneDX VEX representation. (CycloneDX)

Tasks

  1. Model VEX status mapping

    • Example statuses: affected, not_affected, fixed, under_investigation.

    • Derive rules from:

      • Reachability analysis, config, feature usage.
      • Business logic (e.g., vulnerability only affects optional module not shipped).
  2. Generate VEX docs

    • Use the same CycloneDX .NET library to emit CycloneDX VEX documents.
    • Store them: vex/{artifactDigest}/cyclonedx-vex.json.
  3. VexPredicateV1

    public record VexPredicateV1(
        string Format,           // "CycloneDX-VEX"
        string Version,
        Uri   Location,
        string? HashAlgorithm,
        string? HashDigest,
        int TotalVulnerabilities,
        int ExploitableVulnerabilities
    );
    
  4. After VEX generation:

    • Build statement with PredicateTypes.VexV1.
    • Sign, store, publish vex.attestation.created.

Definition of done

  • For an artifact with scan results, there is a VEX doc and attestation that:

    • Marks each vulnerability with exploitability status.
    • Can be consumed by Scorer to prioritize risk.

3.4 Scorer

Goal Compute a trust/risk score based on SBOM + VEX + other signals, and attest to it.

Tasks

  1. Scoring model v1

    • Inputs:

      • Count of exploitable vulns by severity.
      • Presence/absence of required attestations (scan, sbom, vex).
      • Age of last scan.
    • Output:

      • RiskScore (0100 or letter grade).
      • RiskTier (“low”, “medium”, “high”).
      • Reasons (top 3 contributors).
  2. ScorePredicateV1

    public record ScorePredicateV1(
        double Score,
        string Tier,
        DateTimeOffset CalculatedAt,
        IReadOnlyList<string> Reasons
    );
    
  3. When triggered (new VEX or SBOM):

    • Recompute score for the artifact.
    • Create attestation, sign, store, publish score.attestation.created.

Definition of done

  • A consumer can call “/artifacts/{digest}/score” and:

    • Verify the DSSE envelope,
    • Read a deterministic ScorePredicateV1.

3.5 Attestor (Final Verdict + Rekor integration)

Goal Emit the final verdict attestation and push evidences to Rekor / Sigstore bundle.

Tasks

  1. VerdictPredicateV1

    public record VerdictPredicateV1(
        string Decision, // "allow" | "deny" | "quarantine"
        string PolicyVersion,
        DateTimeOffset DecidedAt,
        IReadOnlyList<string> Reasons,
        string? RequestedBy,
        string? Environment // "prod", "staging", etc.
    );
    
  2. Policy evaluation:

    • Input: all attestations for artifact (scan, sbom, vex, score).
    • Apply policy (e.g., “no critical exploitable vulns”, “score ≥ 70”).
    • Produce allow / deny.
  3. Rekor integration (v2ready)

    • Rekor provides an HTTP API and CLI for recording signed metadata. (Sigstore)
    • Rekor v2 uses a modern tilebacked log for better cost/ops (you dont need details, just that the API remains similar). (Sigstore Blog)

    Implementation options:

    • Option A: CLI wrapper

      • Use rekor-cli via a sidecar container.
      • Call rekor-cli upload with the DSSE payload or Sigstore bundle.
    • Option B: Native HTTP client

      • Generate client from Rekor OpenAPI in .NET.

      • Implement:

        public interface IRekorClient
        {
            Task<RekorEntryRef> UploadDsseAsync(DsseEnvelope envelope, CancellationToken ct);
        }
        
        public record RekorEntryRef(
            string Uuid,
            long LogIndex,
            byte[] SignedEntryTimestamp);
        
  4. Sigstore bundle support

    • A Sigstore bundle packages:

      • Verification material (cert, Rekor SET, timestamps),
      • Signature content (DSSE envelope). (Sigstore)
    • You can:

      • Store bundles alongside DSSE envelopes: bundles/{artifactDigest}/{stage}.json.
      • Expose them in an API for offline verification.
  5. After producing final verdict:

    • Sign verdict statement.
    • Upload verdict attestation (and optionally previous key attestations) to Rekor.
    • Store Rekor entry ref (uuid, index, SET) in DB.
    • Publish verdict.attestation.created.

Definition of done

  • For a given artifact, you can:

    • Retrieve a verdict DSSE envelope.
    • Verify its signature and Rekor inclusion.
    • Optionally retrieve a Sigstore bundle for fully offline verification.

4. Attestation Store & Data Model

Create an “Attestation Service” that all others depend on for reading/writing.

4.1 Database schema (simplified)

Relational schema example:

  • artifacts

    • id (PK)
    • algorithm
    • digest
    • name
    • version
  • attestations

    • id (PK)
    • artifact_id (FK)
    • stage (scan, sbom, vex, score, verdict)
    • predicate_type
    • dsse_envelope_json
    • created_at
    • signer_key_id
  • rekor_entries

    • id (PK)
    • attestation_id (FK)
    • uuid
    • log_index
    • signed_entry_timestamp (bytea)
  • sboms

    • id
    • artifact_id
    • format (CycloneDX)
    • version (1.7)
    • location
    • hash_algorithm
    • hash_digest
  • vex_documents

    • id
    • artifact_id
    • format
    • version
    • location
    • hash_algorithm
    • hash_digest

4.2 Attestation Service API

Provide a REST/gRPC API:

  • GET /artifacts/{algo}:{digest}/attestations
  • GET /artestations/{id}
  • GET /artifacts/{algo}:{digest}/sbom
  • GET /artifacts/{algo}:{digest}/vex
  • GET /artifacts/{algo}:{digest}/score
  • GET /artifacts/{algo}:{digest}/bundle (optional, Sigstore bundle)

Definition of done

  • All other services call Attestation Service instead of touching the DB directly.
  • You can fetch the full “attestation chain” for a given artifact from one place.

5. Observability & QA

5.1 Metrics

For each service:

  • attestations_emitted_total{stage}
  • attestation_sign_errors_total{stage}
  • rekor_upload_errors_total
  • attestation_verification_failures_total

5.2 Tests

  1. Contract tests

    • JSON produced for InTotoStatement and DsseEnvelope is validated by:

      • intoto reference tooling.
      • DSSE reference implementations. (GitHub)
  2. Endtoend flow

    • Seed a mini pipeline with a test artifact:

      • Build → Scan → SBOM → VEX → Score → Verdict.
    • Use an external verifier (e.g., cosign, intoto attestation verifier) to:

      • Verify DSSE signatures.
      • Verify Rekor entries and/or Sigstore bundles. (Sigstore)
  3. Failure scenarios

    • Corrupt payload (verification must fail).
    • Missing VEX (policy should deny or fall back to stricter rules).
    • Rekor offline (system should continue but mark entries as “not logged”).

6. Phased Rollout Plan (HighLevel)

You can translate this into epics:

  1. Epic 1 Core Attestation Platform

    • Implement Attestations.Core & Attestations.Signing.
    • Implement Attestation Service + DB schema.
    • Build small CLI / test harness.
  2. Epic 2 Scanner Integration

    • Normalize findings.
    • Emit scan attestations only (no SBOM/VEX yet).
  3. Epic 3 CycloneDX SBOMs

    • Integrate CycloneDX .NET library.
    • Generate 1.7 SBOMs for each artifact.
    • Emit SBOM attestations.
  4. Epic 4 VEXer

    • Implement VEX derivation logic + CycloneDX VEX docs.
    • Emit VEX attestations.
  5. Epic 5 Scorer & Policy

    • Implement scoring model v1.
    • Implement policy engine.
    • Emit Score + Verdict attestations.
  6. Epic 6 Rekor & Bundles

    • Stand up Rekor (or integrate with public instance).
    • Implement Rekor client and Sigstore bundle support.
    • Wire Attestor to log final (and optionally intermediate) attestations.
  7. Epic 7 UX & Docs

    • Build UI (or CLI) to visualize:

      • Artifact → SBOM → VEX → Score → Verdict.
    • Document how other teams integrate (what events to listen to, which APIs to call).


If youd like, I can next:

  • Turn this into Jirastyle epics & stories with acceptance criteria; or
  • Draft the actual C# interfaces and a project structure (src/Attestations.Core, src/Attestations.Signing, services, etc.).