Files
git.stella-ops.org/docs/modules/reachability/architecture.md
2026-01-10 20:38:13 +02:00

24 KiB

Reachability Module Architecture

Overview

The Reachability module provides a unified hybrid reachability analysis system that combines static call-graph analysis with runtime execution evidence to determine whether vulnerable code paths are actually exploitable in a given artifact. It serves as the evidence backbone for VEX (Vulnerability Exploitability eXchange) verdicts.

Problem Statement

Vulnerability scanners generate excessive false positives:

  • Static analysis over-approximates: flags code that is dead, feature-gated, or unreachable
  • Runtime analysis under-approximates: misses rarely-executed but exploitable paths
  • No unified view across static and runtime evidence sources
  • Symbol mismatch between static extraction (Roslyn, ASM) and runtime observation (ETW, eBPF)

Before Reachability Module

Question Answer Method Limitation
Is CVE reachable statically? Query ReachGraph No runtime context
Was CVE executed at runtime? Query Signals runtime facts No static context
Should we mark CVE as NA? Manual analysis No evidence, no audit trail
What's the confidence? Guesswork No formal model

After Reachability Module

Single IReachabilityIndex.QueryHybridAsync() call returns:

  • Lattice state (8-level certainty model)
  • Confidence score (0.0-1.0)
  • Evidence URIs (auditable, reproducible)
  • Recommended VEX status + justification

Module Location

src/__Libraries/StellaOps.Reachability.Core/
├── IReachabilityIndex.cs                    # Main facade interface
├── ReachabilityIndex.cs                     # Implementation
├── HybridQueryOptions.cs                    # Query configuration
├── SymbolRef.cs                             # Symbol reference
├── StaticReachabilityResult.cs              # Static query result
├── RuntimeReachabilityResult.cs             # Runtime query result
├── HybridReachabilityResult.cs              # Combined result
├── LatticeState.cs                          # 8-state lattice enum
├── ReachabilityLattice.cs                   # Lattice state machine
├── ConfidenceCalculator.cs                  # Evidence-weighted confidence
├── EvidenceUriBuilder.cs                    # stella:// URI construction
├── IReachGraphAdapter.cs                    # ReachGraph integration interface
├── ISignalsAdapter.cs                       # Signals integration interface
├── ServiceCollectionExtensions.cs           # DI registration
├── Symbols/
│   ├── ISymbolCanonicalizer.cs              # Symbol normalization interface
│   ├── SymbolCanonicalizer.cs               # Implementation
│   ├── ISymbolNormalizer.cs                 # Normalizer interface
│   ├── CanonicalSymbol.cs                   # Canonicalized symbol
│   ├── RawSymbol.cs                         # Raw input symbol
│   ├── SymbolMatchResult.cs                 # Match result
│   ├── SymbolMatchOptions.cs                # Matching configuration
│   ├── SymbolMatcher.cs                     # Symbol matching logic
│   ├── SymbolSource.cs                      # Source enum
│   ├── ProgrammingLanguage.cs               # Language enum
│   ├── DotNetSymbolNormalizer.cs            # .NET symbols
│   ├── JavaSymbolNormalizer.cs              # Java symbols
│   ├── NativeSymbolNormalizer.cs            # C/C++/Rust
│   └── ScriptSymbolNormalizer.cs            # JS/Python/PHP
└── CveMapping/
    ├── ICveSymbolMappingService.cs          # CVE-symbol mapping interface
    ├── CveSymbolMappingService.cs           # Implementation
    ├── CveSymbolMapping.cs                  # Mapping record
    ├── VulnerableSymbol.cs                  # Vulnerable symbol record
    ├── MappingSource.cs                     # Source enum
    ├── VulnerabilityType.cs                 # Vulnerability type enum
    ├── PatchAnalysisResult.cs               # Patch analysis result
    ├── IPatchSymbolExtractor.cs             # Patch analysis interface
    ├── IOsvEnricher.cs                      # OSV enricher interface
    ├── GitDiffExtractor.cs                  # Git diff parsing
    ├── UnifiedDiffParser.cs                 # Unified diff format parser
    ├── FunctionBoundaryDetector.cs          # Function boundary detection
    └── OsvEnricher.cs                       # OSV API enrichment

Core Concepts

1. Reachability Lattice (8-State Model)

The lattice provides mathematically sound evidence aggregation:

                    X (Contested)
                   /             \
                  /               \
         CR (Confirmed           CU (Confirmed
            Reachable)              Unreachable)
              |    \              /    |
              |     \            /     |
         RO (Runtime        RU (Runtime
            Observed)          Unobserved)
              |                    |
              |                    |
         SR (Static           SU (Static
            Reachable)           Unreachable)
               \                  /
                \                /
                 U (Unknown)
