save progress
This commit is contained in:
@@ -23,6 +23,16 @@ Use this index to locate platform-level architecture references and per-module d
|
||||
- [Data flows](data-flows.md) - SBOM, advisory, VEX, and policy data lifecycles
|
||||
- [Schema mapping](schema-mapping.md) - PostgreSQL, Valkey, and RustFS storage reference
|
||||
|
||||
## Policy engine deep dives (NEW)
|
||||
Comprehensive documentation of how data feeds policy decisions:
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - Master view of all data flowing to policy engine
|
||||
- [SBOM Analyzer Inventory](sbom-analyzer-inventory.md) - Complete inventory of 25 analyzers (11 language, 9 OS, 4 surface, 1 capability)
|
||||
- [Runtime Agents Architecture](runtime-agents-architecture.md) - eBPF observation, Zastava container observer, signal processing
|
||||
- [Call Graph Analysis](call-graph-analysis.md) - ReachGraph construction, BFS path finding, 8-state reachability
|
||||
- [Confidence Scoring](confidence-scoring.md) - 5-factor weighted scoring (RCH, RTS, VEX, PRV, POL)
|
||||
- [K4 Lattice Logic](k4-lattice-logic.md) - Four-valued logic for handling uncertainty and conflicts
|
||||
|
||||
## End-to-end workflow flows
|
||||
Comprehensive flow documentation for all major StellaOps workflows: [flows/](../../flows/)
|
||||
|
||||
|
||||
602
docs/technical/architecture/call-graph-analysis.md
Normal file
602
docs/technical/architecture/call-graph-analysis.md
Normal file
@@ -0,0 +1,602 @@
|
||||
# Call Graph Analysis Pipeline
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the ReachGraph module's call graph construction, analysis, and reachability determination. The call graph connects static analysis (from SBOM/binaries) with dynamic observation (from runtime) to produce high-confidence reachability verdicts.
|
||||
|
||||
---
|
||||
|
||||
## Call Graph Construction
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ CALL GRAPH CONSTRUCTION PIPELINE │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ INPUT SOURCES │
|
||||
│ │
|
||||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
|
||||
│ │ SBOM │ │ Binaries │ │ Source Code │ │ Runtime │ │
|
||||
│ │ (packages) │ │ (ELF/PE) │ │ (if avail) │ │ (hot syms) │ │
|
||||
│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
|
||||
│ │ Package Deps │ │ Symbol Tables │ │ Import/Call │ │ Observed │ │
|
||||
│ │ (DEPENDS_ON) │ │ (exports, │ │ Extraction │ │ Invocations │ │
|
||||
│ │ │ │ imports) │ │ │ │ │ │
|
||||
│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────────────┴──────────────────┴──────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ GRAPH INDEXER │ │
|
||||
│ │ (Node + Edge │ │
|
||||
│ │ Construction) │ │
|
||||
│ └────────────┬────────────┘ │
|
||||
│ │ │
|
||||
└──────────────────────────────────────┼──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ GRAPH DATA MODEL │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ NODE TYPES │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ PackageNode │ │ FunctionNode │ │ FileNode │ │ │
|
||||
│ │ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ │ │
|
||||
│ │ │ purl: string │ │ name: string │ │ path: string │ │ │
|
||||
│ │ │ version: string │ │ signature: str │ │ hash: string │ │ │
|
||||
│ │ │ ecosystem: str │ │ address: u64 │ │ language: str │ │ │
|
||||
│ │ │ license: str │ │ package: ref │ │ loc: (start,end)│ │ │
|
||||
│ │ └─────────────────┘ │ file: ref │ │ package: ref │ │ │
|
||||
│ │ │ visibility: enum│ └─────────────────┘ │ │
|
||||
│ │ │ is_entry: bool │ │ │
|
||||
│ │ └─────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ EntryPointNode │ │ CVENode │ │ │
|
||||
│ │ ├─────────────────┤ ├─────────────────┤ │ │
|
||||
│ │ │ type: HTTP|CLI │ │ id: string │ │ │
|
||||
│ │ │ |EVENT|... │ │ severity: enum │ │ │
|
||||
│ │ │ function: ref │ │ cvss: f32 │ │ │
|
||||
│ │ │ route: string │ │ affected: [ref] │ │ │
|
||||
│ │ │ method: string │ │ fixed: string │ │ │
|
||||
│ │ └─────────────────┘ └─────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EDGE TYPES │ │
|
||||
│ │ │ │
|
||||
│ │ ┌───────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Edge Type │ Source │ Target │ Properties │ │ │
|
||||
│ │ ├─────────────────┼─────────────────┼─────────────────┼─────────────┤ │ │
|
||||
│ │ │ DEPENDS_ON │ Package │ Package │ scope, dev │ │ │
|
||||
│ │ │ CONTAINS │ Package │ File │ │ │ │
|
||||
│ │ │ DEFINES │ File │ Function │ line_start │ │ │
|
||||
│ │ │ CALLS │ Function │ Function │ call_sites │ │ │
|
||||
│ │ │ IMPORTS │ Package │ Package │ symbols[] │ │ │
|
||||
│ │ │ ENTRY_FOR │ EntryPoint │ Function │ route │ │ │
|
||||
│ │ │ AFFECTS │ CVE │ Package/Func │ version_rng │ │ │
|
||||
│ │ │ OBSERVED │ Function │ Function │ count, ts │ │ │
|
||||
│ │ └───────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Graph Construction by Source
|
||||
|
||||
### Package Dependency Graph
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ PACKAGE DEPENDENCY GRAPH CONSTRUCTION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input: SBOM (CycloneDX or SPDX) │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SBOM PARSING │ │
|
||||
│ │ │ │
|
||||
│ │ CycloneDX: SPDX: │ │
|
||||
│ │ ───────────── ─────── │ │
|
||||
│ │ { { │ │
|
||||
│ │ "components": [ "packages": [ │ │
|
||||
│ │ { { │ │
|
||||
│ │ "purl": "pkg:npm/express@4.18", "SPDXID": "SPDXRef-...", │ │
|
||||
│ │ "type": "library" "name": "express", │ │
|
||||
│ │ } "versionInfo": "4.18" │ │
|
||||
│ │ ], } │ │
|
||||
│ │ "dependencies": [ ], │ │
|
||||
│ │ { "relationships": [ │ │
|
||||
│ │ "ref": "pkg:npm/express@4.18", { │ │
|
||||
│ │ "dependsOn": [ "relationshipType": │ │
|
||||
│ │ "pkg:npm/body-parser@1.20" "DEPENDS_ON", │ │
|
||||
│ │ ] "spdxElementId": "...", │ │
|
||||
│ │ } "relatedSpdxElement": "..."│ │
|
||||
│ │ ] } │ │
|
||||
│ │ } ] │ │
|
||||
│ │ } │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ GRAPH CONSTRUCTION │ │
|
||||
│ │ │ │
|
||||
│ │ For each component/package: │ │
|
||||
│ │ 1. Create PackageNode with PURL as ID │ │
|
||||
│ │ 2. Parse version constraints │ │
|
||||
│ │ 3. Identify ecosystem (npm, maven, pypi, etc.) │ │
|
||||
│ │ │ │
|
||||
│ │ For each dependency relationship: │ │
|
||||
│ │ 1. Create DEPENDS_ON edge │ │
|
||||
│ │ 2. Mark scope (compile, runtime, dev, optional) │ │
|
||||
│ │ 3. Track transitive vs direct │ │
|
||||
│ │ │ │
|
||||
│ │ Result: │ │
|
||||
│ │ │ │
|
||||
│ │ [myapp@1.0] ─DEPENDS_ON─► [express@4.18] ─DEPENDS_ON─► [body-parser@1.20] │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ └──DEPENDS_ON─► [accepts@1.3] │ │
|
||||
│ │ │ │ │
|
||||
│ │ └──DEPENDS_ON─► [lodash@4.17] │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Binary Symbol Graph
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ BINARY SYMBOL GRAPH CONSTRUCTION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Input: ELF/PE/Mach-O binaries from container image │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SYMBOL EXTRACTION │ │
|
||||
│ │ │ │
|
||||
│ │ ELF Binary: │ │
|
||||
│ │ ──────────── │ │
|
||||
│ │ │ │
|
||||
│ │ .dynsym section: .symtab section (if not stripped): │ │
|
||||
│ │ ┌─────────────────────────┐ ┌─────────────────────────┐ │ │
|
||||
│ │ │ Symbol │ Type │ Bind│ │ Symbol │ Type │ Bind│ │ │
|
||||
│ │ ├──────────┼───────┼─────┤ ├──────────┼───────┼─────┤ │ │
|
||||
│ │ │ malloc │ FUNC │ GLOB│ │ main │ FUNC │ GLOB│ │ │
|
||||
│ │ │ printf │ FUNC │ GLOB│ │ helper │ FUNC │ LOCAL│ │ │
|
||||
│ │ │ __libc.. │ FUNC │ WEAK│ │ ... │ │ │ │ │
|
||||
│ │ └─────────────────────────┘ └─────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ .plt / .got sections: DWARF debug info (if available): │ │
|
||||
│ │ ┌─────────────────────────┐ ┌─────────────────────────┐ │ │
|
||||
│ │ │ External call targets │ │ DW_TAG_subprogram │ │ │
|
||||
│ │ │ (imported functions) │ │ name: "processData" │ │ │
|
||||
│ │ │ malloc@GLIBC_2.2.5 │ │ decl_file: "main.c" │ │ │
|
||||
│ │ │ SSL_read@OPENSSL_1_1 │ │ decl_line: 42 │ │ │
|
||||
│ │ └─────────────────────────┘ │ low_pc: 0x1234 │ │ │
|
||||
│ │ └─────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CALL EDGE EXTRACTION │ │
|
||||
│ │ │ │
|
||||
│ │ For each function in binary: │ │
|
||||
│ │ 1. Disassemble function body │ │
|
||||
│ │ 2. Identify CALL/JMP instructions │ │
|
||||
│ │ 3. Resolve call targets: │ │
|
||||
│ │ - Direct calls: target address → symbol lookup │ │
|
||||
│ │ - Indirect calls: [reg] or [mem] → mark as dynamic │ │
|
||||
│ │ - PLT calls: resolve to external library symbol │ │
|
||||
│ │ │ │
|
||||
│ │ Example disassembly: │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ processData: │ │ │
|
||||
│ │ │ 0x1234: push rbp │ │ │
|
||||
│ │ │ 0x1235: mov rbp, rsp │ │ │
|
||||
│ │ │ ... │ │ │
|
||||
│ │ │ 0x1250: call 0x4567 ; → resolves to validate() │ │ │
|
||||
│ │ │ 0x1255: call 0x89ab@plt ; → resolves to SSL_read (extern) │ │ │
|
||||
│ │ │ 0x125a: call [rax] ; → indirect call (unknown target) │ │ │
|
||||
│ │ │ ... │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Produces edges: │ │
|
||||
│ │ [processData] ─CALLS─► [validate] (static, direct) │ │
|
||||
│ │ [processData] ─CALLS─► [SSL_read] (static, external) │ │
|
||||
│ │ [processData] ─CALLS─► [?] (dynamic, unresolved) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Source Code Analysis
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SOURCE CODE CALL GRAPH EXTRACTION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ When source code is available (e.g., interpreted languages), extract calls │
|
||||
│ using language-specific parsers: │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ LANGUAGE-SPECIFIC EXTRACTION │ │
|
||||
│ │ │ │
|
||||
│ │ JavaScript/TypeScript: │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ // source.js │ │ │
|
||||
│ │ │ const lodash = require('lodash'); │ │ │
|
||||
│ │ │ const result = lodash.template(input); // ← call site │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Produces: │ │ │
|
||||
│ │ │ [source.js:render] ─CALLS─► [lodash:template] │ │ │
|
||||
│ │ │ [source.js] ─IMPORTS─► [lodash] │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Python: │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ # app.py │ │ │
|
||||
│ │ │ import pickle │ │ │
|
||||
│ │ │ data = pickle.loads(user_input) # ← dangerous call │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Produces: │ │ │
|
||||
│ │ │ [app.py:process] ─CALLS─► [pickle:loads] │ │ │
|
||||
│ │ │ [app.py] ─IMPORTS─► [pickle] │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Java: │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ // Service.java │ │ │
|
||||
│ │ │ import org.apache.logging.log4j.Logger; │ │ │
|
||||
│ │ │ logger.info("User: " + userInput); // ← CVE-2021-44228 │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Produces: │ │ │
|
||||
│ │ │ [Service:handle] ─CALLS─► [Logger:info] │ │ │
|
||||
│ │ │ [Service] ─IMPORTS─► [org.apache.logging.log4j] │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Graph Analytics Engine
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ GRAPH ANALYTICS ENGINE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ LABEL PROPAGATION CLUSTERING │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Group related packages/functions for impact analysis │ │
|
||||
│ │ │ │
|
||||
│ │ Algorithm: │ │
|
||||
│ │ 1. Initialize: each node gets unique label │ │
|
||||
│ │ 2. Iterate: each node adopts most common neighbor label │ │
|
||||
│ │ 3. Converge: when labels stabilize │ │
|
||||
│ │ │ │
|
||||
│ │ Result: Clusters of tightly connected packages/functions │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Cluster A (HTTP handling): Cluster B (Data processing): │ │ │
|
||||
│ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │
|
||||
│ │ │ │ express │ │ lodash │ │ │ │
|
||||
│ │ │ │ body-parser │ │ underscore │ │ │ │
|
||||
│ │ │ │ cookie-parser │ │ ramda │ │ │ │
|
||||
│ │ │ └─────────────────────┘ └─────────────────────┘ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Use case: "If CVE affects lodash, which other packages are │ │ │
|
||||
│ │ │ in the same processing cluster and might be impacted?" │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ BETWEENNESS CENTRALITY │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Identify critical nodes (bottlenecks, high-impact) │ │
|
||||
│ │ │ │
|
||||
│ │ Formula: C_B(v) = Σ (σ_st(v) / σ_st) │ │
|
||||
│ │ Where: │ │
|
||||
│ │ σ_st = number of shortest paths from s to t │ │
|
||||
│ │ σ_st(v) = number of those paths passing through v │ │
|
||||
│ │ │ │
|
||||
│ │ High centrality nodes: │ │
|
||||
│ │ • Commonly used utility functions (lodash.get, axios.request) │ │
|
||||
│ │ • Core framework methods (express.Router) │ │
|
||||
│ │ • Logging/serialization functions │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ [EntryPoint] ──► [auth.validate] ──► [user.fetch] ──► [db.query] │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ ▼ ▼ ▼ │ │ │
|
||||
│ │ │ └────────► [logging.info] ◄─────────┴───────────────┘ │ │ │
|
||||
│ │ │ ▲ │ │ │
|
||||
│ │ │ HIGH CENTRALITY │ │ │
|
||||
│ │ │ (many paths pass through) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reachability Analysis
|
||||
|
||||
### BFS Path Finding
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ REACHABILITY SLICE SERVICE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ BFS TRAVERSAL ALGORITHM │ │
|
||||
│ │ │ │
|
||||
│ │ Query: "Find all paths from entry points to vulnerable function" │ │
|
||||
│ │ │ │
|
||||
│ │ function findReachablePaths(graph, target_func, max_depth=10): │ │
|
||||
│ │ paths = [] │ │
|
||||
│ │ queue = [(entry, [entry]) for entry in graph.entry_points] │ │
|
||||
│ │ visited = set() │ │
|
||||
│ │ │ │
|
||||
│ │ while queue: │ │
|
||||
│ │ node, path = queue.pop(0) │ │
|
||||
│ │ if len(path) > max_depth: │ │
|
||||
│ │ continue │ │
|
||||
│ │ │ │
|
||||
│ │ if node == target_func: │ │
|
||||
│ │ paths.append(path) │ │
|
||||
│ │ continue │ │
|
||||
│ │ │ │
|
||||
│ │ if node in visited: │ │
|
||||
│ │ continue │ │
|
||||
│ │ visited.add(node) │ │
|
||||
│ │ │ │
|
||||
│ │ for edge in graph.outgoing_edges(node, type=CALLS): │ │
|
||||
│ │ queue.append((edge.target, path + [edge.target])) │ │
|
||||
│ │ │ │
|
||||
│ │ return paths │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SLICE TYPES │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ CVE Slice │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Input: CVE-2021-23337 (lodash template injection) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Steps: │ │ │
|
||||
│ │ │ 1. Find affected function: lodash.template │ │ │
|
||||
│ │ │ 2. BFS from all entry points │ │ │
|
||||
│ │ │ 3. Collect all paths reaching lodash.template │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Output: │ │ │
|
||||
│ │ │ [ │ │ │
|
||||
│ │ │ { path: [main.handler → render.compile → lodash.template], │ │ │
|
||||
│ │ │ depth: 2, entry_type: HTTP }, │ │ │
|
||||
│ │ │ { path: [cli.process → template.render → lodash.template], │ │ │
|
||||
│ │ │ depth: 2, entry_type: CLI } │ │ │
|
||||
│ │ │ ] │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Package Slice │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Input: pkg:npm/lodash@4.17.20 │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Steps: │ │ │
|
||||
│ │ │ 1. Find all functions in package │ │ │
|
||||
│ │ │ 2. BFS from all entry points to any package function │ │ │
|
||||
│ │ │ 3. Group by function │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Output: │ │ │
|
||||
│ │ │ { │ │ │
|
||||
│ │ │ "lodash.get": { reachable: true, paths: [...] }, │ │ │
|
||||
│ │ │ "lodash.set": { reachable: true, paths: [...] }, │ │ │
|
||||
│ │ │ "lodash.template": { reachable: true, paths: [...] }, │ │ │
|
||||
│ │ │ "lodash.chunk": { reachable: false } │ │ │
|
||||
│ │ │ } │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Entry Point Slice (Forward) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Input: HTTP /api/v1/render endpoint │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Steps: │ │ │
|
||||
│ │ │ 1. Start from entry point function │ │ │
|
||||
│ │ │ 2. BFS forward through all CALLS edges │ │ │
|
||||
│ │ │ 3. Mark all reachable functions │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Output: Set of all functions reachable from this endpoint │ │ │
|
||||
│ │ │ (Used for "attack surface" analysis) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Eight-State Reachability Lattice
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ 8-STATE REACHABILITY LATTICE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STATE HIERARCHY │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────┐ │ │
|
||||
│ │ │ LiveExploitPath │ HIGHEST │ │
|
||||
│ │ │ (Confirmed exploitable │ CONFIDENCE │ │
|
||||
│ │ │ with runtime proof) │ │ │
|
||||
│ │ └────────────┬────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌────────────▼────────────┐ │ │
|
||||
│ │ │ DynamicReachable │ │ │
|
||||
│ │ │ (Observed at runtime │ │ │
|
||||
│ │ │ via eBPF/hot symbols) │ │ │
|
||||
│ │ └────────────┬────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌────────────▼────────────┐ │ │
|
||||
│ │ │ StaticReachable │ │ │
|
||||
│ │ │ (Call path found via │ │ │
|
||||
│ │ │ static analysis) │ │ │
|
||||
│ │ └────────────┬────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌────────────▼────────────┐ │ │
|
||||
│ │ │ PotentiallyReachable │ │ │
|
||||
│ │ │ (Import exists but no │ │ │
|
||||
│ │ │ direct call found) │ │ │
|
||||
│ │ └────────────┬────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌────────────▼────────────┐ │ │
|
||||
│ │ │ Unknown │ DEFAULT │ │
|
||||
│ │ │ (Insufficient data │ STATE │ │
|
||||
│ │ │ to determine) │ │ │
|
||||
│ │ └────────────┬────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌───────────────────────┼───────────────────────┐ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ ┌──────▼──────┐ ┌────────▼────────┐ ┌───────▼───────┐ │ │
|
||||
│ │ │ NotReachable│ │ GateBlocked │ │ NotApplicable │ │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ Static │ │ Dead code path │ │ Language/OS │ │ │
|
||||
│ │ │ analysis │ │ (ifdef, feature │ │ mismatch │ │ │
|
||||
│ │ │ proves no │ │ flag disabled) │ │ │ │ │
|
||||
│ │ │ path exists │ │ │ │ │ │ │
|
||||
│ │ └─────────────┘ └─────────────────┘ └───────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STATE DETERMINATION LOGIC │ │
|
||||
│ │ │ │
|
||||
│ │ function determineReachabilityState( │ │
|
||||
│ │ static_paths: Path[], │ │
|
||||
│ │ runtime_observations: Observation[], │ │
|
||||
│ │ exploit_proofs: Proof[], │ │
|
||||
│ │ platform_match: bool, │ │
|
||||
│ │ gate_status: GateStatus │ │
|
||||
│ │ ) -> ReachabilityState: │ │
|
||||
│ │ │ │
|
||||
│ │ if not platform_match: │ │
|
||||
│ │ return NotApplicable │ │
|
||||
│ │ │ │
|
||||
│ │ if gate_status == BLOCKED: │ │
|
||||
│ │ return GateBlocked │ │
|
||||
│ │ │ │
|
||||
│ │ if exploit_proofs: │ │
|
||||
│ │ return LiveExploitPath │ │
|
||||
│ │ │ │
|
||||
│ │ if runtime_observations: │ │
|
||||
│ │ return DynamicReachable │ │
|
||||
│ │ │ │
|
||||
│ │ if static_paths: │ │
|
||||
│ │ return StaticReachable │ │
|
||||
│ │ │ │
|
||||
│ │ if import_exists: │ │
|
||||
│ │ return PotentiallyReachable │ │
|
||||
│ │ │ │
|
||||
│ │ if no_path_proven: │ │
|
||||
│ │ return NotReachable │ │
|
||||
│ │ │ │
|
||||
│ │ return Unknown │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Graph Snapshot and Determinism
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ GRAPH SNAPSHOT DETERMINISM │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ GraphSnapshotBuilder │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Create deterministic, hashable graph snapshots for: │ │
|
||||
│ │ • Audit trails (prove analysis was consistent) │ │
|
||||
│ │ • Caching (skip re-analysis if inputs unchanged) │ │
|
||||
│ │ • DSSE attestation (sign analysis results) │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Determinism Rules: │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ 1. Node ordering: sorted by (type, purl/name, version) │ │ │
|
||||
│ │ │ 2. Edge ordering: sorted by (type, source_id, target_id) │ │ │
|
||||
│ │ │ 3. Property ordering: sorted alphabetically │ │ │
|
||||
│ │ │ 4. Timestamps: ISO-8601 UTC (no local timezone) │ │ │
|
||||
│ │ │ 5. Floating point: fixed precision (6 decimal places) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Snapshot Structure: │ │
|
||||
│ │ │ │
|
||||
│ │ { │ │
|
||||
│ │ "version": "1.0", │ │
|
||||
│ │ "created_at": "2024-12-29T10:30:00Z", │ │
|
||||
│ │ "image_digest": "sha256:abc...", │ │
|
||||
│ │ "nodes": [ ... ], // sorted │ │
|
||||
│ │ "edges": [ ... ], // sorted │ │
|
||||
│ │ "reachability": { ... }, // computed states │ │
|
||||
│ │ "hash": "sha256:snapshot_hash..." │ │
|
||||
│ │ } │ │
|
||||
│ │ │ │
|
||||
│ │ Hash computation: │ │
|
||||
│ │ hash = SHA256( │ │
|
||||
│ │ canonical_json(nodes) || │ │
|
||||
│ │ canonical_json(edges) || │ │
|
||||
│ │ canonical_json(reachability) │ │
|
||||
│ │ ) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - How reachability feeds policy
|
||||
- [Runtime Agents Architecture](runtime-agents-architecture.md) - Runtime observation
|
||||
- [Binary Analysis](../../modules/binary-index/architecture.md) - Binary symbol extraction
|
||||
- [ReachGraph Module](../../modules/reachgraph/architecture.md) - ReachGraph dossier
|
||||
- [Policy Evaluation Flow](../../flows/04-policy-evaluation-flow.md) - K4 lattice usage
|
||||
512
docs/technical/architecture/confidence-scoring.md
Normal file
512
docs/technical/architecture/confidence-scoring.md
Normal file
@@ -0,0 +1,512 @@
|
||||
# Confidence Scoring System
|
||||
|
||||
## Overview
|
||||
|
||||
The StellaOps confidence scoring system quantifies the reliability of vulnerability assessments by weighing multiple evidence sources. This enables policy decisions that account for uncertainty and evidence quality.
|
||||
|
||||
---
|
||||
|
||||
## Scoring Formula
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ CONFIDENCE SCORING FORMULA │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ │ FinalScore = Σ (Weight_i × NormalizedScore_i) × 100 │ │
|
||||
│ │ i │ │
|
||||
│ │ │ │
|
||||
│ │ Where: │ │
|
||||
│ │ i ∈ {Reachability, Runtime, VEX, Provenance, Policy} │ │
|
||||
│ │ Σ Weight_i = 1.0 │ │
|
||||
│ │ NormalizedScore_i ∈ [0.0, 1.0] │ │
|
||||
│ │ FinalScore ∈ [0, 100] │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ DEFAULT WEIGHT CONFIGURATION │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ████████████████████████████████ Reachability (RCH): 0.30 │ │ │
|
||||
│ │ │ ██████████████████████████ Runtime (RTS): 0.25 │ │ │
|
||||
│ │ │ ████████████████████ VEX: 0.20 │ │ │
|
||||
│ │ │ ██████████████ Provenance (PRV): 0.15 │ │ │
|
||||
│ │ │ ██████████ Policy (POL): 0.10 │ │ │
|
||||
│ │ │ ──────────────────────────────────────────────────────────── │ │ │
|
||||
│ │ │ = 1.00 │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Factor Details
|
||||
|
||||
### 1. Reachability Factor (RCH) - Weight: 0.30
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ REACHABILITY FACTOR (RCH) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Purpose: Measure confidence that vulnerable code is reachable from entry points │
|
||||
│ Source: ReachGraph call graph analysis + 8-state reachability lattice │
|
||||
│ Weight: 0.30 (highest - most impactful for exploitability) │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SCORE MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ Reachability State │ Score │ Rationale │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ LiveExploitPath │ 1.00 │ Confirmed exploitable path exists │ │
|
||||
│ │ │ │ with runtime proof │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ DynamicReachable │ 0.90 │ Observed at runtime via eBPF │ │
|
||||
│ │ │ │ Strong evidence of usage │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ StaticReachable │ 0.70 │ Static analysis found call path │ │
|
||||
│ │ │ │ May not execute in practice │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ PotentiallyReachable │ 0.50 │ Import exists but no direct call │ │
|
||||
│ │ │ │ Could be reached via reflection/eval │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ Unknown │ 0.30 │ Insufficient data to determine │ │
|
||||
│ │ │ │ Conservative middle ground │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ GateBlocked │ 0.15 │ Dead code behind feature flag │ │
|
||||
│ │ │ │ Low but not zero risk │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ NotReachable │ 0.10 │ Static analysis proves no path │ │
|
||||
│ │ │ │ Still small residual risk │ │
|
||||
│ │ ────────────────────────────┼───────┼──────────────────────────────────────│ │
|
||||
│ │ NotApplicable │ 0.00 │ Platform/language mismatch │ │
|
||||
│ │ │ │ Cannot affect this system │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXAMPLE │ │
|
||||
│ │ │ │
|
||||
│ │ Finding: CVE-2021-23337 in lodash@4.17.20 │ │
|
||||
│ │ Reachability State: StaticReachable │ │
|
||||
│ │ RCH Score: 0.70 │ │
|
||||
│ │ │ │
|
||||
│ │ Contribution to final: 0.70 × 0.30 = 0.210 (21 points) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. Runtime Factor (RTS) - Weight: 0.25
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ RUNTIME FACTOR (RTS) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Purpose: Incorporate runtime observation evidence from eBPF/Signals │
|
||||
│ Source: Hot Symbol Index (signals.hot_symbols table) │
|
||||
│ Weight: 0.25 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SCORE MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ Runtime Observation │ Score │ Rationale │ │
|
||||
│ │ ────────────────────────────────┼───────┼──────────────────────────────────│ │
|
||||
│ │ High frequency observation │ 1.00 │ Function called frequently │ │
|
||||
│ │ (invocation_count > 1000/day) │ │ Definitely in use │ │
|
||||
│ │ ────────────────────────────────┼───────┼──────────────────────────────────│ │
|
||||
│ │ Moderate observation │ 0.80 │ Function called at least once │ │
|
||||
│ │ (invocation_count > 0) │ │ Confirmed in active code path │ │
|
||||
│ │ ────────────────────────────────┼───────┼──────────────────────────────────│ │
|
||||
│ │ No observation (short window) │ 0.50 │ Not seen yet, but observation │ │
|
||||
│ │ (< 7 days of monitoring) │ │ window is short │ │
|
||||
│ │ ────────────────────────────────┼───────┼──────────────────────────────────│ │
|
||||
│ │ No observation (long window) │ 0.20 │ 30+ days of monitoring with │ │
|
||||
│ │ (> 30 days, no calls) │ │ no observation - likely unused │ │
|
||||
│ │ ────────────────────────────────┼───────┼──────────────────────────────────│ │
|
||||
│ │ No runtime posture │ 0.50 │ eBPF agent not deployed │ │
|
||||
│ │ (observation not available) │ │ Cannot contribute evidence │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ OBSERVATION WINDOW DECAY │ │
|
||||
│ │ │ │
|
||||
│ │ Score decreases over time if function is not observed: │ │
|
||||
│ │ │ │
|
||||
│ │ Days without observation │ Score │ │
|
||||
│ │ ─────────────────────────┼────── │ │
|
||||
│ │ 0-7 │ 0.50 (neutral - too early to tell) │ │
|
||||
│ │ 8-14 │ 0.40 │ │
|
||||
│ │ 15-21 │ 0.35 │ │
|
||||
│ │ 22-30 │ 0.30 │ │
|
||||
│ │ 31+ │ 0.20 (strong evidence of non-use) │ │
|
||||
│ │ │ │
|
||||
│ │ Formula: score = 0.50 - (days / 100) clamped to [0.20, 0.50] │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXAMPLE │ │
|
||||
│ │ │ │
|
||||
│ │ Finding: CVE-2021-23337 in lodash@4.17.20 │ │
|
||||
│ │ Runtime: Not observed (14 days of monitoring) │ │
|
||||
│ │ RTS Score: 0.40 │ │
|
||||
│ │ │ │
|
||||
│ │ Contribution to final: 0.40 × 0.25 = 0.100 (10 points) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. VEX Factor - Weight: 0.20
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ VEX FACTOR │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Purpose: Incorporate vendor VEX statements about exploitability │
|
||||
│ Source: VexLens consensus engine (aggregates multiple VEX issuers) │
|
||||
│ Weight: 0.20 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ VEX STATUS SCORING │ │
|
||||
│ │ │ │
|
||||
│ │ VEX Status │ Base │ Trust │ Final │ Rationale │ │
|
||||
│ │ │ Score │ Mult. │ Score │ │ │
|
||||
│ │ ───────────────────────┼───────┼────────┼───────┼──────────────────────────│ │
|
||||
│ │ affected (exploitable) │ 1.00 │ ×trust │ varies│ Vendor confirms vuln │ │
|
||||
│ │ │ │ │ │ applies to this product │ │
|
||||
│ │ ───────────────────────┼───────┼────────┼───────┼──────────────────────────│ │
|
||||
│ │ under_investigation │ 0.70 │ ×1.0 │ 0.70 │ Vendor is analyzing │ │
|
||||
│ │ │ │ │ │ inconclusive │ │
|
||||
│ │ ───────────────────────┼───────┼────────┼───────┼──────────────────────────│ │
|
||||
│ │ no VEX available │ 0.50 │ ×1.0 │ 0.50 │ No statement - neutral │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ ───────────────────────┼───────┼────────┼───────┼──────────────────────────│ │
|
||||
│ │ not_affected │ 0.20 │ ×trust │ varies│ Vendor says not vuln │ │
|
||||
│ │ │ │ │ │ (mitigated, not present) │ │
|
||||
│ │ ───────────────────────┼───────┼────────┼───────┼──────────────────────────│ │
|
||||
│ │ fixed │ 0.10 │ ×trust │ varies│ Vendor confirms fixed │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ISSUER TRUST LEVELS │ │
|
||||
│ │ │ │
|
||||
│ │ Trust is based on issuer reputation and verification: │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Trust Level │ Multiplier │ Issuers │ │ │
|
||||
│ │ │ ────────────┼────────────┼────────────────────────────────────────│ │ │
|
||||
│ │ │ Very High │ 1.0 │ Verified vendor (e.g., RedHat, Ubuntu)│ │ │
|
||||
│ │ │ High │ 0.9 │ Trusted third-party (e.g., Snyk, NIST)│ │ │
|
||||
│ │ │ Medium │ 0.7 │ Community maintainer │ │ │
|
||||
│ │ │ Low │ 0.5 │ Unknown/unverified source │ │ │
|
||||
│ │ │ Contested │ 0.3 │ Multiple conflicting VEX statements │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CONSENSUS CALCULATION │ │
|
||||
│ │ │ │
|
||||
│ │ When multiple VEX statements exist: │ │
|
||||
│ │ │ │
|
||||
│ │ consensus_score = Σ(vex_score_i × trust_i) / Σ(trust_i) │ │
|
||||
│ │ │ │
|
||||
│ │ Example: │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Issuer │ Status │ Base │ Trust │ Weighted │ │ │
|
||||
│ │ │ ─────────────┼───────────────┼──────┼───────┼────────────────────│ │ │
|
||||
│ │ │ RedHat │ not_affected │ 0.20 │ 1.0 │ 0.20 × 1.0 = 0.20 │ │ │
|
||||
│ │ │ Ubuntu │ not_affected │ 0.20 │ 1.0 │ 0.20 × 1.0 = 0.20 │ │ │
|
||||
│ │ │ Community │ affected │ 1.00 │ 0.7 │ 1.00 × 0.7 = 0.70 │ │ │
|
||||
│ │ │ ─────────────┼───────────────┼──────┼───────┼────────────────────│ │ │
|
||||
│ │ │ Weighted sum │ │ │ 2.7 │ 1.10 │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Consensus = 1.10 / 2.7 = 0.407 (weighted toward vendor statements) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4. Provenance Factor (PRV) - Weight: 0.15
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ PROVENANCE FACTOR (PRV) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Purpose: Account for supply chain trust and build provenance │
|
||||
│ Source: SLSA attestations, DSSE signatures, Rekor transparency log │
|
||||
│ Weight: 0.15 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SCORE MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ Provenance Level │ Score │ Rationale │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ Unknown source │ 1.00 │ No attestation - highest risk │ │
|
||||
│ │ (no attestation) │ │ Cannot verify integrity │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ Signed but unverified │ 0.80 │ Signature present but no │ │
|
||||
│ │ (signature, no SLSA) │ │ SLSA attestation │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ SLSA L1 │ 0.60 │ Documented build process │ │
|
||||
│ │ (documented build) │ │ │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ SLSA L2 │ 0.40 │ Signed provenance from │ │
|
||||
│ │ (signed provenance) │ │ hosted build service │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ SLSA L3 │ 0.30 │ Hardened builds + signed │ │
|
||||
│ │ (hardened builds) │ │ provenance │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ SLSA L4 / Reproducible │ 0.10 │ Fully reproducible build │ │
|
||||
│ │ (reproducible build) │ │ verified by multiple parties │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ INTERPRETATION │ │
|
||||
│ │ │ │
|
||||
│ │ Note: Lower provenance score = LOWER confidence in exploitability │ │
|
||||
│ │ │ │
|
||||
│ │ This seems counterintuitive, but the logic is: │ │
|
||||
│ │ - Unknown provenance means we can't trust the package at all │ │
|
||||
│ │ - Untrusted packages should be treated as MORE suspicious │ │
|
||||
│ │ - Better provenance = more confidence the package is what it claims │ │
|
||||
│ │ │ │
|
||||
│ │ So: High provenance score → higher confidence the finding is accurate │ │
|
||||
│ │ Low provenance score → less trust in the package itself │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5. Policy Factor (POL) - Weight: 0.10
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ POLICY FACTOR (POL) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Purpose: Incorporate organizational policy exceptions and overrides │
|
||||
│ Source: Exception store (approved waivers, risk acceptances) │
|
||||
│ Weight: 0.10 (lowest - modifies but doesn't override evidence) │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SCORE MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ Exception Status │ Score │ Rationale │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ No exception │ 1.00 │ Standard policy applies │ │
|
||||
│ │ │ │ Full risk consideration │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ Time-bounded exception │ 0.50 │ Approved temporary waiver │ │
|
||||
│ │ (expires in < 30 days) │ │ Reduced urgency │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ Long-term exception │ 0.30 │ Approved extended waiver │ │
|
||||
│ │ (expires in 30-90 days) │ │ Risk accepted by org │ │
|
||||
│ │ ────────────────────────────────┼───────┼───────────────────────────────────│ │
|
||||
│ │ Permanent waiver │ 0.10 │ Accepted risk - will not fix │ │
|
||||
│ │ (no expiration) │ │ (e.g., false positive, legacy) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXCEPTION METADATA │ │
|
||||
│ │ │ │
|
||||
│ │ Exceptions are tracked with: │ │
|
||||
│ │ • Approver (who authorized) │ │
|
||||
│ │ • Justification (why accepted) │ │
|
||||
│ │ • Expiration (when to re-evaluate) │ │
|
||||
│ │ • Scope (specific CVE, package, or image) │ │
|
||||
│ │ • Compensating controls (mitigations in place) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Complete Calculation Example
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ COMPLETE CALCULATION EXAMPLE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Finding: CVE-2021-23337 (lodash template injection) │
|
||||
│ Package: pkg:npm/lodash@4.17.20 │
|
||||
│ Image: docker.io/myorg/app:v1.2.3 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EVIDENCE COLLECTION │ │
|
||||
│ │ │ │
|
||||
│ │ 1. REACHABILITY │ │
|
||||
│ │ State: StaticReachable │ │
|
||||
│ │ Evidence: BFS found path [main.handler → render.compile → lodash.template] │
|
||||
│ │ Score: 0.70 │ │
|
||||
│ │ │ │
|
||||
│ │ 2. RUNTIME │ │
|
||||
│ │ Observation: Not observed │ │
|
||||
│ │ Monitoring window: 14 days │ │
|
||||
│ │ Score: 0.40 │ │
|
||||
│ │ │ │
|
||||
│ │ 3. VEX │ │
|
||||
│ │ Statements: None available │ │
|
||||
│ │ Score: 0.50 (neutral) │ │
|
||||
│ │ │ │
|
||||
│ │ 4. PROVENANCE │ │
|
||||
│ │ Level: SLSA L2 (signed provenance) │ │
|
||||
│ │ Score: 0.40 │ │
|
||||
│ │ │ │
|
||||
│ │ 5. POLICY │ │
|
||||
│ │ Exception: None │ │
|
||||
│ │ Score: 1.00 │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ WEIGHTED CALCULATION │ │
|
||||
│ │ │ │
|
||||
│ │ ┌───────────────┬────────┬────────┬──────────────────────────────────┐ │ │
|
||||
│ │ │ Factor │ Score │ Weight │ Weighted Score │ │ │
|
||||
│ │ ├───────────────┼────────┼────────┼──────────────────────────────────┤ │ │
|
||||
│ │ │ Reachability │ 0.70 │ 0.30 │ 0.70 × 0.30 = 0.210 │ │ │
|
||||
│ │ │ Runtime │ 0.40 │ 0.25 │ 0.40 × 0.25 = 0.100 │ │ │
|
||||
│ │ │ VEX │ 0.50 │ 0.20 │ 0.50 × 0.20 = 0.100 │ │ │
|
||||
│ │ │ Provenance │ 0.40 │ 0.15 │ 0.40 × 0.15 = 0.060 │ │ │
|
||||
│ │ │ Policy │ 1.00 │ 0.10 │ 1.00 × 0.10 = 0.100 │ │ │
|
||||
│ │ ├───────────────┼────────┼────────┼──────────────────────────────────┤ │ │
|
||||
│ │ │ TOTAL │ │ 1.00 │ 0.570 │ │ │
|
||||
│ │ └───────────────┴────────┴────────┴──────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Final Confidence Score = 0.570 × 100 = 57 │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ VISUALIZATION │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ ███████████████████████████████████████████████░░░░░░░░░░░░░░░░░ │ │ │
|
||||
│ │ │ |---------------- 57% confidence ------------------| │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Component breakdown: │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ RCH ████████████████████▓ 21% (StaticReachable) │ │ │
|
||||
│ │ │ RTS ██████████░░░░░░░░░░ 10% (Not observed) │ │ │
|
||||
│ │ │ VEX ██████████░░░░░░░░░░ 10% (No VEX) │ │ │
|
||||
│ │ │ PRV ██████░░░░░░░░░░░░░░ 6% (SLSA L2) │ │ │
|
||||
│ │ │ POL ██████████░░░░░░░░░░ 10% (No exception) │ │ │
|
||||
│ │ │ ──────────────────────────────────────────────── │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Interpretation: │ │
|
||||
│ │ • Medium-high confidence this vulnerability is exploitable │ │
|
||||
│ │ • Static reachability is main contributor │ │
|
||||
│ │ • Would benefit from runtime observation to confirm/deny │ │
|
||||
│ │ • No VEX statements to modify assessment │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
# Policy engine confidence configuration
|
||||
confidence:
|
||||
weights:
|
||||
reachability: 0.30
|
||||
runtime: 0.25
|
||||
vex: 0.20
|
||||
provenance: 0.15
|
||||
policy: 0.10
|
||||
|
||||
# Reachability state mappings
|
||||
reachability_scores:
|
||||
LiveExploitPath: 1.00
|
||||
DynamicReachable: 0.90
|
||||
StaticReachable: 0.70
|
||||
PotentiallyReachable: 0.50
|
||||
Unknown: 0.30
|
||||
GateBlocked: 0.15
|
||||
NotReachable: 0.10
|
||||
NotApplicable: 0.00
|
||||
|
||||
# Runtime observation decay
|
||||
runtime:
|
||||
base_observed_score: 0.80
|
||||
high_frequency_threshold: 1000 # calls/day
|
||||
decay_rate: 0.01 # per day without observation
|
||||
min_score: 0.20
|
||||
neutral_score: 0.50 # when no runtime data
|
||||
|
||||
# VEX status mappings
|
||||
vex_scores:
|
||||
affected: 1.00
|
||||
under_investigation: 0.70
|
||||
not_affected: 0.20
|
||||
fixed: 0.10
|
||||
no_vex: 0.50
|
||||
|
||||
# Trust levels for VEX issuers
|
||||
issuer_trust:
|
||||
verified_vendor: 1.0
|
||||
trusted_third_party: 0.9
|
||||
community: 0.7
|
||||
unknown: 0.5
|
||||
contested: 0.3
|
||||
|
||||
# SLSA provenance levels
|
||||
provenance_scores:
|
||||
unknown: 1.00
|
||||
signed_only: 0.80
|
||||
slsa_l1: 0.60
|
||||
slsa_l2: 0.40
|
||||
slsa_l3: 0.30
|
||||
slsa_l4: 0.10
|
||||
|
||||
# Policy exception mappings
|
||||
exception_scores:
|
||||
none: 1.00
|
||||
temporary_30d: 0.50
|
||||
temporary_90d: 0.30
|
||||
permanent: 0.10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - Complete data flow
|
||||
- [K4 Lattice Logic](k4-lattice-logic.md) - Four-valued logic for policy decisions
|
||||
- [Policy Evaluation Flow](../../flows/04-policy-evaluation-flow.md) - End-to-end flow
|
||||
- [Reachability Drift Alert Flow](../../flows/19-reachability-drift-alert-flow.md) - Runtime updates
|
||||
570
docs/technical/architecture/k4-lattice-logic.md
Normal file
570
docs/technical/architecture/k4-lattice-logic.md
Normal file
@@ -0,0 +1,570 @@
|
||||
# K4 Belnap Four-Valued Logic
|
||||
|
||||
## Overview
|
||||
|
||||
StellaOps uses K4 Belnap four-valued logic to handle uncertainty and conflicting evidence in policy decisions. This enables the system to represent "both true and false" (conflict) and "neither true nor false" (unknown) states that naturally arise when aggregating evidence from multiple sources.
|
||||
|
||||
---
|
||||
|
||||
## Why Four Values?
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ THE PROBLEM WITH BINARY LOGIC │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ In classical two-valued logic (True/False): │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Scenario: Is this vulnerability reachable? │ │
|
||||
│ │ │ │
|
||||
│ │ Evidence sources: │ │
|
||||
│ │ • Static analysis: "Yes, I found a path" → True │ │
|
||||
│ │ • Runtime observation: "No activity seen" → ??? (not False) │ │
|
||||
│ │ • VEX statement: "Not affected in our configuration" → False │ │
|
||||
│ │ │ │
|
||||
│ │ Problem: How do we combine True + False? │ │
|
||||
│ │ • AND(True, False) = False (lose the static evidence) │ │
|
||||
│ │ • OR(True, False) = True (lose the VEX evidence) │ │
|
||||
│ │ │ │
|
||||
│ │ Neither preserves the fact that we have CONFLICTING evidence! │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Another scenario: No evidence available │ │
|
||||
│ │ │ │
|
||||
│ │ • No static analysis run → ??? │ │
|
||||
│ │ • No runtime observation → ??? │ │
|
||||
│ │ • No VEX statement → ??? │ │
|
||||
│ │ │ │
|
||||
│ │ Problem: This isn't "False" - we just don't know yet! │ │
|
||||
│ │ Classical logic forces us to pick True or False when we have no information.│ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## The Four Values
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ K4 BELNAP TRUTH VALUES │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ THE BILATTICE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌───────────┐ │ │
|
||||
│ │ │ ⊤ │ BOTH (Conflict) │ │
|
||||
│ │ │ "Both" │ Evidence says BOTH true AND false │ │
|
||||
│ │ │ │ (conflicting sources) │ │
|
||||
│ │ └─────┬─────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ╱─────┴─────╲ │ │
|
||||
│ │ ╱ ╲ │ │
|
||||
│ │ ╱ ╲ │ │
|
||||
│ │ ┌───────┴───────┐ ┌───────┴───────┐ │ │
|
||||
│ │ │ T │ │ F │ │ │
|
||||
│ │ │ "True" │ │ "False" │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ Evidence │ │ Evidence │ │ │
|
||||
│ │ │ supports │ │ supports │ │ │
|
||||
│ │ │ "yes" │ │ "no" │ │ │
|
||||
│ │ └───────┬───────┘ └───────┬───────┘ │ │
|
||||
│ │ ╲ ╱ │ │
|
||||
│ │ ╲ ╱ │ │
|
||||
│ │ ╲─────┬─────╱ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌─────┴─────┐ │ │
|
||||
│ │ │ ⊥ │ NEITHER (Unknown) │ │
|
||||
│ │ │ "Neither" │ No evidence either way │ │
|
||||
│ │ │ │ (insufficient data) │ │
|
||||
│ │ └───────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ │ Two orderings (dimensions): │ │
|
||||
│ │ │ │
|
||||
│ │ TRUTH ordering (vertical): INFORMATION ordering (horizontal): │ │
|
||||
│ │ F < ⊥ < T < ⊤ (for meet) ⊥ < T, ⊥ < F, T < ⊤, F < ⊤ (for join) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Value Semantics
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ VALUE SEMANTICS │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ Value │ Symbol │ Meaning │ Example in StellaOps │ │
|
||||
│ │ ──────┼────────┼──────────────────────────────┼────────────────────────────│ │
|
||||
│ │ True │ T │ Evidence supports "yes" │ Static analysis found │ │
|
||||
│ │ │ │ │ reachable path │ │
|
||||
│ │ ──────┼────────┼──────────────────────────────┼────────────────────────────│ │
|
||||
│ │ False │ F │ Evidence supports "no" │ VEX says "not affected" │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ ──────┼────────┼──────────────────────────────┼────────────────────────────│ │
|
||||
│ │ Both │ ⊤ │ Evidence supports BOTH │ Static says reachable, │ │
|
||||
│ │ │ │ "yes" AND "no" │ VEX says not affected │ │
|
||||
│ │ │ │ (contradiction/conflict) │ │ │
|
||||
│ │ ──────┼────────┼──────────────────────────────┼────────────────────────────│ │
|
||||
│ │ Neither│ ⊥ │ No evidence either way │ No analysis run yet, │ │
|
||||
│ │ │ │ (unknown/insufficient data) │ no VEX available │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ INFORMATION CONTENT │ │
|
||||
│ │ │ │
|
||||
│ │ ⊥ (Neither): 0 bits - we know nothing │ │
|
||||
│ │ T (True): 1 bit - we know "yes" │ │
|
||||
│ │ F (False): 1 bit - we know "no" │ │
|
||||
│ │ ⊤ (Both): 2 bits - we know "yes" AND "no" (conflicting sources) │ │
|
||||
│ │ │ │
|
||||
│ │ The JOIN operation adds information (moves up in the lattice) │ │
|
||||
│ │ The MEET operation requires agreement (moves down in the lattice) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lattice Operations
|
||||
|
||||
### JOIN (∨) - Combining Evidence
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ JOIN OPERATION (∨) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ JOIN combines evidence from multiple sources. │
|
||||
│ It prefers "more information" - moves UP the information ordering. │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ JOIN TRUTH TABLE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │ │
|
||||
│ │ │ ∨ │ ⊥ │ T │ F │ ⊤ │ │ │
|
||||
│ │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ │
|
||||
│ │ │ ⊥ │ ⊥ │ T │ F │ ⊤ │ │ │
|
||||
│ │ │ T │ T │ T │ ⊤ │ ⊤ │ │ │
|
||||
│ │ │ F │ F │ ⊤ │ F │ ⊤ │ │ │
|
||||
│ │ │ ⊤ │ ⊤ │ ⊤ │ ⊤ │ ⊤ │ │ │
|
||||
│ │ └─────────┴─────────┴─────────┴─────────┴─────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Key insight: T ∨ F = ⊤ (both) │ │
|
||||
│ │ When evidence conflicts, we get "Both" - we don't lose either source! │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXAMPLES │ │
|
||||
│ │ │ │
|
||||
│ │ Example 1: Adding static analysis to unknown │ │
|
||||
│ │ ───────────────────────────────────────── │ │
|
||||
│ │ Before: ⊥ (no information) │ │
|
||||
│ │ Static analysis: T (found reachable path) │ │
|
||||
│ │ Result: ⊥ ∨ T = T │ │
|
||||
│ │ │ │
|
||||
│ │ Example 2: Static says yes, VEX says no │ │
|
||||
│ │ ──────────────────────────────────────── │ │
|
||||
│ │ Static analysis: T │ │
|
||||
│ │ VEX statement: F (not affected) │ │
|
||||
│ │ Result: T ∨ F = ⊤ (conflict!) │ │
|
||||
│ │ │ │
|
||||
│ │ Example 3: Multiple sources agree │ │
|
||||
│ │ ────────────────────────────────── │ │
|
||||
│ │ Static analysis: T │ │
|
||||
│ │ Runtime observation: T │ │
|
||||
│ │ Result: T ∨ T = T │ │
|
||||
│ │ │ │
|
||||
│ │ Example 4: Adding information to conflict │ │
|
||||
│ │ ────────────────────────────────────────── │ │
|
||||
│ │ Current: ⊤ (conflicting evidence) │ │
|
||||
│ │ New source: T (yes, reachable) │ │
|
||||
│ │ Result: ⊤ ∨ T = ⊤ (still conflicting) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### MEET (∧) - Requiring Agreement
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ MEET OPERATION (∧) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ MEET requires agreement between sources. │
|
||||
│ It prefers "less information" - moves DOWN the information ordering. │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ MEET TRUTH TABLE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │ │
|
||||
│ │ │ ∧ │ ⊥ │ T │ F │ ⊤ │ │ │
|
||||
│ │ ├─────────┼─────────┼─────────┼─────────┼─────────┤ │ │
|
||||
│ │ │ ⊥ │ ⊥ │ ⊥ │ ⊥ │ ⊥ │ │ │
|
||||
│ │ │ T │ ⊥ │ T │ ⊥ │ T │ │ │
|
||||
│ │ │ F │ ⊥ │ ⊥ │ F │ F │ │ │
|
||||
│ │ │ ⊤ │ ⊥ │ T │ F │ ⊤ │ │ │
|
||||
│ │ └─────────┴─────────┴─────────┴─────────┴─────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Key insight: T ∧ F = ⊥ (unknown) │ │
|
||||
│ │ When evidence disagrees, we have no consensus - result is unknown │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EXAMPLES │ │
|
||||
│ │ │ │
|
||||
│ │ Example 1: Requiring both sources to confirm │ │
|
||||
│ │ ───────────────────────────────────────────── │ │
|
||||
│ │ Source A: T (reachable) │ │
|
||||
│ │ Source B: T (reachable) │ │
|
||||
│ │ Result: T ∧ T = T (confirmed by both) │ │
|
||||
│ │ │ │
|
||||
│ │ Example 2: One confirms, one unknown │ │
|
||||
│ │ ──────────────────────────────────────── │ │
|
||||
│ │ Source A: T (reachable) │ │
|
||||
│ │ Source B: ⊥ (no data) │ │
|
||||
│ │ Result: T ∧ ⊥ = ⊥ (can't confirm without both) │ │
|
||||
│ │ │ │
|
||||
│ │ Example 3: Sources disagree │ │
|
||||
│ │ ───────────────────────────── │ │
|
||||
│ │ Source A: T (yes) │ │
|
||||
│ │ Source B: F (no) │ │
|
||||
│ │ Result: T ∧ F = ⊥ (no consensus possible) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### NEGATION (¬)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ NEGATION OPERATION (¬) │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Negation flips T↔F but preserves ⊤ and ⊥ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ NEGATION TABLE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────┬─────────┐ │ │
|
||||
│ │ │ x │ ¬x │ │ │
|
||||
│ │ ├─────────┼─────────┤ │ │
|
||||
│ │ │ ⊥ │ ⊥ │ (unknown stays unknown) │ │
|
||||
│ │ │ T │ F │ (true becomes false) │ │
|
||||
│ │ │ F │ T │ (false becomes true) │ │
|
||||
│ │ │ ⊤ │ ⊤ │ (both stays both) │ │
|
||||
│ │ └─────────┴─────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Key insight: ¬⊤ = ⊤ │ │
|
||||
│ │ Conflict cannot be resolved by negation - "both yes and no" negated │ │
|
||||
│ │ is still "both no and yes" │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Application in Policy Engine
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ K4 IN POLICY EVALUATION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EVIDENCE AGGREGATION FLOW │ │
|
||||
│ │ │ │
|
||||
│ │ Question: "Is CVE-2021-23337 exploitable in this image?" │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Source │ Finding │ K4 Value │ │ │
|
||||
│ │ │ ─────────────────────┼───────────────────┼────────────────────────│ │ │
|
||||
│ │ │ Static analysis │ Path found │ T (True) │ │ │
|
||||
│ │ │ Runtime observation │ Not observed │ ⊥ (Unknown) │ │ │
|
||||
│ │ │ VEX (RedHat) │ Not affected │ F (False) │ │ │
|
||||
│ │ │ VEX (Ubuntu) │ Not affected │ F (False) │ │ │
|
||||
│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Aggregation using JOIN: │ │
|
||||
│ │ │ │
|
||||
│ │ Step 1: T ∨ ⊥ = T (static + runtime) │ │
|
||||
│ │ Step 2: T ∨ F = ⊤ (add VEX RedHat → conflict!) │ │
|
||||
│ │ Step 3: ⊤ ∨ F = ⊤ (add VEX Ubuntu → still conflict) │ │
|
||||
│ │ │ │
|
||||
│ │ Final K4 Value: ⊤ (Both/Conflict) │ │
|
||||
│ │ │ │
|
||||
│ │ Interpretation: We have conflicting evidence. Static analysis found │ │
|
||||
│ │ a path, but vendors say it's not affected. This needs human review. │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ VERDICT MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ K4 Value │ Verdict │ Action │ │
|
||||
│ │ ─────────┼──────────┼──────────────────────────────────────────────────────│ │
|
||||
│ │ T (True) │ FAIL │ Evidence supports vulnerability is exploitable │ │
|
||||
│ │ F (False)│ PASS │ Evidence supports vulnerability is not exploitable │ │
|
||||
│ │ ⊥ (Unknown)│ WARN │ Insufficient data - conservative warning │ │
|
||||
│ │ ⊤ (Both) │ REVIEW │ Conflicting evidence - requires human decision │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Policy Rule Evaluation
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ POLICY RULE EVALUATION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ RULE STRUCTURE │ │
|
||||
│ │ │ │
|
||||
│ │ Policy rules are predicates that evaluate to K4 values: │ │
|
||||
│ │ │ │
|
||||
│ │ rule no_critical_reachable: │ │
|
||||
│ │ condition: severity == CRITICAL AND reachable == TRUE │ │
|
||||
│ │ action: FAIL │ │
|
||||
│ │ │ │
|
||||
│ │ The "AND" uses K4 meet (∧): │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ severity == CRITICAL │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ If CVSS >= 9.0 → T │ │ │
|
||||
│ │ │ If CVSS < 9.0 → F │ │ │
|
||||
│ │ │ If CVSS unknown → ⊥ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ reachable == TRUE │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ From K4 reachability evidence (as shown above) │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Combined: severity_k4 ∧ reachable_k4 │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EVALUATION EXAMPLES │ │
|
||||
│ │ │ │
|
||||
│ │ Example 1: Critical + definitely reachable │ │
|
||||
│ │ ───────────────────────────────────────── │ │
|
||||
│ │ severity: T (CVSS 9.8) │ │
|
||||
│ │ reachable: T (static + runtime confirmed) │ │
|
||||
│ │ Result: T ∧ T = T → FAIL │ │
|
||||
│ │ │ │
|
||||
│ │ Example 2: Critical + not reachable │ │
|
||||
│ │ ──────────────────────────────────── │ │
|
||||
│ │ severity: T (CVSS 9.8) │ │
|
||||
│ │ reachable: F (static analysis proves no path) │ │
|
||||
│ │ Result: T ∧ F = ⊥ → WARN (can't prove both conditions) │ │
|
||||
│ │ │ │
|
||||
│ │ Example 3: Critical + unknown reachability │ │
|
||||
│ │ ─────────────────────────────────────────── │ │
|
||||
│ │ severity: T (CVSS 9.8) │ │
|
||||
│ │ reachable: ⊥ (no analysis done) │ │
|
||||
│ │ Result: T ∧ ⊥ = ⊥ → WARN (missing reachability data) │ │
|
||||
│ │ │ │
|
||||
│ │ Example 4: Critical + conflicting reachability │ │
|
||||
│ │ ─────────────────────────────────────────────── │ │
|
||||
│ │ severity: T (CVSS 9.8) │ │
|
||||
│ │ reachable: ⊤ (static says yes, VEX says no) │ │
|
||||
│ │ Result: T ∧ ⊤ = T → REVIEW (conflict in reachability) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ CONFLICT RESOLUTION │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ When K4 evaluation results in ⊤ (Both/Conflict): │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ RESOLUTION STRATEGIES │ │
|
||||
│ │ │ │
|
||||
│ │ 1. TRUST WEIGHTING │ │
|
||||
│ │ ─────────────────── │ │
|
||||
│ │ Weight sources by trust level and use weighted voting: │ │
|
||||
│ │ │ │
|
||||
│ │ Sources claiming T: │ │
|
||||
│ │ • Static analysis (trust: 0.7) │ │
|
||||
│ │ Total T weight: 0.7 │ │
|
||||
│ │ │ │
|
||||
│ │ Sources claiming F: │ │
|
||||
│ │ • VEX RedHat (trust: 1.0) │ │
|
||||
│ │ • VEX Ubuntu (trust: 1.0) │ │
|
||||
│ │ Total F weight: 2.0 │ │
|
||||
│ │ │ │
|
||||
│ │ Resolution: F wins (2.0 > 0.7) → PASS with note │ │
|
||||
│ │ │ │
|
||||
│ │ 2. RECENCY PREFERENCE │ │
|
||||
│ │ ───────────────────── │ │
|
||||
│ │ Prefer more recent evidence: │ │
|
||||
│ │ │ │
|
||||
│ │ • Static analysis: 2024-12-01 → T │ │
|
||||
│ │ • VEX RedHat: 2024-12-28 → F │ │
|
||||
│ │ │ │
|
||||
│ │ Resolution: F wins (more recent) → PASS │ │
|
||||
│ │ │ │
|
||||
│ │ 3. CONSERVATIVE DEFAULT │ │
|
||||
│ │ ───────────────────────── │ │
|
||||
│ │ When conflict cannot be resolved, default to safer option: │ │
|
||||
│ │ │ │
|
||||
│ │ • Conflict in reachability → assume reachable (T) │ │
|
||||
│ │ • Conflict in exploitability → assume exploitable (T) │ │
|
||||
│ │ │ │
|
||||
│ │ 4. HUMAN ESCALATION │ │
|
||||
│ │ ──────────────────── │ │
|
||||
│ │ Flag for human review with all evidence: │ │
|
||||
│ │ │ │
|
||||
│ │ { │ │
|
||||
│ │ "verdict": "REVIEW", │ │
|
||||
│ │ "reason": "conflicting_evidence", │ │
|
||||
│ │ "evidence": { │ │
|
||||
│ │ "supporting_true": ["static_analysis"], │ │
|
||||
│ │ "supporting_false": ["vex_redhat", "vex_ubuntu"] │ │
|
||||
│ │ } │ │
|
||||
│ │ } │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation
|
||||
|
||||
```csharp
|
||||
// K4 value enumeration
|
||||
public enum K4Value
|
||||
{
|
||||
Neither = 0, // ⊥ - Unknown
|
||||
True = 1, // T
|
||||
False = 2, // F
|
||||
Both = 3 // ⊤ - Conflict
|
||||
}
|
||||
|
||||
// K4 lattice operations
|
||||
public static class K4Lattice
|
||||
{
|
||||
// JOIN (∨) - combines evidence
|
||||
public static K4Value Join(K4Value a, K4Value b)
|
||||
{
|
||||
return (K4Value)((int)a | (int)b);
|
||||
}
|
||||
|
||||
// MEET (∧) - requires agreement
|
||||
public static K4Value Meet(K4Value a, K4Value b)
|
||||
{
|
||||
// Special handling for the bilattice structure
|
||||
if (a == K4Value.Neither || b == K4Value.Neither)
|
||||
return K4Value.Neither;
|
||||
if (a == b)
|
||||
return a;
|
||||
if (a == K4Value.Both)
|
||||
return b;
|
||||
if (b == K4Value.Both)
|
||||
return a;
|
||||
// T meet F = Neither (no consensus)
|
||||
return K4Value.Neither;
|
||||
}
|
||||
|
||||
// Negation
|
||||
public static K4Value Negate(K4Value x)
|
||||
{
|
||||
return x switch
|
||||
{
|
||||
K4Value.True => K4Value.False,
|
||||
K4Value.False => K4Value.True,
|
||||
_ => x // Neither and Both are self-dual
|
||||
};
|
||||
}
|
||||
|
||||
// Information ordering
|
||||
public static bool LessOrEqualInfo(K4Value a, K4Value b)
|
||||
{
|
||||
// ⊥ ≤ T, ⊥ ≤ F, T ≤ ⊤, F ≤ ⊤
|
||||
if (a == K4Value.Neither) return true;
|
||||
if (b == K4Value.Both) return true;
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
|
||||
// Evidence aggregation
|
||||
public class EvidenceAggregator
|
||||
{
|
||||
public K4Value AggregateEvidence(IEnumerable<EvidenceSource> sources)
|
||||
{
|
||||
K4Value result = K4Value.Neither; // Start with no information
|
||||
|
||||
foreach (var source in sources)
|
||||
{
|
||||
K4Value sourceValue = EvaluateSource(source);
|
||||
result = K4Lattice.Join(result, sourceValue);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private K4Value EvaluateSource(EvidenceSource source)
|
||||
{
|
||||
return source.Type switch
|
||||
{
|
||||
"static_reachable" => source.Finding ? K4Value.True : K4Value.False,
|
||||
"runtime_observed" => source.Finding ? K4Value.True : K4Value.Neither,
|
||||
"vex_not_affected" => K4Value.False,
|
||||
"vex_affected" => K4Value.True,
|
||||
_ => K4Value.Neither
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - Complete data flow
|
||||
- [Confidence Scoring](confidence-scoring.md) - Weighted evidence scoring
|
||||
- [Policy Evaluation Flow](../../flows/04-policy-evaluation-flow.md) - End-to-end flow
|
||||
- [Reachability Analysis](call-graph-analysis.md) - 8-state reachability lattice
|
||||
722
docs/technical/architecture/runtime-agents-architecture.md
Normal file
722
docs/technical/architecture/runtime-agents-architecture.md
Normal file
@@ -0,0 +1,722 @@
|
||||
# Runtime Agents Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the runtime observation layer in StellaOps, including eBPF-based kernel instrumentation, container lifecycle monitoring, and signal aggregation. Runtime evidence provides the highest-confidence reachability determination for policy decisions.
|
||||
|
||||
---
|
||||
|
||||
## Runtime Observation Stack
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ RUNTIME OBSERVATION STACK │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ APPLICATION LAYER │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Container 1 │ │ Container 2 │ │ Container 3 │ │ Container N │ │
|
||||
│ │ (app:v1) │ │ (api:v2) │ │ (worker) │ │ (...) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └────────────────┴────────────────┴────────────────┘ │
|
||||
│ │ │
|
||||
│ [Function Calls] │
|
||||
│ [System Calls] │
|
||||
│ [Network I/O] │
|
||||
│ │ │
|
||||
└────────────────────────────────────┼────────────────────────────────────────────────┘
|
||||
│
|
||||
┌────────────────────────────────────┼────────────────────────────────────────────────┐
|
||||
│ KERNEL SPACE │
|
||||
│ │ │
|
||||
│ ┌─────────────────┐ ┌────────▼────────┐ ┌─────────────────┐ │
|
||||
│ │ kprobes │ │ eBPF VM │ │ tracepoints │ │
|
||||
│ │ (syscalls) │◄───┤ (verified │───►│ (scheduler, │ │
|
||||
│ │ │ │ bytecode) │ │ network) │ │
|
||||
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └──────────────────────┼──────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────▼───────────────┐ │
|
||||
│ │ eBPF Ring Buffer │ │
|
||||
│ │ (per-CPU, lock-free) │ │
|
||||
│ └───────────────┬───────────────┘ │
|
||||
│ │ │
|
||||
└────────────────────────────────────┼────────────────────────────────────────────────┘
|
||||
│
|
||||
│ [perf events]
|
||||
│
|
||||
┌────────────────────────────────────┼────────────────────────────────────────────────┐
|
||||
│ USER SPACE │
|
||||
│ │ │
|
||||
│ ┌─────────────────────▼─────────────────────┐ │
|
||||
│ │ RuntimeSignalCollector │ │
|
||||
│ │ (StellaOps.Signals) │ │
|
||||
│ ├───────────────────────────────────────────┤ │
|
||||
│ │ • Perf event polling │ │
|
||||
│ │ • Symbol resolution (DWARF/kallsyms) │ │
|
||||
│ │ • Stack unwinding │ │
|
||||
│ │ • Container ID correlation (cgroup) │ │
|
||||
│ │ • Event batching and compression │ │
|
||||
│ └─────────────────────┬─────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────────────▼─────────────────────┐ │
|
||||
│ │ ZastavaObserver │ │
|
||||
│ │ (Container Lifecycle) │ │
|
||||
│ ├───────────────────────────────────────────┤ │
|
||||
│ │ • Container create/start/stop events │ │
|
||||
│ │ • Image digest extraction │ │
|
||||
│ │ • Runtime posture evaluation │ │
|
||||
│ │ • Label/annotation parsing │ │
|
||||
│ └─────────────────────┬─────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────────────▼─────────────────────┐ │
|
||||
│ │ RuntimeSignalNormalizer │ │
|
||||
│ │ (Event Processing) │ │
|
||||
│ ├───────────────────────────────────────────┤ │
|
||||
│ │ • Deduplicate events │ │
|
||||
│ │ • Aggregate call counts │ │
|
||||
│ │ • Map to package PURLs │ │
|
||||
│ │ • Enrich with SBOM context │ │
|
||||
│ └─────────────────────┬─────────────────────┘ │
|
||||
│ │ │
|
||||
└────────────────────────────────────┼────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ STORAGE LAYER │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Hot Symbol Index │ │
|
||||
│ │ (PostgreSQL: signals.hot_symbols) │ │
|
||||
│ │ │ │
|
||||
│ │ image_digest │ function_name │ purl │ invocation_count │ last_observed │ │
|
||||
│ │ ─────────────┼───────────────┼──────┼──────────────────┼───────────────── │ │
|
||||
│ │ sha256:abc.. │ lodash.merge │ npm/..│ 1,247 │ 2024-12-29T10:00 │ │
|
||||
│ │ sha256:abc.. │ lodash.get │ npm/..│ 8,923 │ 2024-12-29T10:01 │ │
|
||||
│ │ sha256:def.. │ axios.request │ npm/..│ 456 │ 2024-12-29T09:55 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## eBPF Agent Architecture
|
||||
|
||||
### Probe Types
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ eBPF PROBE TYPES │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ KPROBES / KRETPROBES │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Trace kernel function entry/exit │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Syscall Tracing │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ kprobe/sys_execve → New process execution │ │ │
|
||||
│ │ │ kprobe/sys_openat → File access │ │ │
|
||||
│ │ │ kprobe/sys_connect → Network connection │ │ │
|
||||
│ │ │ kprobe/sys_socket → Socket creation │ │ │
|
||||
│ │ │ kprobe/sys_read → File/socket reads │ │ │
|
||||
│ │ │ kprobe/sys_write → File/socket writes │ │ │
|
||||
│ │ │ kprobe/sys_mmap → Memory mapping │ │ │
|
||||
│ │ │ kprobe/sys_clone → Process/thread creation │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ TRACEPOINTS │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Stable kernel instrumentation points │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Category │ Tracepoint │ Data │ │ │
|
||||
│ │ │ ──────────────────┼───────────────────────────┼──────────────────│ │ │
|
||||
│ │ │ Scheduler │ sched:sched_process_exec │ New execution │ │ │
|
||||
│ │ │ Scheduler │ sched:sched_switch │ Context switch │ │ │
|
||||
│ │ │ Network │ net:net_dev_xmit │ Packet TX │ │ │
|
||||
│ │ │ Network │ sock:inet_sock_set_state │ TCP state │ │ │
|
||||
│ │ │ Filesystem │ ext4:ext4_da_write_begin │ Write start │ │ │
|
||||
│ │ │ Memory │ kmem:kmalloc │ Allocation │ │ │
|
||||
│ │ │ Security │ security:security_* │ LSM hooks │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ UPROBES │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: Trace userspace function entry/exit │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Library/Function Tracing │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc │ │ │
|
||||
│ │ │ uprobe:/usr/lib/libssl.so:SSL_read │ │ │
|
||||
│ │ │ uprobe:/usr/lib/libcrypto.so:EVP_EncryptFinal │ │ │
|
||||
│ │ │ uprobe:/path/to/app:vulnerable_function │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Dynamic attachment based on: │ │ │
|
||||
│ │ │ • SBOM analysis (known vulnerable functions) │ │ │
|
||||
│ │ │ • Static call graph (entry points to vulnerable code) │ │ │
|
||||
│ │ │ • Symbol resolution from DWARF/debug info │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ USDT PROBES │ │
|
||||
│ │ │ │
|
||||
│ │ Purpose: User Statically Defined Tracing (application-level) │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Runtime-Specific Probes │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Node.js: │ │ │
|
||||
│ │ │ usdt:/usr/bin/node:http__server__request │ │ │
|
||||
│ │ │ usdt:/usr/bin/node:gc__start │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Python: │ │ │
|
||||
│ │ │ usdt:/usr/bin/python3:function__entry │ │ │
|
||||
│ │ │ usdt:/usr/bin/python3:function__return │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ JVM: │ │ │
|
||||
│ │ │ usdt:libjvm.so:method__entry │ │ │
|
||||
│ │ │ usdt:libjvm.so:gc__begin │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Event Data Structures
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ eBPF EVENT DATA STRUCTURES │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ FunctionCallEvent │ │
|
||||
│ │ │ │
|
||||
│ │ struct function_call_event { │ │
|
||||
│ │ u64 timestamp_ns; // Kernel monotonic timestamp │ │
|
||||
│ │ u32 pid; // Process ID │ │
|
||||
│ │ u32 tid; // Thread ID │ │
|
||||
│ │ u64 cgroup_id; // Container cgroup (for correlation) │ │
|
||||
│ │ u32 uid; // User ID │ │
|
||||
│ │ char comm[16]; // Process name │ │
|
||||
│ │ char func_name[64]; // Function name (if resolved) │ │
|
||||
│ │ u64 func_addr; // Function address (for offline resolution) │ │
|
||||
│ │ u64 caller_addr; // Return address (call site) │ │
|
||||
│ │ u64 stack_id; // Stack trace ID (BPF_MAP_TYPE_STACK_TRACE) │ │
|
||||
│ │ u64 latency_ns; // Function execution time (kretprobe) │ │
|
||||
│ │ u8 event_type; // ENTRY(0), EXIT(1), ERROR(2) │ │
|
||||
│ │ }; │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SyscallEvent │ │
|
||||
│ │ │ │
|
||||
│ │ struct syscall_event { │ │
|
||||
│ │ u64 timestamp_ns; // Kernel monotonic timestamp │ │
|
||||
│ │ u32 pid; // Process ID │ │
|
||||
│ │ u32 tid; // Thread ID │ │
|
||||
│ │ u64 cgroup_id; // Container cgroup │ │
|
||||
│ │ u32 syscall_nr; // Syscall number │ │
|
||||
│ │ u64 args[6]; // Syscall arguments │ │
|
||||
│ │ i64 ret; // Return value │ │
|
||||
│ │ u64 latency_ns; // Syscall duration │ │
|
||||
│ │ u64 stack_id; // Stack trace ID │ │
|
||||
│ │ }; │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ NetworkEvent │ │
|
||||
│ │ │ │
|
||||
│ │ struct network_event { │ │
|
||||
│ │ u64 timestamp_ns; │ │
|
||||
│ │ u32 pid; │ │
|
||||
│ │ u64 cgroup_id; │ │
|
||||
│ │ u8 protocol; // TCP(6), UDP(17) │ │
|
||||
│ │ u8 direction; // INBOUND(0), OUTBOUND(1) │ │
|
||||
│ │ u32 src_addr; // Source IPv4 (or first 4 bytes of IPv6) │ │
|
||||
│ │ u32 dst_addr; // Destination IPv4 │ │
|
||||
│ │ u16 src_port; │ │
|
||||
│ │ u16 dst_port; │ │
|
||||
│ │ u64 bytes; // Data transferred │ │
|
||||
│ │ u8 state; // TCP state (ESTABLISHED, SYN_SENT, etc.) │ │
|
||||
│ │ }; │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Zastava Container Observer
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ZASTAVA CONTAINER OBSERVER │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ARCHITECTURE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────────────────────┐ │ │
|
||||
│ │ │ Container Runtime │ │ │
|
||||
│ │ │ ┌─────────┐ ┌─────────────────┐│ │ │
|
||||
│ │ │ │ Docker │ │ containerd ││ │ │
|
||||
│ │ │ │ Engine │ │ ││ │ │
|
||||
│ │ │ └────┬────┘ └────────┬────────┘│ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ └───────┼───────────────┼─────────┘ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ ┌──────────▼───────────────▼──────────┐ │ │
|
||||
│ │ │ ZastavaObserver │ │ │
|
||||
│ │ │ (Event Subscriber) │ │ │
|
||||
│ │ ├─────────────────────────────────────┤ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Connects to: │ │ │
|
||||
│ │ │ • /var/run/docker.sock │ │ │
|
||||
│ │ │ • /run/containerd/containerd.sock │ │ │
|
||||
│ │ │ • /run/crio/crio.sock │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Listens for: │ │ │
|
||||
│ │ │ • container.create │ │ │
|
||||
│ │ │ • container.start │ │ │
|
||||
│ │ │ • container.stop │ │ │
|
||||
│ │ │ • container.die │ │ │
|
||||
│ │ │ • image.pull │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────┬────────────────────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ▼ │ │
|
||||
│ │ ┌─────────────────────────────────────┐ │ │
|
||||
│ │ │ ContainerLifecycleEvent │ │ │
|
||||
│ │ ├─────────────────────────────────────┤ │ │
|
||||
│ │ │ event_type: CREATE|START|STOP|DIE │ │ │
|
||||
│ │ │ container_id: string │ │ │
|
||||
│ │ │ image_ref: string │ │ │
|
||||
│ │ │ image_digest: sha256:... │ │ │
|
||||
│ │ │ labels: map<string,string> │ │ │
|
||||
│ │ │ annotations: map<string,string> │ │ │
|
||||
│ │ │ env_vars: string[] (filtered) │ │ │
|
||||
│ │ │ pid: u32 (on start) │ │ │
|
||||
│ │ │ cgroup_path: string │ │ │
|
||||
│ │ │ started_at: timestamp │ │ │
|
||||
│ │ │ stopped_at: timestamp │ │ │
|
||||
│ │ │ exit_code: i32 │ │ │
|
||||
│ │ │ oom_killed: bool │ │ │
|
||||
│ │ └─────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ RUNTIME POSTURE EVALUATION │ │
|
||||
│ │ │ │
|
||||
│ │ On container START, Zastava evaluates the runtime observation posture: │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Posture │ Observation Level │ Prerequisites │ │ │
|
||||
│ │ ├───────────────────────┼──────────────────────┼─────────────────────┤ │ │
|
||||
│ │ │ None │ No observation │ eBPF disabled │ │ │
|
||||
│ │ │ Passive │ Lifecycle only │ Docker socket only │ │ │
|
||||
│ │ │ ActiveTracing │ Syscalls + network │ eBPF + kprobes │ │ │
|
||||
│ │ │ EbpfDeep │ + function calls │ + uprobes enabled │ │ │
|
||||
│ │ │ FullInstrumentation │ + USDT + coverage │ + debug symbols │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Posture is determined by: │ │
|
||||
│ │ 1. Kernel capabilities (CAP_BPF, CAP_SYS_ADMIN) │ │
|
||||
│ │ 2. Available probe types │ │
|
||||
│ │ 3. Container annotations (stellaops.io/observe-level) │ │
|
||||
│ │ 4. Image debug symbol availability │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Signal Processing Pipeline
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SIGNAL PROCESSING PIPELINE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Raw Events │
|
||||
│ (millions/sec) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STAGE 1: FILTERING │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ In-Kernel Filtering (eBPF maps) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ • Filter by cgroup_id (only monitored containers) │ │ │
|
||||
│ │ │ • Filter by syscall type (only security-relevant) │ │ │
|
||||
│ │ │ • Rate limiting per-container (prevent flood) │ │ │
|
||||
│ │ │ • Sampling for high-frequency events │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────┬──────────────┘ │
|
||||
│ │ │
|
||||
│ Filtered Events │ │
|
||||
│ (thousands/sec) │ │
|
||||
│ │◄────────────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STAGE 2: ENRICHMENT │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Symbol Resolution │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ func_addr: 0x7f3a4b5c6d7e │ │ │
|
||||
│ │ │ ↓ │ │ │
|
||||
│ │ │ Resolve via: │ │ │
|
||||
│ │ │ 1. /proc/<pid>/maps (memory mappings) │ │ │
|
||||
│ │ │ 2. Symbol table cache (from SBOM binaries) │ │ │
|
||||
│ │ │ 3. DWARF debug info (if available) │ │ │
|
||||
│ │ │ 4. kallsyms (for kernel symbols) │ │ │
|
||||
│ │ │ ↓ │ │ │
|
||||
│ │ │ func_name: "lodash.template" │ │ │
|
||||
│ │ │ module: "/app/node_modules/lodash/lodash.js" │ │ │
|
||||
│ │ │ purl: "pkg:npm/lodash@4.17.20" │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Container Correlation │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ cgroup_id: 12345678 │ │ │
|
||||
│ │ │ ↓ │ │ │
|
||||
│ │ │ Lookup in Zastava registry: │ │ │
|
||||
│ │ │ ↓ │ │ │
|
||||
│ │ │ container_id: "abc123def456" │ │ │
|
||||
│ │ │ image_digest: "sha256:789..." │ │ │
|
||||
│ │ │ scan_id: "scan-xyz" (from label) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────┬──────────────────┘ │
|
||||
│ │ │
|
||||
│ Enriched Events │ │
|
||||
│ (hundreds/sec) │ │
|
||||
│ │◄─────────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STAGE 3: AGGREGATION │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Time-Window Aggregation (1-minute windows) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Key: (image_digest, purl, function_name) │ │ │
|
||||
│ │ │ Value: AggregatedMetrics { │ │ │
|
||||
│ │ │ invocation_count: u64, │ │ │
|
||||
│ │ │ unique_callers: HashSet<caller_addr>, │ │ │
|
||||
│ │ │ total_latency_ns: u64, │ │ │
|
||||
│ │ │ max_latency_ns: u64, │ │ │
|
||||
│ │ │ sample_stack: Option<StackTrace>, │ │ │
|
||||
│ │ │ first_seen: Timestamp, │ │ │
|
||||
│ │ │ last_seen: Timestamp, │ │ │
|
||||
│ │ │ } │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────┬──────────────────┘ │
|
||||
│ │ │
|
||||
│ Aggregated Records │ │
|
||||
│ (per function per minute) │ │
|
||||
│ │◄─────────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ STAGE 4: PERSISTENCE │ │
|
||||
│ │ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ PostgreSQL: signals.hot_symbols │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ INSERT INTO signals.hot_symbols │ │ │
|
||||
│ │ │ (image_digest, function_name, purl, invocation_count, ...) │ │ │
|
||||
│ │ │ ON CONFLICT (image_digest, function_name) │ │ │
|
||||
│ │ │ DO UPDATE SET │ │ │
|
||||
│ │ │ invocation_count = hot_symbols.invocation_count + EXCLUDED.count,│ │ │
|
||||
│ │ │ last_observed = EXCLUDED.last_observed, │ │ │
|
||||
│ │ │ sample_stack = COALESCE(EXCLUDED.sample_stack, hot_symbols....) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └──────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hot Symbol Index Schema
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ HOT SYMBOL INDEX SCHEMA │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ TABLE: signals.hot_symbols │ │
|
||||
│ │ │ │
|
||||
│ │ CREATE TABLE signals.hot_symbols ( │ │
|
||||
│ │ -- Identity │ │
|
||||
│ │ id BIGSERIAL PRIMARY KEY, │ │
|
||||
│ │ image_digest TEXT NOT NULL, │ │
|
||||
│ │ function_name TEXT NOT NULL, │ │
|
||||
│ │ module TEXT, -- Library/file containing func │ │
|
||||
│ │ purl TEXT, -- Package URL for module │ │
|
||||
│ │ │ │
|
||||
│ │ -- Observation metrics │ │
|
||||
│ │ invocation_count BIGINT DEFAULT 0, │ │
|
||||
│ │ unique_callers INTEGER DEFAULT 0, │ │
|
||||
│ │ total_latency_ns BIGINT DEFAULT 0, │ │
|
||||
│ │ max_latency_ns BIGINT DEFAULT 0, │ │
|
||||
│ │ │ │
|
||||
│ │ -- Timestamps │ │
|
||||
│ │ first_observed TIMESTAMPTZ NOT NULL DEFAULT NOW(), │ │
|
||||
│ │ last_observed TIMESTAMPTZ NOT NULL DEFAULT NOW(), │ │
|
||||
│ │ │ │
|
||||
│ │ -- Sample data │ │
|
||||
│ │ sample_stack JSONB, -- Representative stack trace │ │
|
||||
│ │ sample_args JSONB, -- Sample arguments (if captured) │ │
|
||||
│ │ │ │
|
||||
│ │ -- Constraints │ │
|
||||
│ │ CONSTRAINT hot_symbols_unique UNIQUE (image_digest, function_name) │ │
|
||||
│ │ ); │ │
|
||||
│ │ │ │
|
||||
│ │ -- Indexes │ │
|
||||
│ │ CREATE INDEX idx_hot_symbols_purl ON signals.hot_symbols(purl); │ │
|
||||
│ │ CREATE INDEX idx_hot_symbols_count ON signals.hot_symbols(invocation_count);│ │
|
||||
│ │ CREATE INDEX idx_hot_symbols_last ON signals.hot_symbols(last_observed); │ │
|
||||
│ │ CREATE INDEX idx_hot_symbols_image ON signals.hot_symbols(image_digest); │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ QUERY EXAMPLES │ │
|
||||
│ │ │ │
|
||||
│ │ -- Is vulnerable function observed at runtime? │ │
|
||||
│ │ SELECT EXISTS ( │ │
|
||||
│ │ SELECT 1 FROM signals.hot_symbols │ │
|
||||
│ │ WHERE image_digest = $1 │ │
|
||||
│ │ AND purl = $2 │ │
|
||||
│ │ AND function_name = $3 │ │
|
||||
│ │ AND invocation_count > 0 │ │
|
||||
│ │ ); │ │
|
||||
│ │ │ │
|
||||
│ │ -- Get all observed functions for a vulnerable package │ │
|
||||
│ │ SELECT function_name, invocation_count, last_observed, sample_stack │ │
|
||||
│ │ FROM signals.hot_symbols │ │
|
||||
│ │ WHERE image_digest = $1 AND purl = $2 │ │
|
||||
│ │ ORDER BY invocation_count DESC; │ │
|
||||
│ │ │ │
|
||||
│ │ -- Hot path analysis (most called functions) │ │
|
||||
│ │ SELECT purl, function_name, SUM(invocation_count) as total_calls │ │
|
||||
│ │ FROM signals.hot_symbols │ │
|
||||
│ │ WHERE image_digest = $1 │ │
|
||||
│ │ GROUP BY purl, function_name │ │
|
||||
│ │ ORDER BY total_calls DESC │ │
|
||||
│ │ LIMIT 100; │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Runtime Evidence Integration
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ RUNTIME EVIDENCE → POLICY ENGINE │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ REACHABILITY STATE MAPPING │ │
|
||||
│ │ │ │
|
||||
│ │ Runtime Evidence → Reachability State │ │
|
||||
│ │ ───────────────────────────────────────────────────────────────────────── │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Function observed at runtime → DynamicReachable │ │ │
|
||||
│ │ │ (invocation_count > 0) (confidence: 0.90) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Function observed + exploit path → LiveExploitPath │ │ │
|
||||
│ │ │ (confirmed vulnerable flow) (confidence: 1.00) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ Package imported but function → PotentiallyReachable │ │ │
|
||||
│ │ │ not observed (long window) (confidence: 0.50) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ No runtime observation → (defer to static analysis) │ │ │
|
||||
│ │ │ (posture = None) │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CONFIDENCE FACTOR CALCULATION │ │
|
||||
│ │ │ │
|
||||
│ │ The Runtime factor (RTS) in confidence scoring: │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Scenario │ RTS Score │ Weight: 0.25 │ │ │
|
||||
│ │ │ ──────────────────────────────────┼───────────┼───────────────── │ │ │
|
||||
│ │ │ High frequency observation │ 1.00 │ Strong evidence │ │ │
|
||||
│ │ │ (invocation_count > 1000/day) │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ Moderate observation │ 0.80 │ Confirmed used │ │ │
|
||||
│ │ │ (invocation_count > 0) │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ No observation (neutral) │ 0.50 │ Inconclusive │ │ │
|
||||
│ │ │ (posture active, no calls) │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ No observation (long window) │ 0.20 │ Likely unused │ │ │
|
||||
│ │ │ (>30 days, no calls) │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ No runtime posture │ 0.50 │ Cannot determine │ │ │
|
||||
│ │ │ (eBPF not available) │ │ │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EVIDENCE CHAIN │ │
|
||||
│ │ │ │
|
||||
│ │ When runtime observation is available: │ │
|
||||
│ │ │ │
|
||||
│ │ Evidence { │ │
|
||||
│ │ source: "signals/hot_symbols", │ │
|
||||
│ │ evidence_type: "runtime_observation", │ │
|
||||
│ │ data: { │ │
|
||||
│ │ image_digest: "sha256:abc...", │ │
|
||||
│ │ purl: "pkg:npm/lodash@4.17.20", │ │
|
||||
│ │ function: "lodash.template", │ │
|
||||
│ │ invocation_count: 1247, │ │
|
||||
│ │ observation_window: "2024-12-01T00:00:00Z/2024-12-29T00:00:00Z", │ │
|
||||
│ │ sample_stack: [ ... ] │ │
|
||||
│ │ }, │ │
|
||||
│ │ confidence: 0.90, │ │
|
||||
│ │ timestamp: "2024-12-29T10:30:00Z" │ │
|
||||
│ │ } │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment Considerations
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ DEPLOYMENT CONSIDERATIONS │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ KERNEL REQUIREMENTS │ │
|
||||
│ │ │ │
|
||||
│ │ Minimum: Linux 5.8+ (BPF_LINK, ring buffer support) │ │
|
||||
│ │ Recommended: Linux 5.15+ (BTF, CO-RE) │ │
|
||||
│ │ │ │
|
||||
│ │ Required kernel config: │ │
|
||||
│ │ • CONFIG_BPF=y │ │
|
||||
│ │ • CONFIG_BPF_SYSCALL=y │ │
|
||||
│ │ • CONFIG_BPF_JIT=y │ │
|
||||
│ │ • CONFIG_HAVE_EBPF_JIT=y │ │
|
||||
│ │ • CONFIG_DEBUG_INFO_BTF=y (for CO-RE) │ │
|
||||
│ │ • CONFIG_UPROBE_EVENTS=y (for uprobes) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ CONTAINER PRIVILEGES │ │
|
||||
│ │ │ │
|
||||
│ │ Agent container requires: │ │
|
||||
│ │ │ │
|
||||
│ │ securityContext: │ │
|
||||
│ │ privileged: true # For eBPF loading │ │
|
||||
│ │ # OR use capabilities: │ │
|
||||
│ │ capabilities: │ │
|
||||
│ │ add: │ │
|
||||
│ │ - SYS_ADMIN # BPF program loading │ │
|
||||
│ │ - SYS_PTRACE # Stack unwinding │ │
|
||||
│ │ - SYS_RESOURCE # RLIMIT_MEMLOCK │ │
|
||||
│ │ - NET_ADMIN # Network probes │ │
|
||||
│ │ - BPF # BPF operations (5.8+) │ │
|
||||
│ │ - PERFMON # Performance monitoring (5.8+) │ │
|
||||
│ │ │ │
|
||||
│ │ Volume mounts: │ │
|
||||
│ │ - /sys/kernel/debug (debugfs, for kprobes) │ │
|
||||
│ │ - /var/run/docker.sock (container events) │ │
|
||||
│ │ - /proc (process info) │ │
|
||||
│ │ - /sys/fs/bpf (BPF filesystem, optional) │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ PERFORMANCE IMPACT │ │
|
||||
│ │ │ │
|
||||
│ │ Overhead by probe type: │ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Probe Type │ Latency Added │ CPU Overhead │ Memory │ │ │
|
||||
│ │ │ ────────────────┼──────────────────┼──────────────┼──────────────│ │ │
|
||||
│ │ │ kprobe │ ~100-500ns │ <0.5% │ ~1MB/probe │ │ │
|
||||
│ │ │ tracepoint │ ~50-100ns │ <0.2% │ ~500KB/tp │ │ │
|
||||
│ │ │ uprobe │ ~1-5us │ 1-3%* │ ~1MB/probe │ │ │
|
||||
│ │ │ USDT │ ~500ns-2us │ <1% │ ~1MB/probe │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ * uprobe overhead depends on call frequency │ │ │
|
||||
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ Mitigation strategies: │ │
|
||||
│ │ • Selective probe attachment (only observed containers) │ │
|
||||
│ │ • In-kernel filtering (reduce userspace events) │ │
|
||||
│ │ • Sampling for high-frequency events │ │
|
||||
│ │ • Per-container rate limiting │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - How runtime feeds policy
|
||||
- [Reachability Drift Alert Flow](../../flows/19-reachability-drift-alert-flow.md) - Runtime-triggered alerts
|
||||
- [Signals Module Architecture](../../modules/signals/architecture.md) - Signals module dossier
|
||||
- [Zastava Architecture](../../modules/zastava/architecture.md) - Container observer dossier
|
||||
778
docs/technical/architecture/sbom-analyzer-inventory.md
Normal file
778
docs/technical/architecture/sbom-analyzer-inventory.md
Normal file
@@ -0,0 +1,778 @@
|
||||
# SBOM Analyzer Inventory
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a complete inventory of all analyzers used in StellaOps SBOM generation. The Scanner module employs 20+ specialized analyzers organized into four categories: Language, OS/Distribution, Surface, and Capability analyzers.
|
||||
|
||||
---
|
||||
|
||||
## Analyzer Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SCANNER ANALYZER ARCHITECTURE │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────┐
|
||||
│ Container Image │
|
||||
│ (OCI/tar/dir) │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ Layer Extractor │
|
||||
│ (FS reconstruction)│
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌──────────────────────────────┼──────────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
|
||||
│ LANGUAGE ANALYZERS │ │ OS ANALYZERS │ │ SURFACE ANALYZERS │
|
||||
│ (11) │ │ (9) │ │ (4) │
|
||||
├─────────────────────┤ ├─────────────────────┤ ├─────────────────────┤
|
||||
│ • DotNetAnalyzer │ │ • APKAnalyzer │ │ • FSAnalyzer │
|
||||
│ • JavaAnalyzer │ │ • DPKGAnalyzer │ │ • EnvAnalyzer │
|
||||
│ • NodeAnalyzer │ │ • RPMAnalyzer │ │ • SecretsAnalyzer │
|
||||
│ • PythonAnalyzer │ │ • HomebrewAnalyzer │ │ • ValidationAnalyzer│
|
||||
│ • GoAnalyzer │ │ • PkgutilAnalyzer │ └─────────────────────┘
|
||||
│ • RustAnalyzer │ │ • MacOsBundleAnalyzer
|
||||
│ • PhpAnalyzer │ │ • ChocolateyAnalyzer│ ┌─────────────────────┐
|
||||
│ • RubyAnalyzer │ │ • MSIAnalyzer │ │CAPABILITY ANALYZERS │
|
||||
│ • DenoAnalyzer │ │ • WinSxSAnalyzer │ │ (1) │
|
||||
│ • BunAnalyzer │ └─────────────────────┘ ├─────────────────────┤
|
||||
│ • NativeAnalyzer │ │ • CapabilityDetector│
|
||||
└─────────────────────┘ └─────────────────────┘
|
||||
│ │ │
|
||||
└──────────────────────────────┼──────────────────────────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ SBOM Composer │
|
||||
│ (Dedup + Merge) │
|
||||
└──────────┬──────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ CycloneDX │ │ SPDX │ │ CBOM │
|
||||
│ 1.4-1.6 │ │ 2.3 / 3.0.1 │ │ (Cryptographic) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Language Analyzers (11)
|
||||
|
||||
### 1. DotNetAnalyzer
|
||||
|
||||
**Ecosystem:** .NET / NuGet
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ DotNetAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ *.csproj, *.fsproj, *.vbproj │ SDK-style project files │ │
|
||||
│ │ *.props, *.targets │ MSBuild imports │ │
|
||||
│ │ packages.config │ Legacy package references │ │
|
||||
│ │ *.deps.json │ Runtime dependency manifest │ │
|
||||
│ │ *.nuspec │ NuGet package manifest │ │
|
||||
│ │ paket.lock, paket.dependencies │ Paket package manager │ │
|
||||
│ │ global.json │ SDK version pinning │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse SDK-style <PackageReference> elements │
|
||||
│ 2. Parse legacy packages.config XML │
|
||||
│ 3. Parse *.deps.json for runtime dependencies │
|
||||
│ 4. Resolve transitive dependencies from asset files │
|
||||
│ 5. Extract framework targeting (net6.0, net8.0, etc.) │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:nuget/Newtonsoft.Json@13.0.1 │
|
||||
│ pkg:nuget/Microsoft.Extensions.Logging@8.0.0?framework=net8.0 │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Framework-specific dependencies │
|
||||
│ • Native/runtime dependencies (rid-specific) │
|
||||
│ • Source-linked packages │
|
||||
│ • Central Package Management (Directory.Packages.props) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. JavaAnalyzer
|
||||
|
||||
**Ecosystem:** Maven / Gradle / Ivy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ JavaAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ pom.xml │ Maven POM (project model) │ │
|
||||
│ │ build.gradle, build.gradle.kts │ Gradle build files │ │
|
||||
│ │ settings.gradle(.kts) │ Gradle settings │ │
|
||||
│ │ gradle.lockfile │ Gradle dependency lock │ │
|
||||
│ │ ivy.xml │ Apache Ivy descriptor │ │
|
||||
│ │ *.jar!/META-INF/MANIFEST.MF │ JAR manifest │ │
|
||||
│ │ *.jar!/META-INF/maven/**/pom.xml│ Embedded POM │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse Maven effective POM (resolve parent, properties) │
|
||||
│ 2. Parse Gradle dependency configurations │
|
||||
│ 3. Inspect JAR manifests for version info │
|
||||
│ 4. Detect shaded/relocated classes │
|
||||
│ 5. Extract BOM (Bill of Materials) imports │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1 │
|
||||
│ pkg:maven/com.google.guava/guava@31.1-jre?type=jar │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Shaded JARs (relocated packages) │
|
||||
│ • Classifiers (sources, javadoc, tests) │
|
||||
│ • Optional/provided scope dependencies │
|
||||
│ • Version ranges resolution │
|
||||
│ • Multi-module projects │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. NodeAnalyzer
|
||||
|
||||
**Ecosystem:** npm / Yarn / pnpm
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ NodeAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ package.json │ Package manifest │ │
|
||||
│ │ package-lock.json │ npm lockfile (v2/v3) │ │
|
||||
│ │ npm-shrinkwrap.json │ npm shrinkwrap │ │
|
||||
│ │ yarn.lock │ Yarn Classic lockfile │ │
|
||||
│ │ .yarnrc.yml + yarn.lock │ Yarn Berry lockfile │ │
|
||||
│ │ pnpm-lock.yaml │ pnpm lockfile │ │
|
||||
│ │ node_modules/**/package.json │ Installed packages │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse lockfile for exact resolved versions │
|
||||
│ 2. Parse package.json for declared dependencies │
|
||||
│ 3. Walk node_modules for installed packages │
|
||||
│ 4. Detect workspace configurations (monorepos) │
|
||||
│ 5. Identify bundled dependencies │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:npm/lodash@4.17.21 │
|
||||
│ pkg:npm/%40babel/core@7.20.0 (scoped) │
|
||||
│ pkg:npm/express@4.18.2?resolved=https://registry.npmjs.org/... │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Scoped packages (@org/package) │
|
||||
│ • Peer dependencies │
|
||||
│ • Optional dependencies │
|
||||
│ • Workspace/monorepo packages │
|
||||
│ • Aliased packages │
|
||||
│ • Git dependencies (git+https://...) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4. PythonAnalyzer
|
||||
|
||||
**Ecosystem:** PyPI / pip / Poetry / Pipenv
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ PythonAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ requirements.txt │ pip requirements │ │
|
||||
│ │ requirements-*.txt │ Environment-specific reqs │ │
|
||||
│ │ setup.py │ Setuptools config (legacy) │ │
|
||||
│ │ setup.cfg │ Declarative setuptools │ │
|
||||
│ │ pyproject.toml │ PEP 517/518/621 config │ │
|
||||
│ │ Pipfile, Pipfile.lock │ Pipenv files │ │
|
||||
│ │ poetry.lock │ Poetry lockfile │ │
|
||||
│ │ *.egg-info/PKG-INFO │ Installed egg metadata │ │
|
||||
│ │ *.dist-info/METADATA │ Installed wheel metadata │ │
|
||||
│ │ site-packages/* │ Installed packages │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse lockfiles for pinned versions │
|
||||
│ 2. Parse pyproject.toml [project.dependencies] │
|
||||
│ 3. Parse requirements.txt with constraint handling │
|
||||
│ 4. Walk site-packages for METADATA files │
|
||||
│ 5. Detect extras and environment markers │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:pypi/requests@2.28.1 │
|
||||
│ pkg:pypi/django@4.1.5?extras=argon2 │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Environment markers (platform, python_version) │
|
||||
│ • Extras ([package[extra1,extra2]]) │
|
||||
│ • Editable installs (-e .) │
|
||||
│ • Version constraints (>=1.0,<2.0) │
|
||||
│ • Hash checking mode │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 5. GoAnalyzer
|
||||
|
||||
**Ecosystem:** Go Modules
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ GoAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ go.mod │ Module definition │ │
|
||||
│ │ go.sum │ Dependency checksums │ │
|
||||
│ │ vendor/modules.txt │ Vendored dependencies │ │
|
||||
│ │ Binary: __go_buildinfo │ Embedded build info (Go 1.18+) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse go.mod require directives │
|
||||
│ 2. Parse go.sum for integrity verification │
|
||||
│ 3. Detect replace directives (local replacements) │
|
||||
│ 4. Extract build info from compiled binaries │
|
||||
│ 5. Handle pseudo-versions (v0.0.0-yyyymmddhhmmss-hash) │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:golang/github.com/gin-gonic/gin@v1.8.1 │
|
||||
│ pkg:golang/golang.org/x/crypto@v0.0.0-20220722-abcdef │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Replace directives (local, version) │
|
||||
│ • Retract versions │
|
||||
│ • Pseudo-versions from git │
|
||||
│ • +incompatible suffix │
|
||||
│ • Minimal version selection (MVS) │
|
||||
│ • Binary build info extraction (no source needed) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 6. RustAnalyzer
|
||||
|
||||
**Ecosystem:** Cargo / crates.io
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ RustAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Cargo.toml │ Package manifest │ │
|
||||
│ │ Cargo.lock │ Dependency lockfile │ │
|
||||
│ │ Binary: .comment section │ rustc version (ELF) │ │
|
||||
│ │ Binary: .rdata │ rustc version (PE) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse Cargo.lock [[package]] entries │
|
||||
│ 2. Parse Cargo.toml [dependencies] │
|
||||
│ 3. Handle workspace members │
|
||||
│ 4. Detect target-specific dependencies │
|
||||
│ 5. Extract feature flags │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:cargo/serde@1.0.152 │
|
||||
│ pkg:cargo/tokio@1.25.0?features=full │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Feature flags │
|
||||
│ • Target-specific dependencies [target.'cfg(...)'.dependencies] │
|
||||
│ • Build dependencies [build-dependencies] │
|
||||
│ • Dev dependencies [dev-dependencies] │
|
||||
│ • Workspace inheritance │
|
||||
│ • Path/git dependencies │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 7. PhpAnalyzer
|
||||
|
||||
**Ecosystem:** Composer / Packagist
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ PhpAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ composer.json │ Package definition │ │
|
||||
│ │ composer.lock │ Dependency lockfile │ │
|
||||
│ │ vendor/composer/installed.json│ Installed packages │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:composer/laravel/framework@9.48.0 │
|
||||
│ pkg:composer/symfony/http-foundation@6.2.0 │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • PHP version constraints │
|
||||
│ • Extension requirements (ext-*) │
|
||||
│ • Platform packages (php, lib-*) │
|
||||
│ • Stability flags (dev, alpha, beta, RC) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8. RubyAnalyzer
|
||||
|
||||
**Ecosystem:** RubyGems / Bundler
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ RubyAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Gemfile │ Bundler dependencies │ │
|
||||
│ │ Gemfile.lock │ Bundler lockfile │ │
|
||||
│ │ *.gemspec │ Gem specification │ │
|
||||
│ │ gems.rb / gems.locked │ Alternative Bundler format │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:gem/rails@7.0.4 │
|
||||
│ pkg:gem/nokogiri@1.14.0?platform=ruby │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Platform-specific gems │
|
||||
│ • Git/path sources │
|
||||
│ • Groups (development, test, production) │
|
||||
│ • Ruby version constraints │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 9. DenoAnalyzer
|
||||
|
||||
**Ecosystem:** Deno / deno.land
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ DenoAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ deno.json / deno.jsonc │ Deno configuration │ │
|
||||
│ │ deno.lock │ Deno lockfile │ │
|
||||
│ │ import_map.json │ Import map │ │
|
||||
│ │ deps.ts │ Dependency re-exports │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:deno/std@0.177.0 │
|
||||
│ pkg:deno/oak@v11.1.0 │
|
||||
│ pkg:npm/lodash@4.17.21 (via npm: specifier) │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • URL imports (https://deno.land/...) │
|
||||
│ • npm: specifiers (Deno 1.28+) │
|
||||
│ • Import maps for aliasing │
|
||||
│ • JSR registry packages │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 10. BunAnalyzer
|
||||
|
||||
**Ecosystem:** Bun / npm
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ BunAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ package.json │ Package manifest │ │
|
||||
│ │ bun.lockb │ Bun binary lockfile │ │
|
||||
│ │ bunfig.toml │ Bun configuration │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ PURL Format: │
|
||||
│ pkg:npm/hono@3.11.0 │
|
||||
│ pkg:npm/elysia@0.7.0 │
|
||||
│ │
|
||||
│ Special Handling: │
|
||||
│ • Binary lockfile parsing (bun.lockb) │
|
||||
│ • Workspace support │
|
||||
│ • Bun-specific packages │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 11. NativeAnalyzer
|
||||
|
||||
**Ecosystem:** Binary executables (ELF/PE/Mach-O)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ NativeAnalyzer │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ File Patterns: │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ELF binaries (no extension) │ Linux executables/libraries │ │
|
||||
│ │ *.so, *.so.* │ Linux shared libraries │ │
|
||||
│ │ *.exe, *.dll │ Windows binaries │ │
|
||||
│ │ *.dylib, Mach-O binaries │ macOS binaries │ │
|
||||
│ │ *.a, *.lib │ Static libraries │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Extraction Logic: │
|
||||
│ 1. Parse ELF/PE/Mach-O headers │
|
||||
│ 2. Extract Build-ID / CodeView GUID / UUID │
|
||||
│ 3. Parse dynamic linking sections │
|
||||
│ 4. Extract symbol tables (.dynsym, .symtab) │
|
||||
│ 5. Parse debug info (DWARF) if present │
|
||||
│ │
|
||||
│ Output: │
|
||||
│ pkg:generic/libssl.so.1.1?build-id=abc123... │
|
||||
│ pkg:generic/app?build-id=sha256:... │
|
||||
│ │
|
||||
│ Extracted Metadata: │
|
||||
│ • Linked libraries (DT_NEEDED, imports) │
|
||||
│ • Exported symbols │
|
||||
│ • Architecture (x86_64, arm64, etc.) │
|
||||
│ • Compiler identification │
|
||||
│ • Build-time options (PIE, RELRO, stack canary) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## OS/Distribution Analyzers (9)
|
||||
|
||||
### Linux Distributions
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ LINUX PACKAGE ANALYZERS │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ APKAnalyzer (Alpine) │ │
|
||||
│ │ │ │
|
||||
│ │ Database: /lib/apk/db/installed │ │
|
||||
│ │ │ │
|
||||
│ │ Version Format: 1.2.3-r4 │ │
|
||||
│ │ • 1.2.3 = upstream version │ │
|
||||
│ │ • r4 = Alpine revision │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:apk/alpine/openssl@1.1.1q-r0?distro=alpine-3.16 │ │
|
||||
│ │ │ │
|
||||
│ │ Special: Virtual packages, multi-arch support │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ DPKGAnalyzer (Debian/Ubuntu) │ │
|
||||
│ │ │ │
|
||||
│ │ Database: /var/lib/dpkg/status │ │
|
||||
│ │ │ │
|
||||
│ │ Version Format: [epoch:]upstream-debian │ │
|
||||
│ │ • epoch = optional numeric prefix (1:) │ │
|
||||
│ │ • upstream = original version │ │
|
||||
│ │ • debian = distro-specific revision │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:deb/debian/openssl@1.1.1n-0+deb11u3?distro=bullseye │ │
|
||||
│ │ │ │
|
||||
│ │ Special: Source packages, virtual packages, multi-arch │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ RPMAnalyzer (RHEL/Fedora/SUSE) │ │
|
||||
│ │ │ │
|
||||
│ │ Database: /var/lib/rpm/Packages (BerkeleyDB) │ │
|
||||
│ │ /var/lib/rpm/rpmdb.sqlite (SQLite, newer) │ │
|
||||
│ │ │ │
|
||||
│ │ Version Format: NEVRA (Name-Epoch:Version-Release.Arch) │ │
|
||||
│ │ • Epoch = numeric prefix (usually 0 or omitted) │ │
|
||||
│ │ • Version = upstream version │ │
|
||||
│ │ • Release = distro release + dist tag │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:rpm/redhat/openssl@1.1.1k-7.el8_6?arch=x86_64 │ │
|
||||
│ │ │ │
|
||||
│ │ Special: Epoch handling, dist tags, modular packages │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### macOS Analyzers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ macOS PACKAGE ANALYZERS │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ HomebrewAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Locations: │ │
|
||||
│ │ • /usr/local/Cellar/ (Intel) │ │
|
||||
│ │ • /opt/homebrew/Cellar/ (Apple Silicon) │ │
|
||||
│ │ │ │
|
||||
│ │ Detection: INSTALL_RECEIPT.json in formula directories │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:brew/openssl@1.1.1q │ │
|
||||
│ │ pkg:brew/homebrew/cask/docker@4.15.0 (casks) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ PkgutilAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Command: pkgutil --pkgs │ │
|
||||
│ │ Database: /var/db/receipts/ │ │
|
||||
│ │ │ │
|
||||
│ │ Detects: System packages, installer packages (.pkg) │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:macos/com.apple.pkg.CLTools_Executables@14.0.0 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ MacOsBundleAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ File: *.app/Contents/Info.plist │ │
|
||||
│ │ │ │
|
||||
│ │ Extracts: │ │
|
||||
│ │ • CFBundleIdentifier │ │
|
||||
│ │ • CFBundleShortVersionString │ │
|
||||
│ │ • CFBundleVersion │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:swift/com.apple.Safari@16.2 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Windows Analyzers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ WINDOWS PACKAGE ANALYZERS │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ChocolateyAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Location: C:\ProgramData\chocolatey\lib\ │ │
|
||||
│ │ │ │
|
||||
│ │ Detection: .nupkg files, .nuspec metadata │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:choco/7zip@22.01 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ MSIAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Registry: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ │ │
|
||||
│ │ Uninstall\ │ │
|
||||
│ │ │ │
|
||||
│ │ Detection: DisplayName, DisplayVersion, Publisher │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:msi/Microsoft Visual C++ 2019@14.29.30139 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ WinSxSAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Location: C:\Windows\WinSxS\Manifests\ │ │
|
||||
│ │ │ │
|
||||
│ │ Detection: Side-by-side assembly manifests │ │
|
||||
│ │ │ │
|
||||
│ │ Extracts: System assemblies, .NET Framework components │ │
|
||||
│ │ │ │
|
||||
│ │ PURL: pkg:winsxs/Microsoft.VC90.CRT@9.0.30729.1 │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Surface Analyzers (4)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ SURFACE ANALYZERS │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ FileSystemAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Detects: │ │
|
||||
│ │ • SUID/SGID binaries │ │
|
||||
│ │ • World-writable files/directories │ │
|
||||
│ │ • Capability-enhanced binaries (getcap) │ │
|
||||
│ │ • Symlink targets │ │
|
||||
│ │ • File permissions and ownership │ │
|
||||
│ │ │ │
|
||||
│ │ Output: property:fs/suid-binary, property:fs/world-writable │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ EnvironmentAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Sources: │ │
|
||||
│ │ • /etc/environment │ │
|
||||
│ │ • Shell profiles (.bashrc, .profile, .zshrc) │ │
|
||||
│ │ • Container ENV instructions (from image config) │ │
|
||||
│ │ │ │
|
||||
│ │ Detects: │ │
|
||||
│ │ • PATH entries │ │
|
||||
│ │ • LD_LIBRARY_PATH / LD_PRELOAD │ │
|
||||
│ │ • User context │ │
|
||||
│ │ • Locale settings │ │
|
||||
│ │ │ │
|
||||
│ │ Output: property:env/PATH, property:env/LD_PRELOAD │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SecretsAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Detection Patterns: │ │
|
||||
│ │ • API keys (AWS, GCP, Azure, GitHub, etc.) │ │
|
||||
│ │ • Private keys (RSA, ECDSA, Ed25519) │ │
|
||||
│ │ • Passwords in config files │ │
|
||||
│ │ • Connection strings │ │
|
||||
│ │ • JWT tokens │ │
|
||||
│ │ • OAuth secrets │ │
|
||||
│ │ │ │
|
||||
│ │ Output: finding:secret/aws-access-key, finding:secret/private-key│ │
|
||||
│ │ │ │
|
||||
│ │ Note: Findings are security alerts, not SBOM components │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ValidationAnalyzer │ │
|
||||
│ │ │ │
|
||||
│ │ Validates: │ │
|
||||
│ │ • SBOM completeness (all files accounted for) │ │
|
||||
│ │ • Hash verification (checksums match) │ │
|
||||
│ │ • Signature verification (if signed) │ │
|
||||
│ │ • Format compliance (CycloneDX/SPDX schema) │ │
|
||||
│ │ │ │
|
||||
│ │ Output: validation:sbom/complete, validation:sbom/verified │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Capability Analyzer
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ CAPABILITY DETECTOR │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ The CapabilityDetector analyzes code patterns to identify runtime │
|
||||
│ capabilities that affect security posture and reachability analysis. │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ DETECTED CAPABILITIES │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────┬────────────────────────────────────────┐ │ │
|
||||
│ │ │ Capability │ Detection Patterns │ │ │
|
||||
│ │ ├─────────────────┼────────────────────────────────────────┤ │ │
|
||||
│ │ │ Exec │ Process.Start, exec, spawn, fork │ │ │
|
||||
│ │ │ Network │ Socket, HttpClient, fetch, axios │ │ │
|
||||
│ │ │ Filesystem │ File.*, fs.*, open, read, write │ │ │
|
||||
│ │ │ Crypto │ Cipher, Hash, Sign, Verify │ │ │
|
||||
│ │ │ Database │ SqlConnection, MongoClient, Redis │ │ │
|
||||
│ │ │ DynamicCode │ eval, exec, compile, CodeDom │ │ │
|
||||
│ │ │ Reflection │ Type.GetMethod, Assembly.Load │ │ │
|
||||
│ │ │ NativeInterop │ DllImport, P/Invoke, FFI │ │ │
|
||||
│ │ │ Serialization │ JSON.parse, pickle, Marshal │ │ │
|
||||
│ │ │ MemoryUnsafe │ unsafe, pointer, IntPtr │ │ │
|
||||
│ │ └─────────────────┴────────────────────────────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Usage in Policy: │
|
||||
│ • Exec capability + CVE in child process → higher risk │
|
||||
│ • Network capability + CVE in HTTP library → exploitable remotely │
|
||||
│ • DynamicCode capability → increased attack surface │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Analyzer Pipeline Summary
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ COMPLETE ANALYZER INVENTORY │
|
||||
├───────────────────┬────────────────────┬───────────────────────┬────────────────────┤
|
||||
│ Category │ Analyzer │ Files/Sources │ PURL Type │
|
||||
├───────────────────┼────────────────────┼───────────────────────┼────────────────────┤
|
||||
│ Language (11) │ DotNetAnalyzer │ *.csproj, *.deps.json │ pkg:nuget │
|
||||
│ │ JavaAnalyzer │ pom.xml, *.jar │ pkg:maven │
|
||||
│ │ NodeAnalyzer │ package.json, *.lock │ pkg:npm │
|
||||
│ │ PythonAnalyzer │ requirements.txt │ pkg:pypi │
|
||||
│ │ GoAnalyzer │ go.mod, go.sum │ pkg:golang │
|
||||
│ │ RustAnalyzer │ Cargo.toml, *.lock │ pkg:cargo │
|
||||
│ │ PhpAnalyzer │ composer.json │ pkg:composer │
|
||||
│ │ RubyAnalyzer │ Gemfile, *.gemspec │ pkg:gem │
|
||||
│ │ DenoAnalyzer │ deno.json, deno.lock │ pkg:deno │
|
||||
│ │ BunAnalyzer │ bun.lockb │ pkg:npm │
|
||||
│ │ NativeAnalyzer │ ELF/PE/Mach-O │ pkg:generic │
|
||||
├───────────────────┼────────────────────┼───────────────────────┼────────────────────┤
|
||||
│ OS/Distro (9) │ APKAnalyzer │ /lib/apk/db/installed │ pkg:apk │
|
||||
│ │ DPKGAnalyzer │ /var/lib/dpkg/status │ pkg:deb │
|
||||
│ │ RPMAnalyzer │ /var/lib/rpm/ │ pkg:rpm │
|
||||
│ │ HomebrewAnalyzer │ /opt/homebrew/Cellar │ pkg:brew │
|
||||
│ │ PkgutilAnalyzer │ pkgutil --pkgs │ pkg:macos │
|
||||
│ │ MacOsBundleAnalyzer│ *.app/Info.plist │ pkg:swift │
|
||||
│ │ ChocolateyAnalyzer │ chocolatey/lib/ │ pkg:choco │
|
||||
│ │ MSIAnalyzer │ Registry │ pkg:msi │
|
||||
│ │ WinSxSAnalyzer │ WinSxS/Manifests/ │ pkg:winsxs │
|
||||
├───────────────────┼────────────────────┼───────────────────────┼────────────────────┤
|
||||
│ Surface (4) │ FileSystemAnalyzer │ File permissions │ property:fs │
|
||||
│ │ EnvironmentAnalyzer│ ENV, .profile │ property:env │
|
||||
│ │ SecretsAnalyzer │ Pattern matching │ finding:secret │
|
||||
│ │ ValidationAnalyzer │ SBOM validation │ validation:sbom │
|
||||
├───────────────────┼────────────────────┼───────────────────────┼────────────────────┤
|
||||
│ Capability (1) │ CapabilityDetector │ Code patterns │ capability:* │
|
||||
└───────────────────┴────────────────────┴───────────────────────┴────────────────────┘
|
||||
|
||||
Total: 25 Analyzers
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - How analyzers feed policy decisions
|
||||
- [Scanner Architecture](../../modules/scanner/architecture.md) - Scanner module dossier
|
||||
- [SBOM Generation Flow](../../flows/03-sbom-generation-flow.md) - End-to-end SBOM flow
|
||||
- [Data Schemas](../../11_DATA_SCHEMAS.md) - SBOM format specifications
|
||||
Reference in New Issue
Block a user