save progress
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
Here’s a simple way to make vulnerability triage almost noise‑free: combine **static SBOM call‑graph pruning** with **runtime reachability hints** before making a VEX decision.
|
||||
|
||||
---
|
||||
|
||||
# Why this matters (plain English)
|
||||
|
||||
* Static scanners flag lots of CVEs that your app never calls.
|
||||
* Runtimes (traces, signals) know what actually executed.
|
||||
* Merging the two yields “only the CVEs that matter,” so your VEX is credible and quiet.
|
||||
|
||||
---
|
||||
|
||||
# The hybrid model (static → dynamic → VEX)
|
||||
|
||||
1. **Static stage (Sbomer + Feedser assist)**
|
||||
|
||||
* Build SBOM (CycloneDX/SPDX).
|
||||
* Generate a **per‑package call graph** (library → functions → entrypoints).
|
||||
* Compute a **pruned reachable set** using import graphs, symbol tables, and package metadata.
|
||||
* Output: `reachability_static.json` (component → callable IDs).
|
||||
|
||||
2. **Dynamic stage (Signals + Scheduler traces)**
|
||||
|
||||
* Ingest **runtime traces** (e.g., eBPF/ETW/CLR Profiler/JFR) from Scheduler‑managed jobs.
|
||||
* Normalize to **reachability vectors**: `(component, symbol, freq, last_seen, context)`.
|
||||
* Output: `reachability_runtime.json`.
|
||||
|
||||
3. **Decision stage (Vexer)**
|
||||
|
||||
* For each CVE → vulnerable symbols (from advisories/OSVs, delta‑sigs if available).
|
||||
* If vulnerable symbol ∉ static set → **Not Affected (NA: not reachable)**.
|
||||
* If ∈ static but ∉ runtime → **Under Investigation / Likely NA** (confidence < 1).
|
||||
* If ∈ runtime → **Affected** with confidence and evidence URIs.
|
||||
* Emit **VEX** entries with justification (`not_provided_code_path`, `requires_config`, `fixed`, etc.) and confidence scores.
|
||||
|
||||
---
|
||||
|
||||
# Minimal PoC plan (2 weeks of evening work)
|
||||
|
||||
**Goal:** Let **Vexer** import runtime reachability vectors from **Scheduler** traces and use them to gate VEX verdicts.
|
||||
|
||||
### 0) Contracts (day 1)
|
||||
|
||||
* **Schema:**
|
||||
|
||||
* `reachability_static.jsonl`: `{ component, version, symbols:[...] }`
|
||||
* `reachability_runtime.jsonl`: `{ component, symbol, last_seen, count, context:{pid, container, route}}`
|
||||
* **Evidence URIs:** `stella://signals/<trace-id>#symbol=<name>`
|
||||
|
||||
### 1) Static extractor (days 2–4)
|
||||
|
||||
* Sbomer plugin: emit **symbol list + call graph** per artifact.
|
||||
* Start with **.NET**: use Roslyn/IL metadata to map `assembly → type → method`.
|
||||
* Heuristic fallbacks for native: ELF/PE export tables.
|
||||
|
||||
### 2) Runtime collector (days 3–6)
|
||||
|
||||
* Signals module:
|
||||
|
||||
* .NET CLR Profiler or EventPipe→method enter/leave (sampling ok).
|
||||
* Map back to `(assembly, type, method)` + container tags.
|
||||
* Scheduler: batch traces into **reachability vectors** and push to **Router**.
|
||||
|
||||
### 3) Vexer importer (days 6–8)
|
||||
|
||||
* New `Vexer.Reachability` package:
|
||||
|
||||
* Merge static + runtime with **component coordinate normalization** (purl).
|
||||
* `bool IsRuntimeReachable(component, symbol)`; `ReachabilityScore 0..1`.
|
||||
|
||||
### 4) VEX decision filter (days 8–10)
|
||||
|
||||
* For each CVE advisory record (from Feedser): vulnerable symbols → lookup.
|
||||
* Decision table:
|
||||
|
||||
* `Runtime=1` → **Affected (A)**.
|
||||
* `Static=1, Runtime=0` → **NA (Not reachable) with low confidence** unless policy overrides.
|
||||
* `Static=0` → **NA (No code path)**.
|
||||
* Emit CycloneDX VEX or CSAF with **justifications + evidence links**.
|
||||
|
||||
### 5) UI & Ops (days 10–14)
|
||||
|
||||
* **Stella UI:** badge per CVE: `Affected / NA / Probable NA`, hover shows symbols and last‑seen.
|
||||
* **Policy Engine:** org rules like “treat Probable NA as NA after 14 days of runtime with p95 traffic.”
|
||||
* **Notify:** only alert on `Affected` or `Probable NA → A` transitions.
|
||||
|
||||
---
|
||||
|
||||
# Data model & code stubs (illustrative)
|
||||
|
||||
**Vexer reachability interface**
|
||||
|
||||
```csharp
|
||||
public record SymbolRef(string Purl, string Assembly, string Type, string Method);
|
||||
|
||||
public interface IReachabilityIndex {
|
||||
bool InStatic(SymbolRef s);
|
||||
bool InRuntime(SymbolRef s, TimeSpan since, out int count);
|
||||
double Score(SymbolRef s); // 0..1 weighted by freq/recency
|
||||
}
|
||||
```
|
||||
|
||||
**Decision kernel**
|
||||
|
||||
```csharp
|
||||
VexVerdict Decide(Cve cve, IEnumerable<SymbolRef> vulnSyms, IReachabilityIndex idx) {
|
||||
var anyRuntime = vulnSyms.Any(s => idx.InRuntime(s, TimeSpan.FromDays(14), out _));
|
||||
var anyStatic = vulnSyms.Any(s => idx.InStatic(s));
|
||||
|
||||
return anyRuntime ? VexVerdict.Affected
|
||||
: anyStatic ? VexVerdict.ProbableNotAffected // gated by policy window
|
||||
: VexVerdict.NotAffected;
|
||||
}
|
||||
```
|
||||
|
||||
**Evidence snippet in VEX (CycloneDX)**
|
||||
|
||||
```json
|
||||
{
|
||||
"vulnerability": { "id": "CVE-2025-12345" },
|
||||
"analysis": {
|
||||
"state": "not_affected",
|
||||
"justification": "Vulnerable_code_not_in_execute_path",
|
||||
"response": [ "will_not_fix" ],
|
||||
"detail": "Symbols present but not executed across 14d p95 traffic",
|
||||
"evidence": [
|
||||
"stella://signals/trace-9f12#symbol=Contoso.Crypto.Rsa::Sign"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Where it plugs into Stella Ops
|
||||
|
||||
* **Sbomer**: adds call‑graph/symbol export plugin.
|
||||
* **Signals**: runtime tracer + compressor → reachability vectors.
|
||||
* **Scheduler**: tags traces by job/tenant/env; hands them to Router.
|
||||
* **Vexer**: new Reachability importer + decision filter.
|
||||
* **Feedser**: enriches CVEs with symbol hints (from OSV, delta‑sigs).
|
||||
* **Policy Engine**: organization rules for confidence windows.
|
||||
* **Notify/UI/Timeline**: surface verdicts, evidence, and flips over time.
|
||||
|
||||
---
|
||||
|
||||
# Guardrails & edge cases
|
||||
|
||||
* **Backports:** pair with your existing *binary‑delta signatures* so “fixed but looks vulnerable” becomes **NA (fixed by backport)** even if symbol name matches.
|
||||
* **Lazy paths & feature flags:** allow **context filters** (route, tenant, env) before declaring NA.
|
||||
* **Air‑gapped:** ship traces via offline bundle (`*.signals.zip`) and replay.
|
||||
|
||||
---
|
||||
|
||||
# Next steps I can do now
|
||||
|
||||
1. Draft the JSON schemas + purl mapping table.
|
||||
2. Add the `Vexer.Reachability` package and wire the decision filter.
|
||||
3. Provide a tiny sample repo (toy service + vulnerable lib) to demo **A → Probable NA → NA** as traffic evolves.
|
||||
|
||||
If you want, I’ll generate the initial schemas and a .NET tracer checklist so you can drop them into `docs/modules/`.
|
||||
Reference in New Issue
Block a user