State Code Description Confidence Base
Unknown U No analysis performed 0.00
Static Reachable SR Call graph shows path exists 0.30
Static Unreachable SU Call graph proves no path 0.40
Runtime Observed RO Symbol executed at runtime 0.70
Runtime Unobserved RU Observation window passed, no execution 0.60
Confirmed Reachable CR Multiple sources confirm reachability 0.90
Confirmed Unreachable CU Multiple sources confirm no reachability 0.95
Contested X Evidence conflict 0.20 (requires review)

2. Symbol Canonicalization

Symbols from different sources must be normalized to enable matching:

Source Raw Format Canonical Format
Roslyn (.NET) StellaOps.Scanner.Core.SbomGenerator::GenerateAsync stellaops.scanner.core/sbomgenerator/generateasync/(cancellationtoken)
ASM (Java) org/apache/log4j/core/lookup/JndiLookup.lookup(Ljava/lang/String;)Ljava/lang/String; org.apache.log4j.core.lookup/jndilookup/lookup/(string)
eBPF (Native) _ZN4llvm12DenseMapBaseINS_... llvm/densemapbase/operator[]/(keytype)
ETW (.NET) MethodID=12345 ModuleID=67890 (resolved via metadata)

3. CVE-Symbol Mapping

Maps CVE identifiers to specific vulnerable symbols:

{
  "cveId": "CVE-2021-44228",
  "symbols": [
    {
      "canonicalId": "sha256:abc123...",
      "displayName": "org.apache.log4j.core.lookup/jndilookup/lookup/(string)",
      "type": "Sink",
      "condition": "When lookup string contains ${jndi:...}"
    }
  ],
  "source": "PatchAnalysis",
  "confidence": 0.98,
  "patchCommitUrl": "https://github.com/apache/logging-log4j2/commit/abc123"
}

4. Evidence URIs

Standardized stella:// URI scheme for evidence references:

Pattern Example
stella://reachgraph/{digest} stella://reachgraph/blake3:abc123
stella://reachgraph/{digest}/slice?symbol={id} stella://reachgraph/blake3:abc123/slice?symbol=sha256:def
stella://signals/runtime/{tenant}/{artifact} stella://signals/runtime/acme/sha256:abc
stella://cvemap/{cveId} stella://cvemap/CVE-2021-44228
stella://attestation/{digest} stella://attestation/sha256:sig789

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              Reachability Core Library                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ┌────────────────────────────────────────────────────────────────────────────┐ │
│  │                         IReachabilityIndex                                  │ │
│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────────────┐ │ │
│  │  │ QueryStaticAsync │  │ QueryRuntimeAsync│  │ QueryHybridAsync           │ │ │
│  │  └────────┬────────┘  └────────┬────────┘  └────────────┬───────────────┘ │ │
│  └───────────┼────────────────────┼─────────────────────────┼────────────────┘ │
│              │                    │                         │                   │
│              ▼                    ▼                         ▼                   │
│  ┌─────────────────────────────────────────────────────────────────────────────┐│
│  │                        Internal Components                                   ││
│  │                                                                              ││
│  │  ┌────────────────┐   ┌────────────────┐   ┌────────────────────────────┐  ││
│  │  │    Symbol      │   │   CVE-Symbol   │   │   Reachability            │  ││
│  │  │  Canonicalizer │   │    Mapping     │   │      Lattice              │  ││
│  │  │                │   │                │   │                           │  ││
│  │  │ ┌────────────┐ │   │ ┌────────────┐ │   │ ┌───────────────────────┐ │  ││
│  │  │ │.NET Norm.  │ │   │ │PatchExtract│ │   │ │ State Machine        │ │  ││
│  │  │ │Java Norm.  │ │   │ │OSV Enrich  │ │   │ │ Confidence Calc      │ │  ││
│  │  │ │Native Norm.│ │   │ │DeltaSig    │ │   │ │ Transition Rules     │ │  ││
│  │  │ │Script Norm.│ │   │ │Manual Input│ │   │ └───────────────────────┘ │  ││
│  │  │ └────────────┘ │   │ └────────────┘ │   │                           │  ││
│  │  └────────────────┘   └────────────────┘   └────────────────────────────┘  ││
│  │                                                                              ││
│  └──────────────────────────────────────────────────────────────────────────────┘│
│                                      │                                           │
│                                      ▼                                           │
│  ┌──────────────────────────────────────────────────────────────────────────────┐│
│  │                          Evidence Layer                                       ││
│  │                                                                               ││
│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────────────┐  ││
│  │  │ Evidence URI    │  │ Evidence Bundle │  │ Evidence Attestation       │  ││
│  │  │ Builder         │  │ (Collection)    │  │ Service (DSSE)             │  ││
│  │  └─────────────────┘  └─────────────────┘  └─────────────────────────────┘  ││
│  │                                                                               ││
│  └──────────────────────────────────────────────────────────────────────────────┘│
│                                                                                  │
└──────────────────────────────────────────────────────────────────────────────────┘
                                       │
              ┌────────────────────────┼────────────────────────┐
              │                        │                        │
              ▼                        ▼                        ▼
     ┌────────────────┐      ┌────────────────┐      ┌────────────────┐
     │   ReachGraph   │      │    Signals     │      │  Policy Engine │
     │   Adapter      │      │    Adapter     │      │    Adapter     │
     └───────┬────────┘      └───────┬────────┘      └───────┬────────┘
             │                       │                       │
             ▼                       ▼                       ▼
     ┌────────────────┐      ┌────────────────┐      ┌────────────────┐
     │   ReachGraph   │      │    Signals     │      │  Policy Engine │
     │   WebService   │      │   WebService   │      │   (VEX Emit)   │
     └────────────────┘      └────────────────┘      └────────────────┘

