chore(sprints): archive 20260226 advisories and expand deterministic tests
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
I’m sharing this because the current state of **OCI referrers support across major container registries** is finally *messy, uneven, and directly impacts how you implement supply‑chain artifact workflows* — which is exactly the sort of rollout gotcha worth locking down before production.
|
||||
|
||||
---
|
||||
|
||||
<img src="https://opencontainers.org/img/logo-og.png" alt="OCI Logo" width="300">
|
||||
|
||||
**OCI Referrers API and Distribution Spec** — the *official* mechanism to list related artifacts by subject (digest) — is part of OCI Distribution 1.1, and spec text now clarifies fallback behavior when referrers aren’t supported (registries SHOULD return 200 on supported referrers calls; 404 or fallback tag otherwise). ([Open Container Initiative][1])
|
||||
|
||||
---
|
||||
|
||||
### GitHub Container Registry (GHCR) — Lack of referrers
|
||||
|
||||
* GHCR implements OCI image formats, but **does not support the OCI referrers API endpoint** for generic discovery of artifacts by subject.
|
||||
* Community threads confirm queries against `/v2/<name>/referrers/<digest>` simply *don’t work* — referrers don’t show up despite manifests being present. ([GitHub][2])
|
||||
* The practical implication: you **must use GitHub’s specific Attestations/Policy APIs** or fetch artifacts by *known SHA* if you need to extract provenance generically across registries.
|
||||
|
||||
---
|
||||
|
||||
### AWS Elastic Container Registry (ECR) — OCI 1.1 support
|
||||
|
||||
* AWS has documented support for the OCI Image & Distribution 1.1 specs, including image referrers, SBOMs, signatures, and non‑image artifact distribution. ([Amazon Web Services, Inc.][3])
|
||||
* This means OCI‑aware clients (ORAS, containerd tooling) should be able to list and pull referrers by digest.
|
||||
* Because referrers count toward storage and lifecycle policies, you must **include these artifact patterns explicitly in lifecycle/GC rules** to avoid unintended deletions.
|
||||
|
||||
---
|
||||
|
||||
### Google Artifact Registry — attachments + listing
|
||||
|
||||
* Google’s **Artifact Registry** doesn’t expose a native OCI referrers API, but instead provides an **attachments model** for metadata (SBOMs, provenance) tied to an artifact.
|
||||
* You can list attachments with `gcloud artifacts attachments list` and via console UI — this acts as a *referrers‑like* listing UX, not necessarily the standard OCI endpoint. ([Google Cloud Documentation][4])
|
||||
* IAM roles (`artifactregistry.reader/writer/repoAdmin`) govern access, and some features are in **public preview**, especially for non‑Docker formats.
|
||||
|
||||
---
|
||||
|
||||
### Red Hat Quay / Quay.io — OCI referrers implemented
|
||||
|
||||
* Quay has publicly announced support for the **OCI Referrers API**, enabling clients to query relationships by subject and artifactType. ([Red Hat][5])
|
||||
* This aligns them with OCI 1.1 workflows and enables structured discovery of SBOMs/signatures via the native API.
|
||||
* Watch for deployment flags or admin toggles that control this feature — misconfiguration can make discovery inconsistent.
|
||||
|
||||
---
|
||||
|
||||
### Harbor (goharbor) — evolving but partial
|
||||
|
||||
* Harbor’s backend can *store OCI artifacts*, but its implementation of referrers has historically lagged UI classification: cosign or SBOM referrers may be accepted at the API level while displayed as “UNKNOWN” in UI. ([GitHub][6])
|
||||
* Active work overall is on **improving OCI 1.1 support**, but **UI behavior and mediaType classification may still lag the API capabilities** in releases around v2.15+.
|
||||
|
||||
---
|
||||
|
||||
### Spec & ecosystem nuance (broad patterns)
|
||||
|
||||
* OCI Distribution 1.1 spec updates explicitly require registries that *support* referrers to return successful responses for referrers endpoints; otherwise clients should *fall back* to tag‑by‑digest conventions. ([Open Container Initiative][1])
|
||||
* Because referrers support is optional and not universal yet, **generic clients must detect support at runtime** and fallback where needed (e.g., use ORAS discovery`oras discover --distribution-spec v1.1-referrers-api`). ([Google Cloud Documentation][4])
|
||||
* Many registries (e.g., Docker Hub, GitLab) can store OCI artifacts with `subject` fields, *but won’t expose them via a referrers endpoint* — making discovery tooling reliant on owner‑specific APIs or naming conventions. ([GitLab Docs][7])
|
||||
|
||||
---
|
||||
|
||||
The bottom line is that **registry choice still shapes your artifact discovery strategy** — and until OCI Referrers becomes widely implemented, robust implementations need *fallback tagging, dual discovery flows, SCM‑specific API calls, and careful lifecycle/permission planning*.
|
||||
|
||||
Let me know if you want a **compact matrix or scriptable detection and fallback strategy** tailored for vendors like ECR, GHCR, GCR/Artifact Registry, Quay, and Harbor.
|
||||
|
||||
[1]: https://opencontainers.org/posts/blog/2024-03-13-image-and-distribution-1-1/?utm_source=chatgpt.com "OCI Image and Distribution Specs v1.1 Releases"
|
||||
[2]: https://github.com/orgs/community/discussions/163029?utm_source=chatgpt.com "How do I find the provenance which is pushed to ghcr.io ..."
|
||||
[3]: https://aws.amazon.com/blogs/opensource/diving-into-oci-image-and-distribution-1-1-support-in-amazon-ecr/?utm_source=chatgpt.com "Diving into OCI Image and Distribution 1.1 Support in ..."
|
||||
[4]: https://docs.cloud.google.com/artifact-registry/docs/manage-metadata-with-attachments?utm_source=chatgpt.com "Manage artifact metadata | Artifact Registry"
|
||||
[5]: https://www.redhat.com/en/blog/announcing-open-container-initiativereferrers-api-quayio-step-towards-enhanced-security-and-compliance?utm_source=chatgpt.com "Announcing the Open Container InitiativeReferrers API on ..."
|
||||
[6]: https://github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor?utm_source=chatgpt.com "Architecture Overview of Harbor · goharbor/harbor Wiki"
|
||||
[7]: https://docs.gitlab.com/user/packages/container_registry/?utm_source=chatgpt.com "GitLab container registry"
|
||||
@@ -0,0 +1,231 @@
|
||||
Here’s a compact, end‑to‑end blueprint for making your SBOM evidence verifiable and auditable from build → attest → publish → verify → runtime, using only official specs/CLIs (CycloneDX, DSSE/in‑toto, cosign, Rekor v2), plus deterministic VEX and micro‑witness joins.
|
||||
|
||||
---
|
||||
|
||||
# Why this matters (quick primer)
|
||||
|
||||
* **SBOM** (software bill of materials) says what’s inside an artifact.
|
||||
* **DSSE / in‑toto** wraps evidence in a tamper‑evident envelope.
|
||||
* **cosign** signs/verifies those envelopes.
|
||||
* **Rekor (transparency log)** proves *when/what* was published.
|
||||
* **VEX** states whether known CVEs affect your artifact.
|
||||
* **Micro‑witnesses** are runtime breadcrumbs you can join back to SBOM/VEX for triage.
|
||||
|
||||
---
|
||||
|
||||
# NOW (MVP you can ship immediately)
|
||||
|
||||
**Goal:** Minimal, reproducible spine with canonical SBOMs, signed attestations, Rekor v2 anchoring, and deterministic VEX ingestion.
|
||||
|
||||
### Canonical SBOM & ID
|
||||
|
||||
1. Emit CycloneDX v1.7 JSON.
|
||||
2. Canonicalize via JSON‑JCS → `canonical_id := sha256(JCS(sbom.json))`.
|
||||
|
||||
### DSSE attestation (SBOM predicate)
|
||||
|
||||
* Wrap CycloneDX content (or pointer) in an **in‑toto Statement**.
|
||||
* `subject[0].digest.sha256 == canonical_id`.
|
||||
* Sign with cosign (**DSSE mode**).
|
||||
* Capture Rekor v2 tile pointer / entry id and embed it in predicate metadata.
|
||||
|
||||
### Rekor v2 anchoring
|
||||
|
||||
* cosign publish creates the log entry.
|
||||
* Store the **tile URL** and **entry id** in your artifact record.
|
||||
|
||||
### Deterministic VEX ingestion (OpenVEX & CycloneDX VEX)
|
||||
|
||||
* Ingest OpenVEX or CycloneDX VEX, map to a **canonical CycloneDX VEX** form.
|
||||
* Apply strict merge rules (source priority, timestamp, exact `canonical_id` target).
|
||||
|
||||
### CI assertions (must‑pass)
|
||||
|
||||
* **Unit:** `cyclonedx-cli validate ./bom.json && jcs_canonicalize ./bom.json | sha256sum` → equals expected `canonical_id`.
|
||||
* **Integration:**
|
||||
`cosign attest --predicate predicate.json --key cosign.key <subject-ref>`
|
||||
`cosign verify-attestation --key <pubkey> --type in-toto <subject-ref>`
|
||||
Rekor proof: `rekor-cli tile get --entry <entry_id>` (or v2 tiles client) → inclusion proof valid.
|
||||
* **VEX mapping:** jsonschema validate; assert `vulnerabilities[].analysis.state` and target match `canonical_id`.
|
||||
|
||||
---
|
||||
|
||||
# LATER (scale/hardening)
|
||||
|
||||
* Rekor v2 **tile batching** & multi‑tile reconciliation.
|
||||
* **Signed micro‑witness aggregation** service.
|
||||
* **Deterministic replay** harness (nightly) for large volumes.
|
||||
* Predicate **schema registry** (stable `predicateType` URIs, semver).
|
||||
|
||||
---
|
||||
|
||||
# Flow A: Build‑time SBOM + Attestation Anchor (end‑to‑end)
|
||||
|
||||
1. **Producer:**
|
||||
|
||||
* CycloneDX v1.7 → validate: `cyclonedx-cli validate ./bom.json`.
|
||||
* JCS canonicalize → `canonical_id = sha256(canonical_bytes)`.
|
||||
|
||||
2. **Predicate:**
|
||||
|
||||
* in‑toto Statement (`predicateType = https://stella.example/predicate/sbom.v1` or SLSA provenance).
|
||||
* `subject = [{"name":"artifact","digest":{"sha256":"<canonical_id>"}}]`.
|
||||
* `predicate` contains CycloneDX JCS content (or immutable pointer if too large).
|
||||
|
||||
3. **Sign & anchor:**
|
||||
|
||||
* `cosign attest --predicate predicate.json --key cosign.key <subject-ref>`.
|
||||
* Capture Rekor **tile URL** and **entry_id**; persist inside predicate metadata.
|
||||
|
||||
4. **Verify:**
|
||||
|
||||
* Fetch referrers (OCI Referrers 1.1), extract DSSE.
|
||||
* `cosign verify-attestation --key <pubkey> --type in-toto <subject-ref>`.
|
||||
* Recompute `sha256(JCS(sbom.json))` == `subject.digest.sha256`.
|
||||
* Validate Rekor v2 inclusion proof (tile check).
|
||||
|
||||
---
|
||||
|
||||
# Flow B: VEX → Apply → Runtime Micro‑witness Join
|
||||
|
||||
1. **VEX provider:** Publish **OpenVEX** or **CycloneDX VEX**; DSSE‑sign; optionally anchor in Rekor.
|
||||
|
||||
2. **Ingest & map:** OpenVEX → canonical CycloneDX VEX; store DSSE + `rekor_tile` + provenance to original feed.
|
||||
|
||||
3. **Runtime micro‑witness:**
|
||||
|
||||
* When observing a frame (`pc → build_id → symbol`), emit **DSSE micro‑witness predicate** referencing:
|
||||
|
||||
* `subject.canonical_id`
|
||||
* symbol bundle (OCI referrer, `mediaType=application/vnd.stella.symbols+tar`)
|
||||
* `replay_token` (points to deterministic replay inputs)
|
||||
* Sign & anchor to Rekor v2.
|
||||
|
||||
4. **Correlate:** Join micro‑witness DSSE with VEX:
|
||||
|
||||
* If `canonical_id` has `not_affected` for CVE X → auto‑suppress triage.
|
||||
* Else surface evidence and export both DSSEs + Rekor tiles in an **audit pack**.
|
||||
|
||||
---
|
||||
|
||||
# Minimal, unambiguous schemas
|
||||
|
||||
**1) Artifact canonical record**
|
||||
|
||||
```json
|
||||
{"canonical_id":"sha256:<hex>","format":"cyclonedx-jcs:1",
|
||||
"sbom_ref":"oci://registry/repo@sha256:<digest>|object-store://bucket/path",
|
||||
"attestations":[{"type":"in-toto","dsse_b64":"<base64>","rekor_tile":"<url>","entry_id":"<id>"}],
|
||||
"referrers":[{"mediaType":"application/vnd.stella.symbols+tar","descriptor_digest":"sha256:<digest>","registry":"ghcr.io/org/repo"}],
|
||||
"vex_refs":[{"type":"openvex","dsse_b64":"<base64>","rekor_tile":"<url>"}]}
|
||||
```
|
||||
|
||||
**2) Minimal DSSE / in‑toto predicate (for SBOM)**
|
||||
|
||||
```json
|
||||
{"_type":"https://in-toto.io/Statement/v0.1",
|
||||
"subject":[{"name":"artifact","digest":{"sha256":"<canonical_id>"}}],
|
||||
"predicateType":"https://stella.example/predicate/sbom.v1",
|
||||
"predicate":{"bom_format":"cyclonedx-jcs:1","bom":"<base64-or-pointer>",
|
||||
"producer":{"name":"ci-service","kid":"<signer-kid>"},
|
||||
"timestamp":"2026-02-19T12:34:56Z",
|
||||
"rekor_tile":"https://rekor.example/tiles/<tile>#<entry>"}}
|
||||
```
|
||||
|
||||
**3) OpenVEX → CycloneDX VEX mapping (sample OpenVEX)**
|
||||
|
||||
```json
|
||||
{"vexVersion":"1.0.0","id":"vex-123",
|
||||
"statements":[{"vulnerability":"CVE-2025-0001",
|
||||
"product":"pkg:maven/org/example@1.2.3",
|
||||
"status":"not_affected","justification":"code_not_present",
|
||||
"timestamp":"2026-02-19T12:00:00Z","provider":{"name":"vendor"}}]}
|
||||
```
|
||||
|
||||
**CycloneDX SBOM (trimmed example)**
|
||||
|
||||
```json
|
||||
{"bomFormat":"CycloneDX","specVersion":"1.7",
|
||||
"components":[{"bom-ref":"pkg:maven/org/example@1.2.3",
|
||||
"type":"library","name":"example","version":"1.2.3",
|
||||
"purl":"pkg:maven/org/example@1.2.3"}]}
|
||||
```
|
||||
|
||||
**DSSE envelope (shape)**
|
||||
|
||||
```json
|
||||
{"payloadType":"application/vnd.in-toto+json",
|
||||
"payload":"<base64-of-predicate.json>",
|
||||
"signatures":[{"keyid":"cosign:ecdsa-1","sig":"<base64>"}]}
|
||||
```
|
||||
|
||||
**Micro‑witness predicate (sample)**
|
||||
|
||||
```json
|
||||
{"predicateType":"https://stella.example/micro-witness.v1",
|
||||
"subject":[{"name":"artifact","digest":{"sha256":"<canonical_id>"}}],
|
||||
"predicate":{"trace_id":"trace-abc",
|
||||
"frames":[{"pc":"0x400123","build_id":"<buildid>","symbol":"main","offset":123}],
|
||||
"symbol_refs":[{"type":"oci-ref","ref":"ghcr.io/org/repo@sha256:<digest>",
|
||||
"mediaType":"application/vnd.stella.symbols+tar"}],
|
||||
"replay_token":"s3://bucket/replays/trace-abc.json",
|
||||
"timestamp":"2026-02-19T12:40:00Z"}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# CI: authoritative checks (copy‑pasteable)
|
||||
|
||||
**Unit (canonicalization):**
|
||||
|
||||
```bash
|
||||
cyclonedx-cli validate ./bom.json
|
||||
jcs_canonicalize ./bom.json | sha256sum # == canonical_id
|
||||
```
|
||||
|
||||
**Integration (sign + verify + Rekor):**
|
||||
|
||||
```bash
|
||||
cosign attest --predicate predicate.json --key cosign.key <subject-ref>
|
||||
cosign verify-attestation --key <pubkey> --type in-toto <subject-ref>
|
||||
rekor-cli tile get --entry <entry_id> # validate inclusion proof
|
||||
```
|
||||
|
||||
**VEX mapping:**
|
||||
|
||||
* Convert OpenVEX → CycloneDX VEX; jsonschema validate.
|
||||
* Assert: `vulnerabilities[].analysis.state` and target `canonical_id` are exact.
|
||||
|
||||
**E2E (nightly, reproducibility POC):**
|
||||
|
||||
```bash
|
||||
stella-replay --token <replay_token> --seed <seed> # same signed_score DSSE & same Rekor tile id
|
||||
```
|
||||
|
||||
**Deterministic signed score (gate):**
|
||||
|
||||
* Given `(seed, canonical_id, evidence_ids[])` → produce `signed_score_dsse`.
|
||||
* `cosign verify-attestation` and recompute score → byte‑exact equality.
|
||||
|
||||
---
|
||||
|
||||
# Failure modes (and what to do)
|
||||
|
||||
* **Payload > Rekor limit:** Put artifact in immutable object store; Rekor entry contains digest + pointer; embed pointer in predicate; verifier must fetch & hash‑check.
|
||||
* **Missing symbol bundle:** Emit `unknown_state` micro‑witness entry; surface unknowns explicitly in reports.
|
||||
* **Digest mismatch anywhere:** fail the build—no exceptions.
|
||||
|
||||
---
|
||||
|
||||
# Two concrete sample flows (ready to demo in Stella Ops)
|
||||
|
||||
* **Flow A**: Canonical CycloneDX → DSSE sign (cosign) → Rekor v2 tile captured → Verify via referrers + DSSE + tile proof.
|
||||
* **Flow B**: Ingest OpenVEX → Map → Apply to `canonical_id` → Runtime micro‑witness DSSE → Join with VEX (`not_affected` ⇒ auto‑suppress), export audit pack containing both DSSEs + Rekor tiles.
|
||||
|
||||
---
|
||||
|
||||
If you want, I can turn this into:
|
||||
|
||||
* a **CI job pack** (GitLab/YAML) with all commands and assertions,
|
||||
* minimal **JSON schemas** for the predicates,
|
||||
* a **sample repo** with fixtures (SBOM, predicates, signed envelopes) you can run locally with cosign/Rekor.
|
||||
@@ -0,0 +1,106 @@
|
||||
Here are **four fast, defensible moat experiments** you can add to Stella Ops and validate in 1–2 sprints—each with a crisp pass/fail and public references.
|
||||
|
||||
---
|
||||
|
||||
### 1) Function‑level **semantic fingerprints** (“semhash”)
|
||||
|
||||
**Why:** resilient artifact identity across rebuilds/optimizations; raises code‑reuse evasion cost.
|
||||
**Signals to measure:**
|
||||
|
||||
* ≥80% within‑version function match across gcc/clang and -O0/-O2/-Os;
|
||||
* <1% cross‑project false positives vs ~10k‑function corpus;
|
||||
* Robust to symbol‑stripping & minor reordering.
|
||||
**2‑sprint plan:**
|
||||
* A: Extract per‑function IL via DWARF, normalize, embed/hash; prototype store & query. ([Dwarfstd][1])
|
||||
* B: CI job builds 3 variants, computes semhash diffs; publish report.
|
||||
**Single‑card experiment:** CI asserts ≥80% functions cluster to same semhash; attach diffoscope snapshot for mismatches. ([Diffoscope][2])
|
||||
**Grounding:** KEENHash (function‑aware hashing); DWARF v5 spec; diffoscope latest (v312, 2026‑02‑06). ([arXiv][3])
|
||||
|
||||
---
|
||||
|
||||
### 2) **Deterministic short‑run behavior attestations** (sandbox traces)
|
||||
|
||||
**Why:** converts “it executed” into a cryptographically verifiable exploitability signal; complements VEX.
|
||||
**Signals:**
|
||||
|
||||
* > 99% identical syscall/observable trace on repeated runs in hermetic harness;
|
||||
* Variance across different inputs;
|
||||
* Capture <10s, replay <10s.
|
||||
**2‑sprint plan:**
|
||||
* A: Record a containerized micro‑handler under Firecracker (or gVisor) using `rr`; wrap trace as DSSE; sign with cosign. ([Amazon Web Services, Inc.][4])
|
||||
* B: Verifier replays trace (rr) and checks DSSE + Rekor pointer. ([RR Project][5])
|
||||
**Single‑card experiment:** Build+run a <1s handler, emit signed trace, store Rekor pointer, run verifier → PASS only if replay+verify succeed. ([GitHub][6])
|
||||
|
||||
---
|
||||
|
||||
### 3) **Dual‑log “twin‑proof” stitching** (multi‑log anchoring + witness)
|
||||
|
||||
**Why:** attacker must tamper with two independent logs; stronger story for procurement/legal.
|
||||
**Signals:**
|
||||
|
||||
* Same DSSE digest appears in **Rekor v2** and a second append‑only log (e.g., signed Git tag);
|
||||
* Consistency/witness checks detect divergence;
|
||||
* Measurable increased attack cost vs single‑log.
|
||||
**2‑sprint plan:**
|
||||
* A: Write attestation to Rekor v2 and to signed‑tag Git “proofs” repo; record both pointers in DSSE. ([Sigstore Blog][7])
|
||||
* B: Verifier fetches Rekor inclusion proof + Git tag sig; PASS only if both validate. ([Sigstore Blog][8])
|
||||
**Single‑card experiment:** Produce one DSSE, anchor to both logs, run verifier → PASS iff both proofs verify. ([Sigstore Blog][9])
|
||||
|
||||
---
|
||||
|
||||
### 4) **Attestable runtime canary beacons**
|
||||
|
||||
**Why:** low‑volume evidence that a specific artifact actually ran in a real env—without shipping raw telemetry.
|
||||
**Signals:**
|
||||
|
||||
* Signed beacon ⟨artifact_id, nonce, timestamp⟩ verified against cosign key + Rekor pointer;
|
||||
* > 90% beacon verification rate in staged infra;
|
||||
* Origin/IP/arrival cadence provide internal execution evidence.
|
||||
**2‑sprint plan:**
|
||||
* A: Embed a one‑shot beacon emitter (Go) at entrypoint; post DSSE to a small collector over mTLS; sign + anchor. ([GitHub][6])
|
||||
* B: Collector verifies sig + Rekor, stores events; expose query API; (optionally align with OTel signals). ([Canarytokens][10])
|
||||
**Single‑card experiment:** Run the binary once in staging → collector shows verified DSSE + Rekor pointer. ([GitHub][6])
|
||||
|
||||
---
|
||||
|
||||
### Where this slots into **Stella Ops**
|
||||
|
||||
* **Evidence Locker:** store semhashes, traces, dual‑anchors, and beacons as first‑class DSSE records.
|
||||
* **Attestor:** add “sandbox‑trace.verify()” and “twin‑proof.verify()” checks to your policy engine.
|
||||
* **AdvisoryAI:** surface investor‑friendly KPIs: semhash stability %, trace‑replay PASS rate, dual‑anchor PASS rate, beacon verification %.
|
||||
* **Release Orchestrator:** make these jobs optional gates per environment.
|
||||
|
||||
---
|
||||
|
||||
### Acceptance criteria (quick)
|
||||
|
||||
* **Semhash:** ≥80% stable across two compiler flags; <1% FP vs 10k corpus. ([arXiv][3])
|
||||
* **Sandbox traces:** rr replay PASS + DSSE verify + Rekor pointer in CI. ([RR Project][5])
|
||||
* **Twin‑proof:** verifier fails if either Rekor or Git proof missing. ([Sigstore Blog][9])
|
||||
* **Beacons:** ≥90% verified beacons from staged runs. ([Canarytokens][10])
|
||||
|
||||
---
|
||||
|
||||
### Primary links (for your sprint tickets)
|
||||
|
||||
* KEENHash (ISSTA 2025): arXiv/DOI & PDF. ([arXiv][3])
|
||||
* DWARF v5 standard. ([Dwarfstd][1])
|
||||
* diffoscope v312 (2026‑02‑06). ([Diffoscope][2])
|
||||
* Firecracker intro/background. ([Amazon Web Services, Inc.][4])
|
||||
* rr project docs. ([RR Project][5])
|
||||
* cosign (DSSE/in‑toto attestations) & Rekor v2 (alpha→GA). ([GitHub][6])
|
||||
* Canarytokens guide/admin (for beaconing patterns). ([Canarytokens][11])
|
||||
|
||||
If you want, I can draft the **four CI job cards** (Makefile targets + sample DSSE predicates + policy checks) sized for a two‑sprint push.
|
||||
|
||||
[1]: https://dwarfstd.org/dwarf5std.html?utm_source=chatgpt.com "DWARF Version 5"
|
||||
[2]: https://diffoscope.org/?utm_source=chatgpt.com "diffoscope: in-depth comparison of files, archives, and ..."
|
||||
[3]: https://arxiv.org/abs/2506.11612?utm_source=chatgpt.com "KEENHash: Hashing Programs into Function-Aware Embeddings for Large-Scale Binary Code Similarity Analysis"
|
||||
[4]: https://aws.amazon.com/blogs/aws/firecracker-lightweight-virtualization-for-serverless-computing/?utm_source=chatgpt.com "Firecracker – Lightweight Virtualization for Serverless ..."
|
||||
[5]: https://rr-project.org/?utm_source=chatgpt.com "rr: lightweight recording & deterministic debugging"
|
||||
[6]: https://github.com/sigstore/cosign?utm_source=chatgpt.com "sigstore/cosign: Code signing and ..."
|
||||
[7]: https://blog.sigstore.dev/rekor-v2-alpha/?utm_source=chatgpt.com "Rekor v2 - Cheaper to run, simpler to maintain"
|
||||
[8]: https://blog.sigstore.dev/?utm_source=chatgpt.com "Sigstore Blog - Sigstore Blog"
|
||||
[9]: https://blog.sigstore.dev/rekor-v2-ga/?utm_source=chatgpt.com "Rekor v2 GA - Cheaper to run, simpler to maintain"
|
||||
[10]: https://docs.canarytokens.org/guide/getting-started.html?utm_source=chatgpt.com "Getting Started"
|
||||
[11]: https://docs.canarytokens.org/guide/?utm_source=chatgpt.com "Introduction"
|
||||
@@ -0,0 +1,233 @@
|
||||
Here’s a practical, copy‑pasteable test plan to harden your diff‑scanner, DSSE/verifier, and Rekor paths—plus just enough background so it’s clear why each matters.
|
||||
|
||||
---
|
||||
|
||||
# Why these tests?
|
||||
|
||||
* **Canonicalization is brittle.** JSON key order, whitespace, duplicate keys and Unicode normalization can silently change digests.
|
||||
* **Attestation chains fail in weird ways.** Rekor and DSSE failure modes (oversize payloads, unknown entry types, ledger gaps) must return deterministic errors for reliable pipelines.
|
||||
* **Real SBOMs are messy.** Schema‑valid ≠ safe; fuzzing and mutation catch parser edges that schema validation misses.
|
||||
|
||||
---
|
||||
|
||||
# Repo layout (drop in as `/tests/supply-chain/`)
|
||||
|
||||
```
|
||||
tests/supply-chain/
|
||||
01-jcs-property/
|
||||
02-schema-fuzz/
|
||||
03-rekor-neg/
|
||||
04-big-dsse-referrers/
|
||||
05-corpus/
|
||||
tools/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 0) Common tooling (Python + Go)
|
||||
|
||||
```
|
||||
pip install hypothesis hypothesis-jsonschema schemathesis jsonschema
|
||||
# optional native fuzzers
|
||||
# apt-get install -y afl++ radamsa
|
||||
```
|
||||
|
||||
Place helpers in `tools/`:
|
||||
|
||||
* `canon_diff.py` – runs your canonicalizer then diffs (`canonical_diff.patch` output).
|
||||
* `emit_artifacts.py` – writes `failing_case.json`, `hypothesis_seed.txt`, `junit.xml`.
|
||||
* `rekor_shim.py` – lightweight Flask/FastAPI shim that mimics Rekor error modes.
|
||||
* `oci_referrer_mutator.go` – mutates OCI referrers/mediaTypes.
|
||||
|
||||
---
|
||||
|
||||
# 1) JCS property tests (seeded by CycloneDX schema)
|
||||
|
||||
**Goal:** prove canonicalization invariants.
|
||||
**Invariants:** idempotence; permutation equality; reject duplicate keys.
|
||||
|
||||
**Implementation sketch (`tests/supply-chain/01-jcs-property/test_jcs.py`):**
|
||||
|
||||
```python
|
||||
from hypothesis import given, settings, note
|
||||
from hypothesis_jsonschema import from_schema
|
||||
import json, pathlib, subprocess, os, random
|
||||
|
||||
SCHEMA = json.load(open("schemas/cyclonedx-1.5.json"))
|
||||
JUNIT = pathlib.Path("tests/supply-chain/01-jcs-property/junit.xml")
|
||||
|
||||
@given(from_schema(SCHEMA))
|
||||
@settings(max_examples=200)
|
||||
def test_canonicalization(model):
|
||||
# 1) randomize key order
|
||||
blob = json.dumps(model, separators=(",", ":"), sort_keys=False)
|
||||
# 2) run your canonicalizer twice
|
||||
c1 = subprocess.check_output(["./bin/diff-scanner","--canon","-"], input=blob.encode())
|
||||
c2 = subprocess.check_output(["./bin/diff-scanner","--canon","-"], input=c1)
|
||||
assert c1 == c2, "Idempotence failed"
|
||||
|
||||
# 3) ensure permutations hash equal
|
||||
shuffled = json.dumps(model, separators=(",", ":"), sort_keys=False)
|
||||
c3 = subprocess.check_output(["./bin/diff-scanner","--canon","-"], input=shuffled.encode())
|
||||
assert c1 == c3, "Permutation equality failed"
|
||||
```
|
||||
|
||||
**On failure:** write `failing_case.json`, `hypothesis_seed.txt`, `canonical_diff.patch`, and append to `junit.xml` (use `emit_artifacts.py`).
|
||||
|
||||
**Artifacts:**
|
||||
`01-jcs-property/{failing_case.json,hypothesis_seed.txt,junit.xml,canonical_diff.patch}`
|
||||
|
||||
---
|
||||
|
||||
# 2) Schema‑aware fuzzing (CycloneDX + in‑toto)
|
||||
|
||||
**Goal:** crash‑free, memory‑safe parsing & diff logic.
|
||||
|
||||
* **JSON fuzz (property + mutational):**
|
||||
|
||||
* Hypothesis (schema‑seeded) → parser/diff
|
||||
* Radamsa/AFL++ mutate “golden” SBOMs
|
||||
|
||||
* **API fuzz (if you expose an SBOM/attestation API):**
|
||||
|
||||
* Schemathesis → OpenAPI/JSON Schema guided.
|
||||
|
||||
**Layout & gate:**
|
||||
|
||||
```
|
||||
02-schema-fuzz/
|
||||
corpus/golden/ # 10–20 known‑good SBOMs & attestations
|
||||
corpus/mutated/ # generated
|
||||
sanitizer_reports/
|
||||
crash_traces/
|
||||
repro_playbook.md
|
||||
```
|
||||
|
||||
**CI smoke gate:** run 60s or 1000 mutations (whichever first) → **no crashes / no sanitizer errors**.
|
||||
|
||||
---
|
||||
|
||||
# 3) Negative Rekor & attestation fault injection
|
||||
|
||||
**Goal:** deterministic failures & rich diagnostics.
|
||||
|
||||
Simulate via `rekor_shim.py`:
|
||||
|
||||
* Oversized attestations (e.g., 25–200 MB)
|
||||
* Unsupported `entryType`
|
||||
* HTTP responses: 413, 424, 504
|
||||
* Ledger gap window
|
||||
|
||||
**Verifier requirements:**
|
||||
|
||||
* Return stable codes: `424 failed-dependency` or `202` **with** `reprocess_token`
|
||||
* Attach `diagnostic_blob.json` (include upstream status, body, and correlation IDs)
|
||||
|
||||
**Artifacts:** `03-rekor-neg/rekor_negative_cases.tar.gz`
|
||||
|
||||
---
|
||||
|
||||
# 4) Big‑payload DSSE & OCI referrer edge cases
|
||||
|
||||
**Goal:** graceful reject + auditable state.
|
||||
|
||||
Cases:
|
||||
|
||||
* DSSE payloads 100 MB, 250 MB, 1 GB (streamed where possible)
|
||||
* Malformed OCI referrers (dangling, invalid `mediaType`, cycles)
|
||||
* Missing symbol bundles
|
||||
|
||||
**Expected behavior:**
|
||||
|
||||
* Reject cleanly
|
||||
* Emit DSSE predicate `unknown_state`
|
||||
* Append audit line with `reprocess_token`
|
||||
|
||||
**Artifacts:** `04-big-dsse-referrers/big_dsse_payloads.tar.gz`
|
||||
|
||||
---
|
||||
|
||||
# 5) Mutation corpus & fixtures for canonicalization exploits
|
||||
|
||||
**Goal:** permanent regression shield.
|
||||
|
||||
Include:
|
||||
|
||||
* **SBOMs:** 50 small, 30 medium (100–500 KB), 20 large (1–50 MB)
|
||||
* VEX variants & attestation‑only samples
|
||||
* Malformed JSON (duplicate keys, Unicode normalization forms)
|
||||
* Symbol‑bundle stubs
|
||||
* Tricky dependency graphs (diamond, deep chains, cycles)
|
||||
|
||||
**Bundle:** `tests/supply-chain/05-corpus/fixtures/fuzz-corpus-v1.tar.gz`
|
||||
|
||||
---
|
||||
|
||||
# Makefile (one‑command runs)
|
||||
|
||||
```make
|
||||
.PHONY: supplychain test smoke fuzz rekor big
|
||||
|
||||
supplychain: test
|
||||
|
||||
test:
|
||||
\tpytest -q tests/supply-chain/01-jcs-property --junitxml=tests/supply-chain/01-jcs-property/junit.xml
|
||||
|
||||
smoke:
|
||||
\tpython tests/supply-chain/02-schema-fuzz/run_mutations.py --limit 1000 --time 60
|
||||
|
||||
fuzz:
|
||||
\tpython tests/supply-chain/02-schema-fuzz/run_mutations.py --time 600
|
||||
|
||||
rekor:
|
||||
\tpython tests/supply-chain/03-rekor-neg/rekor_shim.py &
|
||||
\t./bin/verifier --rekor-url http://127.0.0.1:8000 run-negative-suite
|
||||
|
||||
big:
|
||||
\tpython tests/supply-chain/04-big-dsse-referrers/run_big_cases.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# CI wiring (example GitHub Actions job)
|
||||
|
||||
```yaml
|
||||
name: supply-chain-hardening
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
smoke:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with: { python-version: '3.12' }
|
||||
- run: pip install -r tests/requirements.txt
|
||||
- run: make test
|
||||
- run: make smoke
|
||||
- run: make rekor
|
||||
- run: make big
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
HYPOTHESIS_PROFILE: ci
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Pass/Fail gates (put in README)
|
||||
|
||||
* **JCS property tests:** 0 failures; artifacts emitted on failure.
|
||||
* **Fuzz smoke (CI):** 1,000 mutations / 60s → 0 crashes, 0 ASAN/UBSAN reports.
|
||||
* **Rekor negative suite:** All cases return deterministic code + `diagnostic_blob.json`.
|
||||
* **Big DSSE/referrers:** All oversized/malformed inputs → graceful reject + `unknown_state` + `reprocess_token`.
|
||||
* **Corpus:** New crashes must add a minimized repro to `fixtures/` before merge.
|
||||
|
||||
---
|
||||
|
||||
# Quick start checklist
|
||||
|
||||
* [ ] Add CycloneDX & in‑toto schemas under `schemas/`.
|
||||
* [ ] Wire `./bin/diff-scanner` and `./bin/verifier` into tests.
|
||||
* [ ] Commit initial `fixtures/fuzz-corpus-v1.tar.gz`.
|
||||
* [ ] Enable CI job above and enforce as a required check.
|
||||
|
||||
If you want, I can generate the skeleton files (tests, helpers, Makefile, CI YAML) tailored to your repo paths.
|
||||
@@ -0,0 +1,79 @@
|
||||
# Auditor UX Experiments: Measurement Plan (Repaired)
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Auditors can verify evidence, but they still lose time on three friction points:
|
||||
|
||||
1. Slow navigation from finding to signed proof chain.
|
||||
2. Ambiguous failure states when verification is unavailable.
|
||||
3. Missing deterministic replay context in triage.
|
||||
|
||||
## Scope
|
||||
|
||||
This advisory defines measurable UI experiments for auditor workflows in `Security -> Triage`, `Security -> Findings`, and `Security -> Risk`.
|
||||
|
||||
## Experiments
|
||||
|
||||
### EXP-AUD-001 - Evidence Pill Resolution Latency
|
||||
|
||||
Hypothesis:
|
||||
- Exposing proof status and verification reason directly in evidence pills reduces time-to-confidence.
|
||||
|
||||
Implementation notes:
|
||||
- Show explicit states: `verified`, `pending`, `unavailable`, `failed`.
|
||||
- Always show deterministic reason text for non-verified states.
|
||||
|
||||
Primary metrics:
|
||||
- P50 time to first proof verdict under 15 seconds.
|
||||
- P95 time to first proof verdict under 45 seconds.
|
||||
|
||||
Acceptance criteria:
|
||||
- At least 80% of trial sessions complete proof review without leaving triage workspace.
|
||||
|
||||
### EXP-AUD-002 - Quick-Verify Action Reliability
|
||||
|
||||
Hypothesis:
|
||||
- A first-class Quick-Verify action with deterministic result payload lowers auditor retries.
|
||||
|
||||
Implementation notes:
|
||||
- Quick-Verify must return consistent status envelope.
|
||||
- `Why unavailable` path must include actionable remediation text.
|
||||
|
||||
Primary metrics:
|
||||
- Verification success response rate >= 99% for valid fixtures.
|
||||
- Retry rate below 5% for deterministic fixtures.
|
||||
|
||||
Acceptance criteria:
|
||||
- Zero ambiguous UI states (no generic unknown/error labels in audited paths).
|
||||
|
||||
### EXP-AUD-003 - Score Explainability Readability
|
||||
|
||||
Hypothesis:
|
||||
- Integrating score history and breakdown in findings reduces manual evidence lookup.
|
||||
|
||||
Implementation notes:
|
||||
- Display score pill, breakdown, and history chart in findings detail view.
|
||||
- Keep chart and breakdown data sourced from API responses only.
|
||||
|
||||
Primary metrics:
|
||||
- 90% of participants can explain score movement in under 60 seconds.
|
||||
- 0 synthetic/demo fallback content in production route coverage.
|
||||
|
||||
Acceptance criteria:
|
||||
- Re-enabled E2E suites pass for score and risk widgets.
|
||||
|
||||
## Data Collection Plan
|
||||
|
||||
- Capture experiment logs with UTC timestamps.
|
||||
- Record lane, widget, and action identifiers for each interaction.
|
||||
- Export deterministic run summaries under CI artifacts.
|
||||
|
||||
## Advisory-to-Sprint Translation
|
||||
|
||||
- `SPRINT_20260226_227_FE_triage_risk_score_widget_wiring_and_parity.md`
|
||||
- `SPRINT_20260226_229_DOCS_advisory_hygiene_dedup_and_archival_translation.md`
|
||||
|
||||
## Status
|
||||
|
||||
- Translation complete as of 2026-03-03 (UTC).
|
||||
- Ready for archival after sprint trackers are updated.
|
||||
@@ -0,0 +1,113 @@
|
||||
Here’s a practical, cross‑platform way to make “symbols just work” across Windows (PDB), Apple platforms (dSYM/DWARF), and Linux (ELF + build‑id), with security and CDN‑friendliness baked in.
|
||||
|
||||
---
|
||||
|
||||
### Why symbols matter (super short)
|
||||
|
||||
* **Windows:** debuggers fetch **.pdb** by PDB **GUID+Age** via symbol servers (SRV/HTTP). ([Microsoft Learn][1])
|
||||
* **Apple:** crash/symbolication uses **dSYM** bundles matched by **Mach‑O UUID** (`dwarfdump --uuid`). ([Apple Developer][2])
|
||||
* **Linux:** tools fetch debuginfo by **ELF build‑id** (HTTP **debuginfod**). ([Sourceware][3])
|
||||
|
||||
---
|
||||
|
||||
### The unified “symbol‑bundle” contract
|
||||
|
||||
**Key idea:** One manifest per build that maps the platform identifier → content‑addressed blobs.
|
||||
|
||||
* **Identifiers**
|
||||
|
||||
* Windows: `{pdb_guid, age}` → blobs. (DIA/SymSrv semantics) ([Microsoft Learn][4])
|
||||
* Apple: `{macho_uuid}` → dSYM DWARF payload. (verified via `dwarfdump --uuid`) ([Apple Developer][2])
|
||||
* Linux: `{elf_build_id}` → debuginfo/source via HTTP. ([Sourceware][3])
|
||||
|
||||
* **Manifest (per bundle)**
|
||||
|
||||
* `platform`: windows|apple|linux
|
||||
* `id`: PDB GUID+Age | Mach‑O UUID | ELF build‑id
|
||||
* `objects`: list of content‑addressed parts (e.g., `sha256://...`) with sizes and optional ranges (to support progressive fetch)
|
||||
* `sources`: optional redacted source paths map (to hide internal paths)
|
||||
* `signatures`: DSSE/attestations for integrity
|
||||
* `hints`: e.g., `func_ranges`, `cu_index` to enable partial loads
|
||||
|
||||
* **Storage layout**
|
||||
|
||||
* **Content‑addressed** blobs in a TLS‑only bucket/CDN; manifests are tiny JSON.
|
||||
* HTTP range‑friendly so debuggers can grab just what they need (great for huge DWARF).
|
||||
* Publish **short‑lived signed URLs** only (no anonymous long‑term links).
|
||||
|
||||
* **Lookup endpoints**
|
||||
|
||||
* `GET /v1/symbols/windows/{guid}/{age}` → manifest
|
||||
* `GET /v1/symbols/apple/{uuid}` → manifest
|
||||
* `GET /v1/symbols/linux/{buildid}` → manifest
|
||||
Mirrors the native expectations: SRV/HTTP for PDB, UUID for dSYM, build‑id for ELF. ([Microsoft Learn][5])
|
||||
|
||||
---
|
||||
|
||||
### Performance & size budgets
|
||||
|
||||
* **Progressive fetch:** serve index first, defer big DWARF sections (target ~100–200 MB per bundle; more is OK but lazy‑load).
|
||||
* **Local cache pinning:** respect debugger caches (SRV path semantics on Windows; keep a local debuginfod cache on Linux/macOS). ([Microsoft Learn][6])
|
||||
|
||||
---
|
||||
|
||||
### Privacy & security
|
||||
|
||||
* **TLS‑only**, **short‑lived URLs**, **no directory listings**.
|
||||
* **Source‑path redaction** in manifests; optionally omit source entirely and ship “public symbols” (strIPPED) where policy demands. (Windows symbol server supports partial/public symbols patterns.) ([Microsoft Learn][7])
|
||||
|
||||
---
|
||||
|
||||
### Tooling hooks you already know
|
||||
|
||||
* **Windows:** Keep SRV compatibility so WinDbg/VS can consume via `srv*<cache>*https://your.cdn/symbols`. ([Microsoft Learn][6])
|
||||
* **Apple:** Ensure dSYM ↔ binary **UUID match** (`dwarfdump --uuid`) before upload; symbolication tools rely on that. ([Apple Developer][2])
|
||||
* **Linux:** Stand up **debuginfod** against your blob store index; clients (gdb, perf, systemd‑coredump, etc.) auto‑fetch by build‑id. ([Sourceware][3])
|
||||
|
||||
---
|
||||
|
||||
### eBPF “micro‑witness” interop (optional but useful)
|
||||
|
||||
* Emit tiny signed records: `{addr, platform_id, function|cu_hint}` to speed post‑mortems and flamegraphs while letting the symbol service hydrate details lazily.
|
||||
|
||||
---
|
||||
|
||||
### Integration test matrix (keep you honest)
|
||||
|
||||
Seeded replay suites that verify:
|
||||
|
||||
* Correct file chosen per **GUID+Age / UUID / build‑id**. ([Microsoft Learn][1])
|
||||
* Mismatch injections (wrong UUID, wrong age) are detected and rejected. ([Apple Developer][2])
|
||||
* Coverage SLOs (e.g., ≥95% frames symbolicated in smoke crashes).
|
||||
* CDN range requests behave; large DWARF loads don’t exceed soft limits.
|
||||
|
||||
---
|
||||
|
||||
### Why this helps your stack (Stella Ops context)
|
||||
|
||||
* Works the same for **.NET on Windows**, **Swift/Obj‑C on iOS/macOS**, **Go/Rust/C++ on Linux**.
|
||||
* Lets you **attest** artifacts (DSSE) and keep symbol access **least‑privileged**.
|
||||
* Reduces crash‑to‑signal time: prod agents can attach only IDs; backends fetch symbols on demand.
|
||||
|
||||
---
|
||||
|
||||
### Pointers if you’re implementing now
|
||||
|
||||
* Start by exposing **read‑only HTTP** that answers by identifier and returns a **small JSON manifest**.
|
||||
* Back it with:
|
||||
|
||||
* a **DIA** pass to extract `{GUID,Age}` from PDBs (Windows), ([Microsoft Learn][8])
|
||||
* a `dwarfdump --uuid` scan for dSYMs (Apple), ([Apple Developer][2])
|
||||
* an **elfutils** scan to index **build‑ids** (Linux). ([Sourceware][3])
|
||||
* Keep a **compat SRV endpoint** (reverse‑proxy that translates SRV requests to your manifest/CDN fetches) so legacy Windows tools work unchanged. ([Microsoft Learn][5])
|
||||
|
||||
If you want, I can draft the manifest schema (JSON), an ingestion CLI (Windows + Linux + macOS), and a minimal Go/ASP.NET Core service that serves the three lookups with signed‑URL redirects.
|
||||
|
||||
[1]: https://learn.microsoft.com/en-us/windows/win32/debug/symbol-servers-and-symbol-stores?utm_source=chatgpt.com "Symbol Server and Symbol Stores - Win32 apps"
|
||||
[2]: https://developer.apple.com/documentation/technotes/tn3178-checking-for-and-resolving-build-uuid-problems?utm_source=chatgpt.com "TN3178: Checking for and resolving build UUID problems"
|
||||
[3]: https://sourceware.org/elfutils/Debuginfod.html?utm_source=chatgpt.com "elfutils debuginfod services"
|
||||
[4]: https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/symbols-and-symbol-tags?view=visualstudio&utm_source=chatgpt.com "Symbols and Symbol Tags - Visual Studio (Windows)"
|
||||
[5]: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/http-symbol-stores?utm_source=chatgpt.com "HTTP Symbol Stores - Windows drivers"
|
||||
[6]: https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/symbol-path?utm_source=chatgpt.com "Configure Symbol Path: Windows Debuggers"
|
||||
[7]: https://learn.microsoft.com/en-us/windows/win32/debug/using-symsrv?utm_source=chatgpt.com "Using SymSrv - Win32 apps"
|
||||
[8]: https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk?view=visualstudio&utm_source=chatgpt.com "Debug Interface Access SDK - Visual Studio (Windows)"
|
||||
@@ -0,0 +1,54 @@
|
||||
Here’s a super-practical “verifier recipe” you can drop into Stella Ops to validate supply‑chain attestations and Rekor v2 tiles end‑to‑end.
|
||||
|
||||
# 0) Quick background (so the terms make sense)
|
||||
|
||||
* **in‑toto Statement**: a tiny wrapper that says “this attestation is about artifact X with digest Y; the payload (predicate) is of type Z (e.g., SLSA Provenance).” ([GitHub][1])
|
||||
* **DSSE**: a signing envelope format (signatures over `payloadType` + canonicalized `payload` bytes). ([GitHub][2])
|
||||
* **Rekor v2 tiles**: transparency log moved to a **tile‑backed** layout; clients fetch tiles and compute inclusion proofs locally (no “get by index” API). ([Sigstore Blog][3])
|
||||
* **JCS**: a deterministic JSON canonicalization used when hashing/validating JSON payload bytes. ([RFC Editor][4])
|
||||
|
||||
# 1) Match the attestation to the artifact (Statement checks)
|
||||
|
||||
* Load the in‑toto **Statement**. Confirm each `subject[*].name` and `subject[*].digest` matches the artifact you’re verifying.
|
||||
* Assert the **`predicateType`** is recognized (e.g., `https://slsa.dev/provenance` / v0.1–v1.x) and, if present, validate **`predicate.materials`** (inputs) against expected sources. This binds “what was built” and “from what.” ([GitHub][1])
|
||||
|
||||
# 2) Verify DSSE signatures (bytes matter)
|
||||
|
||||
* **Canonicalize** the DSSE *payload bytes* using DSSE’s own serialization rules; verify the DSSE signature against the signer’s public key (or Sigstore bundle chain if you use that path). ([GitHub][2])
|
||||
* Before any policy hash checks over JSON, **re‑canonicalize** the payload using **JCS** so downstream hashing is deterministic across platforms. ([RFC Editor][4])
|
||||
|
||||
# 3) Prove Rekor inclusion (tiles, not point lookups)
|
||||
|
||||
* **Prefer** the `inclusion_proof` returned at upload time—store it with the bundle to avoid reconstructing later. ([GitHub][5])
|
||||
* If missing, **assemble the minimal tile set** from Rekor v2 endpoints (client‑side), then verify:
|
||||
a) merkle inclusion for the entry’s leaf, and
|
||||
b) the inclusion proof’s **checkpoint** against the Rekor v2 checkpoint.
|
||||
Rekor v2 intentionally removed “get by index/leaf hash”; clients fetch tiles and compute proofs locally. ([Sigstore Blog][3])
|
||||
|
||||
---
|
||||
|
||||
## How to wire this into Stella Ops (concise plan)
|
||||
|
||||
* **Verifier service** (AdvisoryAI/EvidenceLocker boundary):
|
||||
|
||||
* Input: `{artifactPath|digest, dsseEnvelope|bundle, optional inclusion_proof}`.
|
||||
* Steps: (1) Statement match → (2) DSSE verify → (3) Inclusion verify → (4) Policy (SLSA fields, materials allow‑list).
|
||||
* **Policy hooks**: add simple YAML policies (e.g., allowed builders, required `materials[]` domains, min SLSA predicate version). ([SLSA][6])
|
||||
* **Caching**: persist tiles + checkpoints per tree size to avoid refetch.
|
||||
* **UI**: in Release Bundle > Evidence tab show: “Subject match ✅ / DSSE sig ✅ / Inclusion ✅ (treeSize, rootHash, checkpoint origin)”.
|
||||
|
||||
## Pitfalls to avoid
|
||||
|
||||
* Hashing the JSON *without* JCS and getting platform‑specific diffs. (Use JCS before any JSON‑level policy hashing.) ([RFC Editor][4])
|
||||
* Treating Rekor v2 like v1 (no direct “get by index” reads; fetch tiles and compute locally). ([Sigstore Blog][3])
|
||||
* Ignoring `predicateType` evolution; track the URI (it encodes major version semantics). ([SLSA][7])
|
||||
|
||||
If you want, I can sketch a tiny .NET verifier module (interfaces + test vectors) that plugs into Stella Ops’s EvidenceLocker and uses the Rekor v2 tile client model.
|
||||
|
||||
[1]: https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md?utm_source=chatgpt.com "attestation/spec/v1/statement.md at main · in-toto/attestation"
|
||||
[2]: https://github.com/secure-systems-lab/dsse?utm_source=chatgpt.com "DSSE: Dead Simple Signing Envelope"
|
||||
[3]: https://blog.sigstore.dev/rekor-v2-ga/?utm_source=chatgpt.com "Rekor v2 GA - Cheaper to run, simpler to maintain"
|
||||
[4]: https://www.rfc-editor.org/rfc/rfc8785?utm_source=chatgpt.com "RFC 8785: JSON Canonicalization Scheme (JCS)"
|
||||
[5]: https://github.com/sigstore/rekor?utm_source=chatgpt.com "sigstore/rekor: Software Supply Chain Transparency Log"
|
||||
[6]: https://slsa.dev/spec/v0.1/provenance?utm_source=chatgpt.com "Provenance"
|
||||
[7]: https://slsa.dev/spec/v0.1/verification_summary?utm_source=chatgpt.com "Verification Summary Attestation (VSA)"
|
||||
@@ -0,0 +1,100 @@
|
||||
Here’s a practical playbook to turn “technical defensibility” into measurable revenue—explained plainly and mapped to motions you can ship.
|
||||
|
||||
---
|
||||
|
||||
# 6 motions that convert security rigor into ARR
|
||||
|
||||
1. **Provenance ledger + signed decisions (audits that sell themselves)**
|
||||
|
||||
* What it is: Canonicalize every decision artifact (use RFC 8785 JCS for stable JSON), then wrap scores/findings with DSSE signatures.
|
||||
* Why it sells: Auditors/SOCs can verify evidence cryptographically; buyers feel safe to expand seats.
|
||||
* Ship it:
|
||||
|
||||
* “Decision Service” emits `decision.json` (JCS) + `.sig` (DSSE).
|
||||
* Append immutable receipts to a lightweight ledger (SQLite/WAL → Postgres later).
|
||||
* UI: “Verify” button shows green check = signature + chain proof.
|
||||
* KPI: Audit pass rate, time‑to‑evidence, expansion revenue tied to compliance milestones.
|
||||
|
||||
2. **Exploitability modeling → micro‑witnesses → prioritized fixes**
|
||||
|
||||
* What it is: Map findings to ATT&CK + attack‑graph paths; emit tiny, human‑readable “micro‑witnesses” that prove a path exists.
|
||||
* Why it sells: Security teams buy prioritization, not lists.
|
||||
* Ship it:
|
||||
|
||||
* For each vuln, store `(entrypoint → privilege) path` + 1‑page witness.
|
||||
* Rank by “exploit path length × blast radius.”
|
||||
* KPI: Mean‑time‑to‑remediation (MTTR) for top‑10 risks; % fixes driven by witnesses.
|
||||
|
||||
3. **Call‑stack provenance with eBPF (runtime truth, not guesses)**
|
||||
|
||||
* What it is: Trace kernel/user call stacks to bind events to exact symbols/builds.
|
||||
* Why it sells: Runtime proof quiets false positives and justifies higher pricing.
|
||||
* Ship it:
|
||||
|
||||
* Sidecar eBPF agent captures `(symbol, hash, pid, cgroup)` and signs a short evidence blob.
|
||||
* Link to SBOM entries + commit SHA.
|
||||
* KPI: FP reduction, accepted fixes per sprint, “blocker to deploy” avoided.
|
||||
|
||||
4. **Binary‑ecosystem function‑matching index (network effects)**
|
||||
|
||||
* What it is: A shared index of function hashes ↔ symbols across builds/vendors.
|
||||
* Why it sells: Each new customer improves coverage for all—compelling moat.
|
||||
* Ship it:
|
||||
|
||||
* Normalize to normalized‑CFG hash; store `(fn_hash → {package, version, symbol})`.
|
||||
* Offer opt‑in “anonymized contribution” for discounts.
|
||||
* KPI: Function coverage %, match‑time latency, upsell to “priority index” tier.
|
||||
|
||||
5. **Continuous delta detection (semantic binary diffs + CI hooks)**
|
||||
|
||||
* What it is: Detect *meaningful* code path changes and patch deltas on every commit/tag.
|
||||
* Why it sells: Teams pay for “don’t let regressions ship” alerts with SLAs.
|
||||
* Ship it:
|
||||
|
||||
* Git/CI hook produces semantic diff → emits DSSE‑signed “delta receipt.”
|
||||
* Alerting: “Critical path changed without test coverage.”
|
||||
* KPI: Caught‑before‑prod incidents, SLA credits avoided, alert precision.
|
||||
|
||||
6. **Developer UX hooks: PR/IDE micro‑witnesses + one‑click replay**
|
||||
|
||||
* What it is: Put proof *inside* the PR/IDE (witness snippet + “replay locally” button).
|
||||
* Why it sells: Habit loops → daily active users → land‑and‑expand.
|
||||
* Ship it:
|
||||
|
||||
* GitHub/GitLab check with inline witness; CLI `stella replay <witness>` spins a container and reproduces the issue.
|
||||
* KPI: DAU/WAU for extensions, replay runs per PR, conversion from pilot → paid.
|
||||
|
||||
---
|
||||
|
||||
# How to package this commercially
|
||||
|
||||
* **Tiers that map to risk**
|
||||
|
||||
* Core: Signed decisions + deltas.
|
||||
* Pro: Exploitability + eBPF provenance.
|
||||
* Enterprise: Ecosystem index + auditor dashboards + SLA alerts.
|
||||
* **Sales motions**
|
||||
|
||||
* Compliance-led: “Cryptographically verifiable audits in <2 weeks.”
|
||||
* Ops-led: “Cut MTTR 40% with micro‑witnesses and one‑click replay.”
|
||||
* Platform-led: “Join the function index—better matches day one.”
|
||||
|
||||
---
|
||||
|
||||
# Minimal architecture to start
|
||||
|
||||
* Evidence types: `decision.jcs`, `witness.md`, `delta.yaml`, all DSSE‑signed.
|
||||
* Ledger: append-only table with `(artifact_digest, signer, scope, created_at)`.
|
||||
* Verifier CLI: `stella verify <artifact>` → prints trust chain + result.
|
||||
* UI: Evidence Locker with filters (service, build, control) + “Export for audit”.
|
||||
|
||||
---
|
||||
|
||||
# Fast 30‑day plan
|
||||
|
||||
* Week 1: JCS canonicalization + DSSE for two artifacts (decisions, deltas).
|
||||
* Week 2: Micro‑witness format + PR checks + basic verifier CLI.
|
||||
* Week 3: ATT&CK mapping + simple attack‑graph scoring.
|
||||
* Week 4: eBPF pilot in staging + Evidence Locker v1 + 3 SLAs + pricing page copy.
|
||||
|
||||
If you want, I can draft the DSSE/JCS spec snippets, the witness schema, a sample PR check, and the KPI dashboard widgets next.
|
||||
@@ -0,0 +1,192 @@
|
||||
Here’s a clean, first‑time‑friendly blueprint for a **deterministic crash analyzer pipeline** you can drop into Stella Ops (or any CI/CD + observability stack).
|
||||
|
||||
---
|
||||
|
||||
# What this thing does (in plain words)
|
||||
|
||||
It ingests a crash “evidence tile” (a signed, canonical JSON blob + hash), looks up symbols from your chosen stores (ELF/PDB/dSYM), unwinds the stack deterministically, and returns a **stable, symbol‑pinned call stack** plus a **replay manifest** so you can reproduce the exact same result later—bit‑for‑bit.
|
||||
|
||||
---
|
||||
|
||||
# The contract
|
||||
|
||||
### Input (strict, deterministic)
|
||||
|
||||
* **signed_evidence_tile**: Canonical JSON (JCS) with your payload (e.g., OS, arch, registers, fault addr, module list) and its `sha256`.
|
||||
|
||||
* Canonicalization must follow **RFC 8785 JCS** to make the hash verifiable.
|
||||
* **symbol_pointers**:
|
||||
|
||||
* ELF: debuginfod build‑id URIs
|
||||
* Windows: PDB GUID+Age
|
||||
* Apple: dSYM UUID
|
||||
* **unwind_context**: register snapshot, preference flags (e.g., “prefer unwind tables over frame‑pointers”), OS/ABI hints.
|
||||
* **deterministic_seed**: single source of truth for any randomized tie‑breakers or heuristics.
|
||||
|
||||
### Output
|
||||
|
||||
* **call_stack**: ordered vector of frames
|
||||
|
||||
* `addr`, `symbol_id`, optional `file:line`, `symbol_resolution_confidence`, and `resolver` (which backend won).
|
||||
* **replay_manifest**: `{ seed, env_knobs, symbol_bundle_pointer }` so you (or CI) can re‑run the exact same resolution later.
|
||||
|
||||
---
|
||||
|
||||
# Resolver abstraction (so CI can fan‑out)
|
||||
|
||||
Define a tiny interface and run resolvers in parallel; record who succeeded:
|
||||
|
||||
```ts
|
||||
type Platform = "linux" | "windows" | "apple";
|
||||
|
||||
interface ResolveResult {
|
||||
symbol_id: string; // stable id in your store
|
||||
file?: string;
|
||||
line?: number;
|
||||
confidence: number; // 0..1
|
||||
resolver: string; // e.g., "debuginfod", "dia", "dsymutil"
|
||||
}
|
||||
|
||||
function resolve(address: string, platform: Platform, bundle_hint?: string): ResolveResult | null;
|
||||
```
|
||||
|
||||
**Backends:**
|
||||
|
||||
* **Linux/ELF**: debuginfod (by build‑id), DWARF/unwind tables.
|
||||
* **Windows**: DIA/PDB (by GUID+Age).
|
||||
* **Apple**: dSYM/DWARF (by UUID), `atos`/`llvm-symbolizer` flow if desired.
|
||||
|
||||
---
|
||||
|
||||
# Deterministic ingest & hashing
|
||||
|
||||
* Parse incoming JSON → **canonicalize via JCS** → compute `sha256` → verify signature → only then proceed.
|
||||
* Persist `{canonical_json, sha256, signature, received_at}` so downstream stages always pull the exact blob.
|
||||
|
||||
---
|
||||
|
||||
# Unwinding & symbolization pipeline (deterministic)
|
||||
|
||||
1. **Normalize modules** (match load addresses → build‑ids/GUIDs/UUIDs).
|
||||
2. **Unwind** using the declared policy in `unwind_context` (frame pointers vs. EH/CFI tables).
|
||||
3. For each PC:
|
||||
|
||||
* **Parallel resolve** via resolvers (`debuginfod`, DIA/PDB, dSYM).
|
||||
* Pick the winner by **deterministic reducer**: highest `confidence`, then lexical tie‑break using `deterministic_seed`.
|
||||
4. Emit frames with `symbol_id` (stable, content‑addressed if possible), and optional `file:line`.
|
||||
|
||||
---
|
||||
|
||||
# Telemetry & SLOs (what to measure)
|
||||
|
||||
* **replay_success_ratio** (golden ≥ **95%**) — same input → same output.
|
||||
* **symbol_coverage_pct** (prod ≥ **90%**) — % of frames resolved to symbols.
|
||||
* **verify_time_ms** (median ≤ **3000 ms**) — signature + hash + canonicalization + core steps.
|
||||
* **resolver_latency_ms** per backend — for tuning caches and fallbacks.
|
||||
|
||||
---
|
||||
|
||||
# Trade‑offs (make them explicit)
|
||||
|
||||
* **On‑demand decompilation / function‑matching**
|
||||
|
||||
* ✅ Higher confidence on stripped binaries
|
||||
* ❌ More CPU/latency; potentially leaks more symbol metadata (privacy)
|
||||
* **Progressive fetch + partial symbolization**
|
||||
|
||||
* ✅ Lower latency, good UX under load
|
||||
* ❌ Lower confidence on some frames; riskier explainability (false positives)
|
||||
|
||||
Pick per environment via `env_knobs` and record that in the `replay_manifest`.
|
||||
|
||||
---
|
||||
|
||||
# Minimal wire formats (copy/paste ready)
|
||||
|
||||
### Evidence tile (canonical, pre‑hash)
|
||||
|
||||
```json
|
||||
{
|
||||
"evidence_version": 1,
|
||||
"platform": "linux",
|
||||
"arch": "x86_64",
|
||||
"fault_addr": "0x7f1a2b3c",
|
||||
"registers": { "rip": "0x7f1a2b3c", "rsp": "0x7ffd...", "rbp": "0x..." },
|
||||
"modules": [
|
||||
{"name":"svc","base":"0x400000","build_id":"a1b2c3..."},
|
||||
{"name":"libc.so.6","base":"0x7f...","build_id":"d4e5f6..."}
|
||||
],
|
||||
"ts_unix_ms": 1739999999999
|
||||
}
|
||||
```
|
||||
|
||||
### Analyzer request
|
||||
|
||||
```json
|
||||
{
|
||||
"signed_evidence_tile": {
|
||||
"jcs_json": "<the exact JCS-canonical JSON above>",
|
||||
"sha256": "f1c2...deadbeef",
|
||||
"signature": "dsse/…"
|
||||
},
|
||||
"symbol_pointers": {
|
||||
"linux": ["debuginfod:buildid:a1b2c3..."],
|
||||
"windows": ["pdb:GUID+Age:..."],
|
||||
"apple": ["dsym:UUID:..."]
|
||||
},
|
||||
"unwind_context": {
|
||||
"prefer_unwind_tables": true,
|
||||
"stack_limit_bytes": 262144
|
||||
},
|
||||
"deterministic_seed": "6f5d7d1e-..."
|
||||
}
|
||||
```
|
||||
|
||||
### Analyzer response
|
||||
|
||||
```json
|
||||
{
|
||||
"call_stack": [
|
||||
{
|
||||
"addr": "0x400abc",
|
||||
"symbol_id": "svc@a1b2c3...:main",
|
||||
"file": "main.cpp",
|
||||
"line": 127,
|
||||
"symbol_resolution_confidence": 0.98,
|
||||
"resolver": "debuginfod"
|
||||
}
|
||||
],
|
||||
"replay_manifest": {
|
||||
"seed": "6f5d7d1e-...",
|
||||
"env_knobs": { "progressive_fetch": true, "max_resolvers": 3 },
|
||||
"symbol_bundle_pointer": "bundle://a1b2c3.../svc.sym"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# How this plugs into Stella Ops
|
||||
|
||||
* **EvidenceLocker**: store the JCS‑canonical tile + DSSE signature + sha256.
|
||||
* **AdvisoryAI**: consume symbol‑pinned stacks as first‑class facts for RCA, search, and explanations.
|
||||
* **Attestor**: sign analyzer outputs (DSSE) and attach to Releases/Incidents.
|
||||
* **CI**: on build, publish symbol bundles (ELF build‑id / PDB GUID+Age / dSYM UUID) to your internal stores; register debuginfod endpoints.
|
||||
* **SLO dashboards**: show coverage, latency, and replay ratio by service and release.
|
||||
|
||||
---
|
||||
|
||||
# Quick implementation checklist
|
||||
|
||||
* [ ] JCS canonicalization + sha256 + DSSE verify gate
|
||||
* [ ] Resolver interface + parallel fan‑out + deterministic reducer
|
||||
* [ ] debuginfod client (ELF), DIA/PDB (Windows), dSYM/DWARF (Apple) adapters
|
||||
* [ ] Unwinder with policy switches (frame‑ptr vs. CFI)
|
||||
* [ ] Content‑addressed `symbol_id` scheme
|
||||
* [ ] Replay harness honoring `replay_manifest`
|
||||
* [ ] Metrics emitters + SLO dashboards
|
||||
* [ ] Privacy guardrails (strip/leak‑check symbol metadata by env)
|
||||
|
||||
---
|
||||
|
||||
If you want, I can generate a tiny reference service (Go or C#) with: JCS canonicalizer, debuginfod lookup, DIA shim, dSYM flow, and the exact JSON contracts above so you can drop it into your build & incident pipeline.
|
||||
@@ -0,0 +1,192 @@
|
||||
Here’s a small, reproducible “risk score” service design you can drop into Stella Ops to turn CVSS v4 + EPSS + analyzer evidence into a deterministic number with an auditable trail.
|
||||
|
||||
---
|
||||
|
||||
# What it does (in plain terms)
|
||||
|
||||
* Takes **authoritative inputs** (CVSS v4 vector & score, EPSS probability, your analyzer’s call‑stack confidence, optional CVE tag, etc.).
|
||||
* Computes a **deterministic score** (no RNG, no hidden heuristics).
|
||||
* Returns a **breakdown** with fixed weights + human‑readable explanations.
|
||||
* Emits a **DSSE‑signed envelope** so anyone can re‑compute and verify.
|
||||
* Includes **replay hooks** so CI can prove results are reproducible on your infra.
|
||||
|
||||
---
|
||||
|
||||
# API (stable, tiny)
|
||||
|
||||
**POST `/v1/score`**
|
||||
|
||||
```json
|
||||
{
|
||||
"evidence_jcs_hash": "sha256",
|
||||
"cve": "CVE-XXXX-YYYY",
|
||||
"cvss_v4": {
|
||||
"vector": "T:.../A:.../AV:.../AC:.../PR:.../UI:.../S:...",
|
||||
"score": 8.1
|
||||
},
|
||||
"epss": 0.27,
|
||||
"analyzer_manifest": "uri_or_blob",
|
||||
"deterministic_seed": 1337,
|
||||
"replay_constraints": {
|
||||
"max_cpu_ms": 5000,
|
||||
"unwind_mode": "full",
|
||||
"symbol_source": "debuginfod"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"score": 0.742,
|
||||
"breakdown": [
|
||||
{"factor": "cvss", "weight": 0.45, "explanation": "Normalized CVSS v4 base score (0–10 → 0–1)."},
|
||||
{"factor": "epss", "weight": 0.35, "explanation": "EPSS probability of exploitation in the wild."},
|
||||
{"factor": "exploitability", "weight": 0.10, "explanation": "Runtime exploit signals (if any)."},
|
||||
{"factor": "callstack_match", "weight": 0.10, "explanation": "Analyzer call‑stack ↔ vulnerable symbol match confidence."}
|
||||
],
|
||||
"signed_score_dsse": "base64(dsse-envelope)",
|
||||
"replay_verification": {
|
||||
"replay_success": true,
|
||||
"replay_success_ratio": 1.0,
|
||||
"verify_time_ms": 1120,
|
||||
"symbol_coverage_pct": 83.4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Deterministic math (fixed, auditable)
|
||||
|
||||
* Normalize CVSS: `cvss_n = clamp(cvss_v4.score / 10, 0, 1)`
|
||||
* Use EPSS directly: `epss_n = clamp(epss, 0, 1)`
|
||||
* Analyzer channels (each 0–1 from your evidence engine):
|
||||
|
||||
* `exploitability_n` (e.g., known IOC hits, honeypot signals, etc.)
|
||||
* `callstack_n` (e.g., symbol‑level match confidence)
|
||||
|
||||
**Fixed rational weights (exact decimals):**
|
||||
|
||||
* `w_cvss = 0.45`, `w_epss = 0.35`, `w_expl = 0.10`, `w_stack = 0.10`
|
||||
* Sum = `1.00` exactly (store as fixed‑precision decimals, e.g., Q16.16 or `decimal(6,5)`)
|
||||
|
||||
**Score:**
|
||||
|
||||
```
|
||||
score = (w_cvss*cvss_n) + (w_epss*epss_n) + (w_expl*exploitability_n) + (w_stack*callstack_n)
|
||||
```
|
||||
|
||||
No randomness. If inputs are identical, output is identical.
|
||||
|
||||
---
|
||||
|
||||
# Canonical inputs & signing
|
||||
|
||||
* Create a **JCS** (JSON Canonicalization Scheme) of the request after normalizing numeric precision.
|
||||
* Hash with SHA‑256 → publish the digest in the DSSE payload.
|
||||
* Sign DSSE with your service key (e.g., Sigstore‑style keyless or KMS key).
|
||||
* Return `signed_score_dsse` + include the exact **JCS** you used inside the envelope so downstream verifiers can re‑compute and validate.
|
||||
|
||||
---
|
||||
|
||||
# Replay hooks (for CI + “Verify” buttons)
|
||||
|
||||
Implement three internal functions and expose them as admin ops or test endpoints:
|
||||
|
||||
* `seeded_replay(seed)` — runs the scoring with the given seed and the exact stored JCS input; proves determinism across runs.
|
||||
* `permutation_test(n)` — randomizes **ordering only** of non‑keyed evidence to show order‑independence; expect identical outputs.
|
||||
* `offline_bundle_replay(bundle_uri)` — replays using a frozen symbol/debug bundle (no network); ensures air‑gap verifiability.
|
||||
|
||||
**Telemetry & gates**
|
||||
|
||||
* Release gate: require `replay_success_ratio ≥ 0.95`.
|
||||
* UI “Verify” button: median `verify_time_ms ≤ 3000`.
|
||||
* Track `fp_escalations_total` and `symbol_coverage_pct`; use as release criteria.
|
||||
|
||||
* Trade‑off: higher weight on `callstack_match` → better explainability but requires broader symbol retention (privacy/storage) and increases verifier CPU/latency.
|
||||
|
||||
---
|
||||
|
||||
# Drop‑in sketch (C# minimal)
|
||||
|
||||
```csharp
|
||||
public record ScoreRequest(
|
||||
string evidence_jcs_hash, string? cve,
|
||||
Cvss cvss_v4, decimal epss, string analyzer_manifest,
|
||||
int deterministic_seed, Replay replay_constraints);
|
||||
public record Cvss(string vector, decimal score);
|
||||
public record Replay(int max_cpu_ms, string unwind_mode, string symbol_source);
|
||||
|
||||
public static class Scorer {
|
||||
static readonly decimal wCvss = 0.45m, wEpss = 0.35m, wExpl = 0.10m, wStack = 0.10m;
|
||||
|
||||
public static decimal Compute(ScoreRequest r, decimal exploitability_n, decimal callstack_n) {
|
||||
decimal cvss_n = Clamp(r.cvss_v4.score / 10m);
|
||||
decimal epss_n = Clamp(r.epss);
|
||||
return Round4(wCvss*cvss_n + wEpss*epss_n + wExpl*Clamp(exploitability_n) + wStack*Clamp(callstack_n));
|
||||
}
|
||||
static decimal Clamp(decimal v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
||||
static decimal Round4(decimal v) => Math.Round(v, 4, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Example
|
||||
|
||||
**Request**
|
||||
|
||||
```json
|
||||
{
|
||||
"evidence_jcs_hash": "sha256",
|
||||
"cve": "CVE-2025-12345",
|
||||
"cvss_v4": {"vector":"T:AV:N/AC:L/AT:N/PR:N/UI:N/S:U/C:H/I:H/A:H","score":9.0},
|
||||
"epss": 0.22,
|
||||
"analyzer_manifest": "evidence://builds/ro-2026-02-25-001",
|
||||
"deterministic_seed": 42,
|
||||
"replay_constraints": {"max_cpu_ms": 3000, "unwind_mode": "partial", "symbol_source": "bundle"}
|
||||
}
|
||||
```
|
||||
|
||||
**Effective analyzer channels** (from your evidence engine):
|
||||
|
||||
```
|
||||
exploitability_n = 0.3
|
||||
callstack_n = 0.8
|
||||
```
|
||||
|
||||
**Score**
|
||||
|
||||
```
|
||||
= 0.45*(0.9) + 0.35*(0.22) + 0.10*(0.3) + 0.10*(0.8)
|
||||
= 0.405 + 0.077 + 0.03 + 0.08
|
||||
= 0.592
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Operational notes (Stella Ops fit)
|
||||
|
||||
* Put the service behind **EvidenceLocker**; store the request JCS, DSSE, and the replay vector.
|
||||
* Expose a **“Recompute & Verify”** button on each finding; display `symbol_coverage_pct`, `verify_time_ms`, and the signed breakdown.
|
||||
* Let **Attestor** gate promotions with `replay_success_ratio` and DSSE verification status.
|
||||
* Keep weights in a **BUSL‑guarded policy file** (decimal literals), versioned and change‑controlled; any change is a policy release.
|
||||
|
||||
---
|
||||
|
||||
# Quick contract to share with integrators
|
||||
|
||||
```bash
|
||||
curl -sS https://stella.local/v1/score \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d @payload.json | jq .
|
||||
```
|
||||
|
||||
* If integrators recompute: they must JCS‑canonicalize your response’s `inputs` object and verify the DSSE over its SHA‑256.
|
||||
* If any dependent input changes (EPSS refresh, CVSS re‑base), **score will change**, but **for the same inputs** the score is identical across machines.
|
||||
|
||||
---
|
||||
|
||||
Want me to turn this into a ready‑to‑run .NET minimal API (with DSSE using your KMS, plus a tiny verifier CLI) and wire it into Stella Ops’ AdvisoryAI module?
|
||||
@@ -0,0 +1,54 @@
|
||||
Here’s a super-practical “verifier recipe” you can drop into Stella Ops to validate supply‑chain attestations and Rekor v2 tiles end‑to‑end.
|
||||
|
||||
# 0) Quick background (so the terms make sense)
|
||||
|
||||
* **in‑toto Statement**: a tiny wrapper that says “this attestation is about artifact X with digest Y; the payload (predicate) is of type Z (e.g., SLSA Provenance).” ([GitHub][1])
|
||||
* **DSSE**: a signing envelope format (signatures over `payloadType` + canonicalized `payload` bytes). ([GitHub][2])
|
||||
* **Rekor v2 tiles**: transparency log moved to a **tile‑backed** layout; clients fetch tiles and compute inclusion proofs locally (no “get by index” API). ([Sigstore Blog][3])
|
||||
* **JCS**: a deterministic JSON canonicalization used when hashing/validating JSON payload bytes. ([RFC Editor][4])
|
||||
|
||||
# 1) Match the attestation to the artifact (Statement checks)
|
||||
|
||||
* Load the in‑toto **Statement**. Confirm each `subject[*].name` and `subject[*].digest` matches the artifact you’re verifying.
|
||||
* Assert the **`predicateType`** is recognized (e.g., `https://slsa.dev/provenance` / v0.1–v1.x) and, if present, validate **`predicate.materials`** (inputs) against expected sources. This binds “what was built” and “from what.” ([GitHub][1])
|
||||
|
||||
# 2) Verify DSSE signatures (bytes matter)
|
||||
|
||||
* **Canonicalize** the DSSE *payload bytes* using DSSE’s own serialization rules; verify the DSSE signature against the signer’s public key (or Sigstore bundle chain if you use that path). ([GitHub][2])
|
||||
* Before any policy hash checks over JSON, **re‑canonicalize** the payload using **JCS** so downstream hashing is deterministic across platforms. ([RFC Editor][4])
|
||||
|
||||
# 3) Prove Rekor inclusion (tiles, not point lookups)
|
||||
|
||||
* **Prefer** the `inclusion_proof` returned at upload time—store it with the bundle to avoid reconstructing later. ([GitHub][5])
|
||||
* If missing, **assemble the minimal tile set** from Rekor v2 endpoints (client‑side), then verify:
|
||||
a) merkle inclusion for the entry’s leaf, and
|
||||
b) the inclusion proof’s **checkpoint** against the Rekor v2 checkpoint.
|
||||
Rekor v2 intentionally removed “get by index/leaf hash”; clients fetch tiles and compute proofs locally. ([Sigstore Blog][3])
|
||||
|
||||
---
|
||||
|
||||
## How to wire this into Stella Ops (concise plan)
|
||||
|
||||
* **Verifier service** (AdvisoryAI/EvidenceLocker boundary):
|
||||
|
||||
* Input: `{artifactPath|digest, dsseEnvelope|bundle, optional inclusion_proof}`.
|
||||
* Steps: (1) Statement match → (2) DSSE verify → (3) Inclusion verify → (4) Policy (SLSA fields, materials allow‑list).
|
||||
* **Policy hooks**: add simple YAML policies (e.g., allowed builders, required `materials[]` domains, min SLSA predicate version). ([SLSA][6])
|
||||
* **Caching**: persist tiles + checkpoints per tree size to avoid refetch.
|
||||
* **UI**: in Release Bundle > Evidence tab show: “Subject match ✅ / DSSE sig ✅ / Inclusion ✅ (treeSize, rootHash, checkpoint origin)”.
|
||||
|
||||
## Pitfalls to avoid
|
||||
|
||||
* Hashing the JSON *without* JCS and getting platform‑specific diffs. (Use JCS before any JSON‑level policy hashing.) ([RFC Editor][4])
|
||||
* Treating Rekor v2 like v1 (no direct “get by index” reads; fetch tiles and compute locally). ([Sigstore Blog][3])
|
||||
* Ignoring `predicateType` evolution; track the URI (it encodes major version semantics). ([SLSA][7])
|
||||
|
||||
If you want, I can sketch a tiny .NET verifier module (interfaces + test vectors) that plugs into Stella Ops’s EvidenceLocker and uses the Rekor v2 tile client model.
|
||||
|
||||
[1]: https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md?utm_source=chatgpt.com "attestation/spec/v1/statement.md at main · in-toto/attestation"
|
||||
[2]: https://github.com/secure-systems-lab/dsse?utm_source=chatgpt.com "DSSE: Dead Simple Signing Envelope"
|
||||
[3]: https://blog.sigstore.dev/rekor-v2-ga/?utm_source=chatgpt.com "Rekor v2 GA - Cheaper to run, simpler to maintain"
|
||||
[4]: https://www.rfc-editor.org/rfc/rfc8785?utm_source=chatgpt.com "RFC 8785: JSON Canonicalization Scheme (JCS)"
|
||||
[5]: https://github.com/sigstore/rekor?utm_source=chatgpt.com "sigstore/rekor: Software Supply Chain Transparency Log"
|
||||
[6]: https://slsa.dev/spec/v0.1/provenance?utm_source=chatgpt.com "Provenance"
|
||||
[7]: https://slsa.dev/spec/v0.1/verification_summary?utm_source=chatgpt.com "Verification Summary Attestation (VSA)"
|
||||
@@ -0,0 +1,28 @@
|
||||
I’m sharing this because the current state of scanner triage and trace UIs exposes the very disconnects you’ve been targeting — tools are *great* at finding issues, but the paths from *vulnerability to proven context* are still too brittle for reliable triage and automated workflows.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Scanner tools like **Snyk** are adding reachability analysis to help prioritize vulnerabilities by whether application code *can* call the affected functions — effectively analyzing call graphs to determine *reachable CVEs*. This uses static program analysis and AI heuristics to map paths from your app into vulnerability code, though it still acknowledges limitations where static paths aren’t fully known. ([Snyk Docs][1])
|
||||
Enterprise scanners such as **JFrog Xray** extend SCA into binaries and SBOMs, performing deep artifact scans and ingesting SBOM data (e.g., CycloneDX) to detect vulnerabilities and license risks — and they’re integrated into build and CI/CD lifecycles. ([JFrog][2])
|
||||
|
||||
While these tools excel at *surface detection* and prioritization based on static context, they don’t yet bridge the gap into **live, low‑latency trace or call‑stack verified evidence** the way observability UIs (Perfetto/Jaeger/Speedscope) do for performance and distributed traces. Those UIs let engineers visually inspect call stacks, timelines, and flamegraphs with tight symbol binding — something scanner consoles rarely provide in an actionable, signed form.
|
||||
|
||||
The contrast is clear in practice:
|
||||
|
||||
* **Scanner flows** (Snyk, Anchore/Grype, Xray, Wiz, Prisma Cloud) focus on detection and risk scoring, integrated with SBOMs and CI/CD. They stop short of *reliable runtime evidence playback* or *signed call‑stack histories* that can prove exploitability or triage decisions with cryptographic confidence. ([echo.ai][3])
|
||||
|
||||
* **Trace / profiling UIs** (Perfetto, Speedscope flamegraphs, Jaeger distributed tracing) provide interactive timelines with symbol resolution and execution context — the exact sort of evidence you’d want when determining if a reported issue truly matters in a given run. Yet scanners don’t emit this form of trace data, and observability tools aren’t wired into vulnerability pipelines by default.
|
||||
|
||||
That explains why your proposed targets — provenance aggregation, minimal repro anchoring, reachability/trace fusion, and in‑console timelines — are hitting core gaps in the ecosystem: current solutions optimize detection and prioritization, not *evidence-backed, low‑latency verification* in triage. In other words, we have deep scanning engines and *deep tracing UIs* — but not a cohesive, signed pipeline that ties them together in real time with actionable context.
|
||||
|
||||
The ecosystem today gives us strong static analysis and SBOM‑focused tools, but not the *runtime replay/verified call‑stack context* that would close the loop on triage confidence in high‑velocity CICD environments.
|
||||
|
||||
[1]: https://docs.snyk.io/manage-risk/prioritize-issues-for-fixing/reachability-analysis?utm_source=chatgpt.com "Reachability analysis - Homepage | Snyk User Docs"
|
||||
[2]: https://jfrog.com/xray/?utm_source=chatgpt.com "Xray | Software Composition Analysis (SCA) Tool"
|
||||
[3]: https://www.echo.ai/blog/best-container-scanning-tools?utm_source=chatgpt.com "10 Best Container Scanning Tools for 2025 - Echo"
|
||||
18
docs-archived/product/advisories/ARCHIVE_LOG_20260303.md
Normal file
18
docs-archived/product/advisories/ARCHIVE_LOG_20260303.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Advisory Archive Log - 2026-03-03
|
||||
|
||||
| Timestamp (UTC) | Source Name | Archived Name |
|
||||
| --- | --- | --- |
|
||||
| 2026-03-03T21:51:27Z | 20260220 - OCI 1.1 referrers compatibility across major registries.md | 20260220 - OCI 1.1 referrers compatibility across major registries.md |
|
||||
| 2026-03-03T21:51:27Z | 20260221 - Building a verifiable SBOM and attestation spine.md | 20260221 - Building a verifiable SBOM and attestation spine.md |
|
||||
| 2026-03-03T21:51:27Z | 20260221 - Four novel, testable moat hypotheses.md | 20260221 - Four novel, testable moat hypotheses.md |
|
||||
| 2026-03-03T21:51:27Z | 20260222 - Fuzz & mutation hardening suite.md | 20260222 - Fuzz & mutation hardening suite.md |
|
||||
| 2026-03-03T21:51:27Z | 20260223 - Auditor UX experiments measurement plan.md | 20260223 - Auditor UX experiments measurement plan.md |
|
||||
| 2026-03-03T21:51:27Z | 20260223 - Unified symbolization across platforms and vendors.md | 20260223 - Unified symbolization across platforms and vendors.md |
|
||||
| 2026-03-03T21:51:27Z | 20260224 - Deterministic tile verification with Rekor v2.md | 20260224 - Deterministic tile verification with Rekor v2 (superseded by 20260226).md |
|
||||
| 2026-03-03T21:51:27Z | 20260224 - Turning defensibility into measurable business moats.md | 20260224 - Turning defensibility into measurable business moats.md |
|
||||
| 2026-03-03T21:51:27Z | 20260226 - Deterministic call‑stack analysis and resolver strategy.md | 20260226 - Deterministic call‑stack analysis and resolver strategy.md |
|
||||
| 2026-03-03T21:51:27Z | 20260226 - Deterministic score service and replay control.md | 20260226 - Deterministic score service and replay control.md |
|
||||
| 2026-03-03T21:51:27Z | 20260226 - Deterministic tile verification with Rekor v2.md | 20260226 - Deterministic tile verification with Rekor v2.md |
|
||||
| 2026-03-03T21:51:27Z | 20260226 - Triage explainability four measurable fixes.md | 20260226 - Triage explainability four measurable fixes.md |
|
||||
|
||||
Deduplication note: `20260224 - Deterministic tile verification with Rekor v2.md` was archived as superseded by the canonical `20260226` advisory.
|
||||
Reference in New Issue
Block a user