new advisories
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
2025-11-23 23:38:25 +02:00
parent c13355923f
commit 2de8d1784b
24 changed files with 443 additions and 17 deletions

View File

@@ -3,6 +3,7 @@
Objective
- Build a multi-runtime reachability corpus (Go/.NET/Python/Rust) with EXPECT.yaml ground truths and captured traces.
- Make fixtures CI-consumable to validate reachability scoring and VEX proofs continuously.
- Add public mini-dataset cases (PHP/JavaScript/C#) from advisory 23-Nov-2025 for ingestion/bench reuse.
Scope & deliverables
- Fixture layout: `tests/reachability/corpus/<language>/<case>/`
@@ -13,6 +14,17 @@ Scope & deliverables
- `vex.openvex.json` — expected VEX statement.
- CI integration: add corpus harness to `tests/reachability/StellaOps.Reachability.FixtureTests` to validate presence, schema, and determinism (hash manifest).
- Offline posture: all artifacts deterministic, no external downloads; hashes recorded in manifest.
- Public mini-dataset layout (PHP/JS/C#) to be mirrored under `tests/reachability/samples-public/`:
```
vuln-reach-dataset/
schema/ground-truth.schema.json
runners/run_all.sh
samples/
php/php-001-phar-deserialize/...
js/js-002-yaml-unsafe-load/...
csharp/cs-001-binaryformatter-deserialize/...
```
Each sample ships: minimal app, lockfile, SBOM (CycloneDX JSON), VEX, ground truth (EXPECT/JSON), repro script.
MVP slice (proposed)
- Go: `go-ssh-CVE-2020-9283-keyexchange`

View File

@@ -46,6 +46,16 @@ Purpose: define the canonical fields for reachability graph nodes/edges, runtime
}
```
## 2.5 Attestation levels (hybrid default)
- **Graph DSSE (required):** one DSSE envelope over the canonical graph JSON (sorted arrays/keys) with `graph_hash` = BLAKE3 of body; Rekor publish always (or mirror when offline).
- **Edge-bundle DSSE (optional):** batches of ≤512 edges, emitted only for high-signal cases (`runtime`, `init_array`/TLS roots, contested/third-party edges). Each bundle carries `graph_hash`, `bundle_reason`, per-edge `reason`, `symbol_digest`, `purl`, `confidence`, and optional `revoked=true` for quarantine. Rekor publish is configurable; CAS storage is mandatory.
- CAS layout additions:
- Graph body: `cas://reachability/graphs/{blake3}`
- Graph DSSE: `cas://reachability/graphs/{blake3}.dsse`
- Edge bundle: `cas://reachability/edges/{graph_hash}/{bundle_id}` + `.dsse`
- Determinism: bundle ordering by `(bundle_reason, edge_id)`; arrays sorted before hashing.
## 3. Runtime facts (Signals ingestion)
Fields per NDJSON event:
@@ -69,6 +79,7 @@ Unknowns must include `unknown_type`, `scope`, `provenance`, `confidence.p`, and
- Graphs: `cas://reachability/graphs/{blake3}` (canonical JSON, sorted keys/arrays)
- Runtime traces: `cas://reachability/runtime/{sha256}`
- Unknowns evidence (optional large blobs): `cas://unknowns/{sha256}`
- Edge bundles: `cas://reachability/edges/{graph_hash}/{bundle_id}` (JSON + `.dsse`)
Metadata for each CAS object: `{ schema: "richgraph-v1", analyzer: {name,version}, createdAtUtc, toolchain_digest }`. When analyzer metadata is supplied at ingest (Signals OpenAPI), persist it alongside parsed analyzer fields from the artifact.
@@ -78,6 +89,8 @@ Metadata for each CAS object: `{ schema: "richgraph-v1", analyzer: {name,version
- If `build_id` present, `symbol_id` and `code_id` must store it; if absent, record `build_id_source: "FileHash"`.
- Evidence arrays sorted; confidence in [0,1].
- Roots must include load-time constructors when present.
- When `edge_bundles` are present, each edge in a bundle must also exist in the graph edge set; `revoked=true` bundles override graph edges for policy/scoring.
- Graph DSSE is mandatory per scan; edge-bundle DSSEs are optional but must reference `graph_hash` and `bundle_id`.
## 7. Acceptance checklist

View File

@@ -0,0 +1,55 @@
# Hybrid Reachability Attestation (Graph + Edge-Bundle)
> Decision date: 2025-11-23 · Owners: Scanner Guild, Attestor Guild, Signals Guild, Policy Guild
## 1. Purpose
- Guarantee replayable, signed reachability evidence with **graph-level DSSE** for every scan while enabling **selective edge-level DSSE bundles** when finer provenance or dispute handling is required.
- Keep CI/offline bundles lean (graph-first), but allow auditors/regulators to quarantine or prove individual edges without regenerating whole graphs.
## 2. Attestation levels
- **Level 0 (Graph DSSE) — Required**
- Payload: canonical `richgraph-v1` (nodes, edges, roots, graph_hash, analyzer metadata, policy_hash).
- Signature: one DSSE envelope per graph; submit digest to Rekor (or mirror) always.
- CAS: `cas://reachability/graphs/{blake3}` (body) + `cas://reachability/graphs/{blake3}.dsse` (envelope).
- **Level 1 (Edge-Bundle DSSE) — Optional/Selective**
- Payload: batch of edges (size ≤ 512) with per-edge reason, evidence hashes, `symbol_digest`, `purl`, `confidence`, and `phase`.
- Criteria to emit bundles:
- Edge reason is `runtime`, `init_array`/constructors/TLS callbacks, or comes from third-party provenance.
- Edge is contested/flagged in Unknowns registry or under policy quarantine.
- Signature: one DSSE envelope per bundle; Rekor submission **configurable** (default on for contested/high-risk bundles, off for bulk benign bundles in sealed mode).
- CAS: `cas://reachability/edges/{graph_hash}/{bundle_id}` JSON + `.../{bundle_id}.dsse`.
## 3. Producer responsibilities
- **Scanner**
- Always emit Level 0 graph + manifest.
- When criteria match, emit Level 1 bundles; include `bundle_reason` (e.g., `runtime-hit`, `init-root`, `third-party`, `disputed`).
- Canonicalise JSON (sorted keys/arrays) before hashing; BLAKE3 as graph hash, SHA-256 inside bundles.
- **Attestor/Signer**
- Apply DSSE for both levels; respect sovereign crypto modes (FIPS/GOST/SM/PQC) from environment.
- Rekor: push graph envelope digests; push edge-bundle digests only when `rekor_publish=true` (policy/default for high-risk bundles).
## 4. Consumer responsibilities
- **Signals**
- Ingest graph DSSE as the canonical source; ingest edge-bundles when present and attach to the same `graph_hash`.
- Store per-edge DSSE metadata for quarantine/override flows; surface missing edges as Unknowns only when absent from both graph and bundles.
- **Policy**
- Default trust path: graph DSSE + CAS object.
- When an edge is quarantined/contested, drop it from consideration if an edge-bundle DSSE marks it `revoked=true` or if the Unknowns registry lists it with policy quarantine flag.
- For “evidence-required” rules, require either (a) graph DSSE + policy_hash match **or** (b) edge-bundle DSSE that covers the vulnerable path edges.
- **Replay/Bench/CLI**
- `stella graph verify` should accept `--graph {hash}` and optional `--edge-bundles` to validate deeper provenance offline.
## 5. Verification and quarantine flows
- **Happy path**: verify graph DSSE → verify Rekor inclusion (or mirror) → hash graph body → match `graph_hash` in policy/replay manifest → accept.
- **Dispute/quarantine**: mark specific `edge_id` as `revoked` in an edge-bundle DSSE; Policy/Signals exclude it, recompute reachability, and surface delta in explainers.
- **Offline**: retain graph DSSE and selected edge-bundles inside replay pack; Rekor proofs cached when available.
## 6. Performance & storage guardrails
- Default: only graph DSSE is mandatory; edge-bundles capped at 512 edges per envelope and emitted only on criteria above.
- Rekor flood control: cap edge-bundle Rekor submissions per graph (config `reachability.edgeBundles.maxRekorPublishes`, default 5). Others stay CAS-only.
- Determinism: bundle ordering = stable sort by `(bundle_reason, edge_id)`; hash before signing.
## 7. Open decisions (tracked in Sprint 0401 tasks 5356)
- Rekor publish defaults per deployment tier (regulated vs standard).
- CLI UX for selective bundle verification.
- Bench coverage for edge-bundle verification time/size.

78
docs/reachability/lead.md Normal file
View File

@@ -0,0 +1,78 @@
# Deterministic Reachability — Product Moat (Nov 2025)
Source: internal advisory “23-Nov-2025 - Where StellaOps Can Truly Lead”. Supersedes/extends archived binary reachability advisories (18-Nov-2025 - Binary-Reachability-Engine, Encoding Binary Reachability with PURL-Resolved Edges, CSharp-Binary-Analyzer). This page is the canonical, high-level articulation of our reachability moat for architects, PMM, and field teams. Detailed schemas live in `docs/reachability/evidence-schema.md` and `docs/reachability/hybrid-attestation.md`.
## Why it matters
- Most scanners list every CVE; reachability asks whether vulnerable code is actually callable.
- Competitors infer paths and rarely sign evidence; we **prove** paths with deterministic graphs and attestations.
- Outcome targets: ≥40% fewer noisy vulns shown; ≥25% faster triage via explainable “why” paths.
## Moat elements
1) **Deterministic call-graphs per artifact**
- Stable node IDs: `purl@version!build-id!symbol-signature` (or code offset when stripped).
- Stable edge IDs: `SHA256(nodeA||nodeB||tool-version||inputs-hash)`.
- Graph hash: BLAKE3 over canonical JSON; locked by manifest.
2) **Signed evidence**
- Graph-level DSSE for every scan (mandatory).
- Optional edge-bundle DSSE (≤512 edges) for runtime/init/contested edges; Rekor publish capped. See `docs/reachability/hybrid-attestation.md`.
3) **Explainability**
- Each finding carries call-chain + per-edge reason + VEX gate decision + layer attribution.
4) **Container layer provenance**
- Track file-to-layer mapping; show “introduced in layer X from base Y”.
5) **Replayability**
- Determinism manifest locks feeds, toolchain hashes, analyzer flags; replay yields identical graph and attestations.
## Minimal architecture slice
- **Sbomer/Scanner**: emit SBOM + symbol maps + per-layer file index; capture Build-IDs.
- **Cartographer**: build deterministic call-graphs (language + native), output `EdgeList.jsonl` with stable IDs.
- **Attestor**: wrap graph (and edge bundles when emitted) into DSSE; log digests to Rekor/mirror.
- **Vexer/Policy**: evaluate lattice, produce OpenVEX with linked edge proofs.
- **Ledger**: retain manifests and DSSE; mirror to Rekor where allowed.
## Practical spec (condensed)
- **Node fields**: `symbol_id`, `code_id`, `purl`, `build_id`, `symbol_digest`, `lang`, `evidence[]`.
- **Edge fields**: `from`, `to`, `kind` (direct|plt|runtime|init), `purl`, `symbol_digest`, `reason`, `confidence`, `evidence[]`.
- **Roots**: exports, entrypoints, **.init_array/.ctors/TLS callbacks**, plugin hooks.
- **Attestation layout**:
- Graph: `cas://reachability/graphs/{blake3}` + `{blake3}.dsse` (Rekor always).
- Edge bundle: `cas://reachability/edges/{graph_hash}/{bundle_id}[.dsse]` (Rekor optional, capped).
### Example: Edge-bundle DSSE payload (abridged)
```json
{
"graph_hash": "blake3:...",
"bundle_reason": "runtime-hit",
"edges": [{
"edge_id": "sha256:...",
"from": "sym:...caller",
"to": "sym:...callee",
"reason": "plt",
"purl": "pkg:deb/openssl@3.0.2?arch=amd64",
"symbol_digest": "sha256:...",
"revoked": false
}]
}
```
### Field cheat sheet (for sprint readers)
- `graph_hash` — BLAKE3 of canonical graph JSON.
- `bundle_reason``runtime-hit | init-root | contested | third-party`.
- `edge_id` — sha256(from||to||reason||tool-version||inputs-hash).
- `revoked` — when true, policy/Signals must drop this edge before reachability scoring.
- `purl` + `symbol_digest` — bind edge to SBOM component and callee identity.
## Quick wins (ship order)
1) Capture Build-IDs in Scanner and thread into `symbol_id`/`code_id`.
2) Emit Graph Determinism Manifest (feeds + toolchain hashes) per scan.
3) Turn on edge-bundle DSSE for runtime/init edges first; keep Rekor cap low.
4) Surface “why path” + layer attribution in CLI/UI explainers.
## APIs (strawman)
- `POST /graph/edges: attest` — idempotent; same inputs → same edge IDs.
- `GET /findings/:id/proof` — returns call-chain + Rekor inclusion proofs.
- `GET /vex/:artifact` — streams OpenVEX with embedded proofs.
## Links
- Advisory source: `docs/product-advisories/23-Nov-2025 - Where StellaOps Can Truly Lead.md`
- Schemas: `docs/reachability/evidence-schema.md`, `docs/reachability/hybrid-attestation.md`
- Sprint tracking: `docs/implplan/SPRINT_0401_0001_0001_reachability_evidence_chain.md`