Data Flow

Query Flow

1. Consumer calls IReachabilityIndex.QueryHybridAsync(symbol, artifact, options)
          │
          ▼
2. SymbolCanonicalizer normalizes input symbol to CanonicalSymbol
          │
          ▼
3. Parallel queries:
   ├── ReachGraphAdapter.QueryAsync() → StaticReachabilityResult
   └── SignalsAdapter.QueryRuntimeFactsAsync() → RuntimeReachabilityResult
          │
          ▼
4. ReachabilityLattice computes combined state from evidence
          │
          ▼
5. ConfidenceCalculator applies evidence weights and guardrails
          │
          ▼
6. EvidenceBundle collects URIs for audit trail
          │
          ▼
7. Return HybridReachabilityResult with verdict recommendation

Ingestion Flow (CVE Mapping)

1. Patch commit detected (Concelier, Feedser, or manual)
          │
          ▼
2. GitDiffExtractor parses diff to find changed functions
          │
          ▼
3. SymbolCanonicalizer normalizes extracted symbols
          │
          ▼
4. OsvEnricher adds context from OSV database
          │
          ▼
5. CveSymbolMappingService persists mapping with provenance
          │
          ▼
6. Mapping available for reachability queries

API Contracts

IReachabilityIndex

public interface IReachabilityIndex
{
    /// <summary>
    /// Query static reachability from call graph.
    /// </summary>
    Task<StaticReachabilityResult> QueryStaticAsync(
        SymbolRef symbol,
        string artifactDigest,
        CancellationToken ct);

    /// <summary>
    /// Query runtime reachability from observed facts.
    /// </summary>
    Task<RuntimeReachabilityResult> QueryRuntimeAsync(
        SymbolRef symbol,
        string artifactDigest,
        TimeSpan observationWindow,
        CancellationToken ct);

    /// <summary>
    /// Query hybrid reachability combining static + runtime.
    /// </summary>
    Task<HybridReachabilityResult> QueryHybridAsync(
        SymbolRef symbol,
        string artifactDigest,
        HybridQueryOptions options,
        CancellationToken ct);

    /// <summary>
    /// Batch query for CVE vulnerability analysis.
    /// </summary>
    Task<IReadOnlyList<HybridReachabilityResult>> QueryBatchAsync(
        IEnumerable<SymbolRef> symbols,
        string artifactDigest,
        HybridQueryOptions options,
        CancellationToken ct);

    /// <summary>
    /// Get vulnerable symbols for a CVE.
    /// </summary>
    Task<CveSymbolMapping?> GetCveMappingAsync(
        string cveId,
        CancellationToken ct);
}

Result Types

public sealed record HybridReachabilityResult
{
    public required SymbolRef Symbol { get; init; }
    public required string ArtifactDigest { get; init; }
    public required LatticeState LatticeState { get; init; }
    public required double Confidence { get; init; }
    public required StaticEvidence? StaticEvidence { get; init; }
    public required RuntimeEvidence? RuntimeEvidence { get; init; }
    public required VerdictRecommendation Verdict { get; init; }
    public required ImmutableArray<string> EvidenceUris { get; init; }
    public required DateTimeOffset ComputedAt { get; init; }
    public required string ComputedBy { get; init; }
}

public sealed record VerdictRecommendation
{
    public required VexStatus Status { get; init; }
    public VexJustification? Justification { get; init; }
    public required ConfidenceBucket ConfidenceBucket { get; init; }
    public string? ImpactStatement { get; init; }
    public string? ActionStatement { get; init; }
}

public enum LatticeState
{
    Unknown = 0,
    StaticReachable = 1,
    StaticUnreachable = 2,
    RuntimeObserved = 3,
    RuntimeUnobserved = 4,
    ConfirmedReachable = 5,
    ConfirmedUnreachable = 6,
    Contested = 7
}

