Files
git.stella-ops.org/docs/modules/airgap/evidence-reconciliation.md
master 2170a58734
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
Add comprehensive security tests for OWASP A02, A05, A07, and A08 categories
- Implemented tests for Cryptographic Failures (A02) to ensure proper handling of sensitive data, secure algorithms, and key management.
- Added tests for Security Misconfiguration (A05) to validate production configurations, security headers, CORS settings, and feature management.
- Developed tests for Authentication Failures (A07) to enforce strong password policies, rate limiting, session management, and MFA support.
- Created tests for Software and Data Integrity Failures (A08) to verify artifact signatures, SBOM integrity, attestation chains, and feed updates.
2025-12-16 16:40:44 +02:00

7.1 KiB

Evidence Reconciliation

This document describes the evidence reconciliation algorithm implemented in the StellaOps.AirGap.Importer module. The algorithm provides deterministic, lattice-based reconciliation of security evidence from air-gapped bundles.

Overview

Evidence reconciliation is a 5-step pipeline that transforms raw evidence artifacts (SBOMs, attestations, VEX documents) into a unified, content-addressed evidence graph suitable for policy evaluation and audit trails.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                   Evidence Reconciliation Pipeline              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Step 1: Artifact Indexing                                      │
│  ├── EvidenceDirectoryDiscovery                                 │
│  ├── ArtifactIndex (digest-keyed)                               │
│  └── Digest normalization (sha256:...)                          │
│                                                                 │
│  Step 2: Evidence Collection                                    │
│  ├── SbomCollector (CycloneDX, SPDX)                            │
│  ├── AttestationCollector (DSSE)                                │
│  └── Integration with DsseVerifier                              │
│                                                                 │
│  Step 3: Normalization                                          │
│  ├── JsonNormalizer (stable sorting)                            │
│  ├── Timestamp stripping                                        │
│  └── URI lowercase normalization                                │
│                                                                 │
│  Step 4: Lattice Rules                                          │
│  ├── SourcePrecedenceLattice                                    │
│  ├── VEX merge with precedence                                  │
│  └── Conflict resolution                                        │
│                                                                 │
│  Step 5: Graph Emission                                         │
│  ├── EvidenceGraph construction                                 │
│  ├── Deterministic serialization                                │
│  └── SHA-256 manifest generation                                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Components

Step 1: Artifact Indexing

ArtifactIndex - A digest-keyed index of all artifacts in the evidence bundle.

// Key types
public readonly record struct DigestKey(string Algorithm, string Value);

// Normalization
DigestKey.Parse("sha256:abc123...")  DigestKey("sha256", "abc123...")

EvidenceDirectoryDiscovery - Discovers evidence files from a directory structure.

Expected structure:

evidence/
├── sboms/
│   ├── component-a.cdx.json
│   └── component-b.spdx.json
├── attestations/
│   └── artifact.dsse.json
└── vex/
    └── vendor-vex.json

Step 2: Evidence Collection

Parsers:

  • CycloneDxParser - Parses CycloneDX 1.4/1.5/1.6 format
  • SpdxParser - Parses SPDX 2.3 format
  • DsseAttestationParser - Parses DSSE envelopes

Collectors:

  • SbomCollector - Orchestrates SBOM parsing and indexing
  • AttestationCollector - Orchestrates attestation parsing and verification

Step 3: Normalization

SbomNormalizer applies format-specific normalization:

Rule Description
Stable JSON sorting Keys sorted alphabetically (ordinal)
Timestamp stripping Removes created, modified, timestamp fields
URI normalization Lowercases scheme, host, normalizes paths
Whitespace normalization Consistent formatting

Step 4: Lattice Rules

SourcePrecedenceLattice implements a bounded lattice for VEX source authority:

    Vendor (top)
       ↑
   Maintainer
       ↑
   ThirdParty
       ↑
    Unknown (bottom)

Lattice Properties (verified by property-based tests):

  • Commutativity: Join(a, b) = Join(b, a)
  • Associativity: Join(Join(a, b), c) = Join(a, Join(b, c))
  • Idempotence: Join(a, a) = a
  • Absorption: Join(a, Meet(a, b)) = a

Conflict Resolution Order:

  1. Higher precedence source wins
  2. More recent timestamp wins (when same precedence)
  3. Status priority: NotAffected > Fixed > UnderInvestigation > Affected > Unknown

Step 5: Graph Emission

EvidenceGraph - A content-addressed graph of reconciled evidence:

public sealed record EvidenceGraph
{
    public required string Version { get; init; }
    public required string DigestAlgorithm { get; init; }
    public required string RootDigest { get; init; }
    public required IReadOnlyList<EvidenceNode> Nodes { get; init; }
    public required IReadOnlyList<EvidenceEdge> Edges { get; init; }
    public required DateTimeOffset GeneratedAt { get; init; }
}

Determinism guarantees:

  • Nodes sorted by digest (ordinal)
  • Edges sorted by (source, target, type)
  • SHA-256 manifest includes content hash
  • Reproducible across runs with same inputs

Integration

CLI Usage

# Verify offline evidence bundle
stellaops verify offline \
  --evidence-dir /evidence \
  --artifact sha256:def456... \
  --policy verify-policy.yaml

API

// Reconcile evidence
var reconciler = new EvidenceReconciler(options);
var graph = await reconciler.ReconcileAsync(evidenceDir, cancellationToken);

// Verify determinism
var hash1 = graph.ComputeHash();
var graph2 = await reconciler.ReconcileAsync(evidenceDir, cancellationToken);
var hash2 = graph2.ComputeHash();
Debug.Assert(hash1 == hash2); // Always true

Testing

Golden-File Tests

Test fixtures in tests/AirGap/StellaOps.AirGap.Importer.Tests/Reconciliation/Fixtures/:

  • cyclonedx-sample.json - CycloneDX 1.5 sample
  • spdx-sample.json - SPDX 2.3 sample
  • dsse-attestation-sample.json - DSSE envelope sample

Property-Based Tests

SourcePrecedenceLatticePropertyTests verifies:

  • Lattice algebraic properties (commutativity, associativity, idempotence, absorption)
  • Ordering properties (antisymmetry, transitivity, reflexivity)
  • Bound properties (join is LUB, meet is GLB)
  • Merge determinism