Integration Points

Upstream (Data Sources)

Module Interface Data
ReachGraph IReachGraphSliceService Static call-graph nodes/edges
Signals IRuntimeFactsService Runtime method observations
Scanner.CallGraph ICallGraphExtractor Per-artifact call graphs
Feedser IBackportProofService Patch analysis results

Downstream (Consumers)

Module Interface Usage
Policy Engine IReachabilityAwareVexEmitter VEX verdict with evidence
VexLens IReachabilityIndex Consensus enrichment
Web Console REST API Evidence panel display
CLI stella reachability Command-line queries
ExportCenter IReachabilityExporter Offline bundles

Storage

PostgreSQL Schema

-- CVE-Symbol Mappings
CREATE TABLE reachability.cve_symbol_mappings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    cve_id TEXT NOT NULL,
    symbol_canonical_id TEXT NOT NULL,
    symbol_display_name TEXT NOT NULL,
    vulnerability_type TEXT NOT NULL,
    condition TEXT,
    source TEXT NOT NULL,
    confidence DECIMAL(3,2) NOT NULL,
    patch_commit_url TEXT,
    delta_sig_digest TEXT,
    extracted_at TIMESTAMPTZ NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (tenant_id, cve_id, symbol_canonical_id)
);

-- Query Cache
CREATE TABLE reachability.query_cache (
    cache_key TEXT PRIMARY KEY,
    artifact_digest TEXT NOT NULL,
    symbol_canonical_id TEXT NOT NULL,
    lattice_state INTEGER NOT NULL,
    confidence DECIMAL(3,2) NOT NULL,
    result_json JSONB NOT NULL,
    computed_at TIMESTAMPTZ NOT NULL,
    expires_at TIMESTAMPTZ NOT NULL
);

-- Audit Log
CREATE TABLE reachability.query_audit_log (
    id BIGSERIAL PRIMARY KEY,
    tenant_id UUID NOT NULL,
    query_type TEXT NOT NULL,
    artifact_digest TEXT NOT NULL,
    symbol_count INTEGER NOT NULL,
    lattice_state INTEGER NOT NULL,
    confidence DECIMAL(3,2) NOT NULL,
    duration_ms INTEGER NOT NULL,
    queried_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Valkey (Redis) Caching

Key Pattern TTL Purpose
reach:static:{artifact}:{symbol} 1h Static query cache
reach:runtime:{artifact}:{symbol} 5m Runtime query cache
reach:hybrid:{artifact}:{symbol}:{options_hash} 15m Hybrid query cache
cvemap:{cve_id} 24h CVE mapping cache

Determinism Guarantees

Reproducibility Rules

  1. Canonical Symbol IDs: SHA-256 of purl|namespace|type|method|signature (lowercase, sorted)
  2. Stable Lattice Transitions: Deterministic state machine, no randomness
  3. Ordered Evidence: Evidence URIs sorted lexicographically
  4. Time Injection: All ComputedAt via TimeProvider
  5. Culture Invariance: InvariantCulture for all string operations

Replay Verification

public interface IReachabilityReplayService
{
    Task<ReplayResult> ReplayAsync(
        HybridReachabilityInputs inputs,
        HybridReachabilityResult expected,
        CancellationToken ct);
}

Performance Characteristics

Operation Target P95 Notes
Static query (cached) <10ms Valkey hit
Static query (uncached) <100ms ReachGraph slice
Runtime query (cached) <5ms Valkey hit
Runtime query (uncached) <50ms Signals lookup
Hybrid query <50ms Parallel static + runtime
Batch query (100 symbols) <500ms Parallelized
CVE mapping lookup <10ms Cached
Symbol canonicalization <1ms In-memory

Security Considerations

Access Control

Operation Required Scope
Query reachability reachability:read
Ingest CVE mapping reachability:write
Admin CVE mapping reachability:admin
Export bundles reachability:export

Tenant Isolation

  • All queries filtered by tenant_id
  • RLS policies on all tables
  • Cache keys include tenant prefix

Data Sensitivity

  • Symbol names may reveal internal architecture
  • Runtime traces expose execution patterns
  • CVE mappings are security-sensitive

Observability

Metrics

Metric Type Labels
reachability_query_duration_seconds histogram query_type, cache_hit
reachability_lattice_state_total counter state
reachability_cache_hit_ratio gauge cache_type
reachability_cvemap_count gauge source

Traces

Span Description
reachability.query.static Static graph query
reachability.query.runtime Runtime facts query
reachability.query.hybrid Combined computation
reachability.canonicalize Symbol normalization
reachability.lattice.compute State calculation


Last updated: 10-Jan-2026