feat(cli): Implement crypto plugin CLI architecture with regional compliance
Sprint: SPRINT_4100_0006_0001 Status: COMPLETED Implemented plugin-based crypto command architecture for regional compliance with build-time distribution selection (GOST/eIDAS/SM) and runtime validation. ## New Commands - `stella crypto sign` - Sign artifacts with regional crypto providers - `stella crypto verify` - Verify signatures with trust policy support - `stella crypto profiles` - List available crypto providers & capabilities ## Build-Time Distribution Selection ```bash # International (default - BouncyCastle) dotnet build src/Cli/StellaOps.Cli/StellaOps.Cli.csproj # Russia distribution (GOST R 34.10-2012) dotnet build -p:StellaOpsEnableGOST=true # EU distribution (eIDAS Regulation 910/2014) dotnet build -p:StellaOpsEnableEIDAS=true # China distribution (SM2/SM3/SM4) dotnet build -p:StellaOpsEnableSM=true ``` ## Key Features - Build-time conditional compilation prevents export control violations - Runtime crypto profile validation on CLI startup - 8 predefined profiles (international, russia-prod/dev, eu-prod/dev, china-prod/dev) - Comprehensive configuration with environment variable substitution - Integration tests with distribution-specific assertions - Full migration path from deprecated `cryptoru` CLI ## Files Added - src/Cli/StellaOps.Cli/Commands/CryptoCommandGroup.cs - src/Cli/StellaOps.Cli/Commands/CommandHandlers.Crypto.cs - src/Cli/StellaOps.Cli/Services/CryptoProfileValidator.cs - src/Cli/StellaOps.Cli/appsettings.crypto.yaml.example - src/Cli/__Tests/StellaOps.Cli.Tests/CryptoCommandTests.cs - docs/cli/crypto-commands.md - docs/implplan/SPRINT_4100_0006_0001_COMPLETION_SUMMARY.md ## Files Modified - src/Cli/StellaOps.Cli/StellaOps.Cli.csproj (conditional plugin refs) - src/Cli/StellaOps.Cli/Program.cs (plugin registration + validation) - src/Cli/StellaOps.Cli/Commands/CommandFactory.cs (command wiring) - src/Scanner/__Libraries/StellaOps.Scanner.Core/Configuration/PoEConfiguration.cs (fix) ## Compliance - GOST (Russia): GOST R 34.10-2012, FSB certified - eIDAS (EU): Regulation (EU) No 910/2014, QES/AES/AdES - SM (China): GM/T 0003-2012 (SM2), OSCCA certified ## Migration `cryptoru` CLI deprecated → sunset date: 2025-07-01 - `cryptoru providers` → `stella crypto profiles` - `cryptoru sign` → `stella crypto sign` ## Testing ✅ All crypto code compiles successfully ✅ Integration tests pass ✅ Build verification for all distributions (international/GOST/eIDAS/SM) Next: SPRINT_4100_0006_0002 (eIDAS plugin implementation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
Here’s a simple, practical way to make vulnerability “reachability” auditable and offline‑verifiable in Stella Ops without adding a lot of UI or runtime cost.
|
||||
|
||||

|
||||
|
||||
# What this is (plain English)
|
||||
|
||||
* **Call‑stack subgraph:** when we say a vuln is “reachable,” we really mean *some* functions in your code can eventually call the risky function. That tiny slice of the big call graph is the **subgraph**.
|
||||
* **Proof of exposure (PoE):** a compact bundle (think: a few kilobytes) that cryptographically proves *which* functions and edges make the vuln reachable in a specific build.
|
||||
* **Offline‑verifiable:** auditors can check the proof later, in an air‑gapped setting, using only hashes and your reproducible build IDs.
|
||||
|
||||
# The minimal data model
|
||||
|
||||
* **BuildID:** deterministic identifier (e.g., ELF Build‑ID or source‑of‑truth content hash).
|
||||
* **Nodes:** function identifiers `(module, symbol, debug‑addr, source:line?)`.
|
||||
* **Edges:** caller → callee (with optional guard predicates like feature flags).
|
||||
* **Entry set:** the function(s)/handlers reachable from runtime entrypoints (HTTP handlers, cron, CLI).
|
||||
* **Sink set:** vulnerable API(s)/function(s) tied to a CVE.
|
||||
* **Reachability proof:** `{BuildID, nodes[N], edges[E], entryRefs, sinkRefs, policyContext, toolVersions}` + DSSE signature.
|
||||
|
||||
# How it fits the Stella Ops ledger
|
||||
|
||||
* Store each **resolved call‑stack** as a **subgraph object** keyed by `(BuildID, vulnID, package@version)`.
|
||||
* Link it to:
|
||||
|
||||
* SBOM component node (CycloneDX/SPDX ref).
|
||||
* VEX claim (affected/not‑affected/under‑investigation).
|
||||
* Scan recipe (so anyone can replay the result).
|
||||
* Emit one **PoE artifact** per “(vuln, component) with reachability=true”.
|
||||
|
||||
# Why this helps
|
||||
|
||||
* **Binary precision + explainability:** even if you only have a container image, the PoE explains *why* it’s reachable.
|
||||
* **Auditor‑friendly:** tiny artifact, DSSE‑signed, replayable with a known scanner build.
|
||||
* **Noise control:** store reachability as first‑class evidence; triage focuses on subgraphs, not global graphs.
|
||||
|
||||
# Implementation guide (short and concrete)
|
||||
|
||||
**1) Extraction (per build)**
|
||||
|
||||
* Prefer source‑level graphs when available; otherwise:
|
||||
|
||||
* ELF/PE/Mach‑O symbol harvest + debug info (DWARF/PDB) if present.
|
||||
* Lightweight static call‑edge inference (import tables, PLT/GOT, relocation targets).
|
||||
* Optional dynamic trace sampling (eBPF hooks) to confirm hot edges.
|
||||
|
||||
**2) Resolution pipeline**
|
||||
|
||||
* Normalize function IDs: `ModuleHash:Symbol@Addr[:File:Line]`.
|
||||
* Compute **entry set** (framework adapters know HTTP/GRPC/CLI entrypoints).
|
||||
* Compute **sink set** via rulepack mapping CVEs → {module:function(s)}.
|
||||
* Run bounded graph search with **policy guards** (feature flags, platform, build tags).
|
||||
* Persist the **subgraph** + metadata.
|
||||
|
||||
**3) PoE artifact (OCI‑attached attestation)**
|
||||
|
||||
* Canonical JSON (stable sort, normalized IDs).
|
||||
* Include: BuildID, tool versions, policy digest, SBOM refs, VEX claim link, subgraph nodes/edges, minimal repro steps.
|
||||
* Sign via DSSE; attach as OCI ref to the image digest.
|
||||
|
||||
**4) Offline verification (auditor)**
|
||||
|
||||
* Inputs: PoE, image digest, SBOM slice.
|
||||
* Steps: verify DSSE → check BuildID ↔ image digest → confirm nodes/edges hashes → re‑evaluate policy (optional) → show minimal path(s) entry→sink.
|
||||
|
||||
# UI: keep it small
|
||||
|
||||
* **Evidence tab → “Proof of exposure”** pill on any reachable vuln row.
|
||||
* Click opens a tiny **path viewer** (entry→…→sink) with:
|
||||
|
||||
* path count, shortest path, guarded edges (badges for feature flags).
|
||||
* “Copy PoE JSON” and “Verify offline” instructions.
|
||||
* No separate heavy UI needed; reuse the existing vulnerability details drawer.
|
||||
|
||||
# C# shape (sketch)
|
||||
|
||||
```csharp
|
||||
record FunctionId(string ModuleHash, string Symbol, ulong Addr, string? File, int? Line);
|
||||
record Edge(FunctionId Caller, FunctionId Callee, string[] Guards);
|
||||
record Subgraph(string BuildId, string ComponentRef, string VulnId,
|
||||
IReadOnlyList<FunctionId> Nodes, IReadOnlyList<Edge> Edges,
|
||||
string[] EntryRefs, string[] SinkRefs,
|
||||
string PolicyDigest, string ToolchainDigest);
|
||||
|
||||
interface IReachabilityResolver {
|
||||
Subgraph Resolve(string buildId, string componentRef, string vulnId, ResolverOptions opts);
|
||||
}
|
||||
|
||||
interface IProofEmitter {
|
||||
byte[] EmitPoE(Subgraph g, PoeMeta meta); // canonical JSON bytes
|
||||
}
|
||||
```
|
||||
|
||||
# Policy hooks you’ll want from day one
|
||||
|
||||
* `fail_if_unknown_edges > N` in prod.
|
||||
* `require_guard_evidence` for claims like “feature off”.
|
||||
* `max_paths`/`max_depth` to keep proofs compact.
|
||||
* `source-first-but-fallback-binary` selection.
|
||||
|
||||
# Rollout plan (2 sprints)
|
||||
|
||||
* **Sprint A (MVP):** static graph, per‑component sinks, shortest path only, PoE JSON + DSSE sign, attach to image, verify‑cli.
|
||||
* **Sprint B (Hardening):** guard predicates, multiple paths with cap, eBPF confirmation toggle, UI path viewer, policy gates wired to release checks.
|
||||
@@ -0,0 +1,439 @@
|
||||
# Implementation Summary: Competitor Scanner UI Gap Closure
|
||||
|
||||
> **Date:** 2025-12-23
|
||||
> **Status:** Planning Complete, Implementation Ready
|
||||
> **Related Advisory:** [23-Dec-2026 - Competitor Scanner UI Breakdown.md](./23-Dec-2026%20-%20Competitor%20Scanner%20UI%20Breakdown.md)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document summarizes the comprehensive planning and design work completed to close competitive gaps identified in the "Competitor Scanner UI Breakdown" advisory. We've created **5 sprint plans**, **2 JSON schemas**, and **2 comprehensive documentation guides** that establish Stella Ops differentiators against Snyk Container, Anchore Enterprise, and Prisma Cloud.
|
||||
|
||||
---
|
||||
|
||||
## Gap Analysis Results
|
||||
|
||||
### Gaps Identified Against src/**/*.md
|
||||
|
||||
| Feature | Advisory Source | Stella Ops Status | Priority | Artifacts Created |
|
||||
|---------|----------------|-------------------|----------|-------------------|
|
||||
| **Signed Delta-Verdicts** | N/A (differentiator) | Foundation exists, integration missing | **HIGH** | Sprint, Schema, Docs |
|
||||
| **Replayable Evidence Packs** | N/A (differentiator) | Primitives exist, bundle missing | **HIGH** | Sprint, Schema, Docs |
|
||||
| **Reachability Proof Panels** | N/A (differentiator) | Backend exists, UI missing | **MEDIUM** | Sprint |
|
||||
| **UI Vulnerability Annotation** | Anchore Enterprise | API exists, UI workflow missing | **MEDIUM** | Sprint |
|
||||
| **Base Image Detection/Recs** | Snyk Container | Missing | **MEDIUM** | Sprint |
|
||||
| **Admin Audit Trail UI** | Prisma Cloud | Partial (decisions only) | **LOW** | *Deferred* |
|
||||
|
||||
---
|
||||
|
||||
## Deliverables Created
|
||||
|
||||
### Sprint Plans (5 Total)
|
||||
|
||||
| Sprint ID | Title | Priority | Components | Status |
|
||||
|-----------|-------|----------|------------|--------|
|
||||
| **SPRINT_3000_0100_0001** | Signed Delta-Verdicts | HIGH | Policy Engine, Attestor, Evidence Locker | Planning |
|
||||
| **SPRINT_3000_0100_0002** | Replayable Evidence Packs | HIGH | Evidence Locker, Policy Engine, Replay | Planning |
|
||||
| **SPRINT_4000_0100_0001** | Reachability Proof Panels UI | MEDIUM | Web (Angular), Policy APIs | Planning |
|
||||
| **SPRINT_4000_0100_0002** | UI-Driven Vulnerability Annotation | MEDIUM | Web, Findings Ledger, Excititor | Planning |
|
||||
| **SPRINT_3000_0100_0003** | Base Image Detection & Recommendations | MEDIUM | Scanner, Policy Engine | Planning |
|
||||
|
||||
**Location:** `docs/implplan/SPRINT_3000_0100_*.md`, `docs/implplan/SPRINT_4000_0100_*.md`
|
||||
|
||||
### JSON Schemas (2 Total)
|
||||
|
||||
| Schema | URI | Purpose | Status |
|
||||
|--------|-----|---------|--------|
|
||||
| **Policy Verdict Predicate** | `https://stellaops.dev/predicates/policy-verdict@v1` | DSSE predicate for signed verdicts | Complete |
|
||||
| **Evidence Pack Manifest** | `https://stellaops.dev/evidence-pack@v1` | Replayable bundle manifest | Complete |
|
||||
|
||||
**Location:** `docs/schemas/stellaops-policy-verdict.v1.schema.json`, `docs/schemas/stellaops-evidence-pack.v1.schema.json`
|
||||
|
||||
### Documentation (2 Comprehensive Guides)
|
||||
|
||||
| Document | Scope | Status |
|
||||
|----------|-------|--------|
|
||||
| **[Policy Verdict Attestations](../policy/verdict-attestations.md)** | API, CLI, implementation guide, troubleshooting | Complete |
|
||||
| **[Evidence Pack Schema](../evidence-locker/evidence-pack-schema.md)** | Pack format, replay workflow, air-gap transfer | Complete |
|
||||
|
||||
---
|
||||
|
||||
## Competitive Differentiation Matrix
|
||||
|
||||
### Stella Ops vs Competitors
|
||||
|
||||
| Feature | Snyk | Anchore | Prisma | **Stella Ops** |
|
||||
|---------|------|---------|--------|---------------|
|
||||
| **Signed Verdicts** | ❌ No | ❌ No | ❌ No | **✅ DSSE-wrapped, Rekor-anchored** |
|
||||
| **Evidence Packs** | ❌ Separate exports | ❌ Separate exports | ❌ Separate exports | **✅ Single signed bundle** |
|
||||
| **Replayable Policy** | ❌ No | ❌ No | ❌ No | **✅ Deterministic re-evaluation** |
|
||||
| **Proof Visualization** | ℹ️ Basic | ℹ️ Basic | ℹ️ Basic | **✅ Cryptographic verification UI** |
|
||||
| **VEX Auto-Generation** | ❌ Manual | ⚠️ UI annotation | ❌ Manual | **✅ Smart-Diff auto-emit + approval** |
|
||||
| **Base Image Detection** | ✅ Yes | ❌ No | ⚠️ Limited | **🚧 Planned (Sprint 3000_0100_0003)** |
|
||||
| **Custom Base Recs** | ✅ Yes | ❌ No | ❌ No | **🚧 Policy-driven from internal registry** |
|
||||
| **Admin Audit Trail** | ⚠️ Limited | ⚠️ Limited | ✅ Yes | **⚠️ Decisions only (future enhancement)** |
|
||||
| **Offline Support** | ❌ Cloud-only | ⚠️ Limited | ❌ Cloud-only | **✅ Air-gap first** |
|
||||
|
||||
**Legend:**
|
||||
- ✅ Full support
|
||||
- ⚠️ Partial support
|
||||
- ℹ️ Basic/limited
|
||||
- ❌ Not supported
|
||||
- 🚧 Planned/in progress
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Signed Delta-Verdicts Flow
|
||||
|
||||
```
|
||||
Policy Engine Evaluation
|
||||
↓
|
||||
PolicyExplainTrace (per finding)
|
||||
↓
|
||||
VerdictPredicateBuilder
|
||||
↓
|
||||
VerdictAttestation Request → Attestor Service
|
||||
↓
|
||||
DSSE Signing + Optional Rekor Anchoring
|
||||
↓
|
||||
Evidence Locker Storage (PostgreSQL + Object Store)
|
||||
↓
|
||||
API: GET /api/v1/verdicts/{verdictId}
|
||||
```
|
||||
|
||||
**Key Differentiators:**
|
||||
- **Cryptographic Binding:** Each verdict cryptographically signed, tamper-evident
|
||||
- **Granular Attestations:** One attestation per finding (not batch)
|
||||
- **Transparency Option:** Rekor anchoring for public auditability
|
||||
- **Offline Verification:** Signature verification without network
|
||||
|
||||
### Replayable Evidence Packs Flow
|
||||
|
||||
```
|
||||
Policy Run Completion
|
||||
↓
|
||||
Pack Assembly Trigger
|
||||
↓
|
||||
Collect: Policy + SBOMs + Advisories + VEX + Verdicts + Reachability
|
||||
↓
|
||||
Generate Manifest (content index + determinism hash)
|
||||
↓
|
||||
Sign Manifest (DSSE)
|
||||
↓
|
||||
Compress to Tarball (.tar.gz)
|
||||
↓
|
||||
Store in Object Store + Index in PostgreSQL
|
||||
↓
|
||||
Download → Transfer → Replay on Any Environment
|
||||
```
|
||||
|
||||
**Key Differentiators:**
|
||||
- **Complete Context:** Single bundle contains all evaluation inputs
|
||||
- **Deterministic Replay:** Bit-for-bit reproducible verdicts
|
||||
- **Queryable Offline:** Inspect without external APIs
|
||||
- **Air-Gap Transfer:** Sign once, verify anywhere
|
||||
|
||||
---
|
||||
|
||||
## Implementation Roadmap
|
||||
|
||||
### Phase 1: HIGH Priority (Weeks 1-4)
|
||||
|
||||
**SPRINT_3000_0100_0001 — Signed Delta-Verdicts**
|
||||
|
||||
*Week 1-2:*
|
||||
- [ ] Implement `VerdictPredicateBuilder` in Policy Engine
|
||||
- [ ] Wire Policy Engine → Attestor integration
|
||||
- [ ] Implement `VerdictAttestationHandler` in Attestor
|
||||
- [ ] Evidence Locker storage schema + API endpoints
|
||||
|
||||
*Week 3-4:*
|
||||
- [ ] CLI commands (`stella verdict get/verify/list`)
|
||||
- [ ] Integration tests (Policy Run → Verdict Attestation → Retrieval → Verification)
|
||||
- [ ] Rekor anchoring integration (optional)
|
||||
- [ ] Documentation finalization
|
||||
|
||||
**SPRINT_3000_0100_0002 — Replayable Evidence Packs**
|
||||
|
||||
*Week 1-2:*
|
||||
- [ ] Implement `EvidencePackAssembler` in Evidence Locker
|
||||
- [ ] Pack assembly workflow (collect artifacts, generate manifest, sign, compress)
|
||||
- [ ] Pack storage (object store + PostgreSQL index)
|
||||
- [ ] API endpoints (`POST /runs/{id}/evidence-pack`, `GET /packs/{id}`, etc.)
|
||||
|
||||
*Week 3-4:*
|
||||
- [ ] Implement `ReplayService` in Policy Engine
|
||||
- [ ] Replay workflow (extract → deserialize → re-evaluate → compare)
|
||||
- [ ] CLI commands (`stella pack create/download/inspect/verify/replay`)
|
||||
- [ ] Integration tests (determinism validation, air-gap transfer)
|
||||
|
||||
**Success Metrics:**
|
||||
- ✅ Every policy run produces signed verdicts
|
||||
- ✅ Evidence packs replay with 100% determinism
|
||||
- ✅ CLI can verify signatures offline
|
||||
- ✅ API endpoints documented and tested
|
||||
|
||||
### Phase 2: MEDIUM Priority (Weeks 5-8)
|
||||
|
||||
**SPRINT_4000_0100_0001 — Reachability Proof Panels UI**
|
||||
|
||||
*Dependencies:* SPRINT_3000_0100_0001 (verdict attestation API)
|
||||
|
||||
- [ ] Design UI mockups for proof panel
|
||||
- [ ] Implement `VerdictProofPanelComponent` (Angular)
|
||||
- [ ] Integrate with verdict API + signature verification
|
||||
- [ ] Render evidence chain (advisory → SBOM → VEX → reachability → verdict)
|
||||
- [ ] Storybook stories + E2E tests
|
||||
|
||||
**SPRINT_4000_0100_0002 — UI-Driven Vulnerability Annotation**
|
||||
|
||||
- [ ] Define vulnerability state machine in Findings Ledger
|
||||
- [ ] Implement triage dashboard UI (Angular)
|
||||
- [ ] VEX candidate review/approval workflow
|
||||
- [ ] API: `PATCH /findings/{id}/state`, `POST /vex-candidates/{id}/approve`
|
||||
- [ ] E2E tests for annotation workflow
|
||||
|
||||
**SPRINT_3000_0100_0003 — Base Image Detection & Recommendations**
|
||||
|
||||
- [ ] Create `StellaOps.Scanner.BaseImage` library
|
||||
- [ ] Implement Dockerfile parser + OCI manifest analyzer
|
||||
- [ ] Build approved image registry schema
|
||||
- [ ] Recommendation engine logic
|
||||
- [ ] API endpoints + CLI commands
|
||||
|
||||
**Success Metrics:**
|
||||
- ✅ Proof panel visualizes verdict evidence chain
|
||||
- ✅ Triage dashboard enables UI-driven VEX approval
|
||||
- ✅ Base image recommendations from internal registry
|
||||
|
||||
### Phase 3: Enhancements (Weeks 9+)
|
||||
|
||||
- [ ] Admin audit trail UI (comprehensive activity logging)
|
||||
- [ ] Pack retention policies + automated archiving
|
||||
- [ ] Batch verdict signing optimization
|
||||
- [ ] Evidence pack incremental updates
|
||||
- [ ] Policy replay diff visualization
|
||||
|
||||
---
|
||||
|
||||
## Technical Specifications
|
||||
|
||||
### Verdict Attestation Predicate
|
||||
|
||||
**Type:** `https://stellaops.dev/predicates/policy-verdict@v1`
|
||||
|
||||
**Key Fields:**
|
||||
- `verdict.status`: passed | warned | blocked | quieted | ignored
|
||||
- `ruleChain`: Ordered policy rule execution trace
|
||||
- `evidence`: Advisory, VEX, reachability, SBOM evidence with digests
|
||||
- `reachability.status`: confirmed | likely | present | unreachable | unknown
|
||||
- `metadata.determinismHash`: SHA256 of verdict computation
|
||||
|
||||
**Signing:** DSSE envelope, Ed25519/ECDSA/RSA-PSS
|
||||
|
||||
**Storage:** PostgreSQL (verdict_attestations table) + optional Rekor
|
||||
|
||||
### Evidence Pack Manifest
|
||||
|
||||
**Type:** `https://stellaops.dev/evidence-pack@v1`
|
||||
|
||||
**Structure:**
|
||||
- `contents.policy`: Policy definition + run metadata
|
||||
- `contents.sbom`: SPDX/CycloneDX SBOMs
|
||||
- `contents.advisories`: Timestamped CVE snapshots
|
||||
- `contents.vex`: OpenVEX statements
|
||||
- `contents.verdicts`: DSSE-wrapped verdict attestations
|
||||
- `contents.reachability`: Drift + slice analysis
|
||||
|
||||
**Determinism:** `determinismHash` = SHA256(sorted content digests)
|
||||
|
||||
**Signing:** Manifest signature covers all content digests
|
||||
|
||||
**Format:** Compressed tarball (`.tar.gz`)
|
||||
|
||||
---
|
||||
|
||||
## API Summary
|
||||
|
||||
### Verdict Attestation APIs
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| `GET` | `/api/v1/verdicts/{verdictId}` | Retrieve verdict attestation (DSSE envelope) |
|
||||
| `GET` | `/api/v1/runs/{runId}/verdicts` | List verdicts for policy run (filters: status, severity) |
|
||||
| `POST` | `/api/v1/verdicts/{verdictId}/verify` | Verify signature + optional Rekor inclusion proof |
|
||||
|
||||
### Evidence Pack APIs
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
|--------|----------|---------|
|
||||
| `POST` | `/api/v1/runs/{runId}/evidence-pack` | Create evidence pack for policy run |
|
||||
| `GET` | `/api/v1/evidence-packs/{packId}` | Download pack tarball |
|
||||
| `GET` | `/api/v1/evidence-packs/{packId}/manifest` | Inspect manifest (no download) |
|
||||
| `POST` | `/api/v1/evidence-packs/{packId}/replay` | Replay policy evaluation from pack |
|
||||
| `POST` | `/api/v1/evidence-packs/{packId}/verify` | Verify pack signature + content integrity |
|
||||
|
||||
---
|
||||
|
||||
## CLI Summary
|
||||
|
||||
### Verdict Commands
|
||||
|
||||
```bash
|
||||
stella verdict get <verdictId> # Retrieve verdict
|
||||
stella verdict verify <verdict.json> --public-key <key> # Verify signature (offline)
|
||||
stella verdict list --run <runId> --status blocked # List verdicts for run
|
||||
stella verdict download <verdictId> --output <file> # Download DSSE envelope
|
||||
```
|
||||
|
||||
### Evidence Pack Commands
|
||||
|
||||
```bash
|
||||
stella pack create <runId> # Create pack
|
||||
stella pack download <packId> --output <file> # Download pack tarball
|
||||
stella pack inspect <pack.tar.gz> # Display manifest + stats
|
||||
stella pack list <pack.tar.gz> # List all files in pack
|
||||
stella pack export <pack.tar.gz> --artifact <path> # Extract single artifact
|
||||
stella pack verify <pack.tar.gz> # Verify signature + integrity
|
||||
stella pack replay <pack.tar.gz> # Replay policy evaluation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- [ ] Verdict predicate builder (canonical JSON, determinism)
|
||||
- [ ] Evidence pack assembler (manifest generation, determinism hash)
|
||||
- [ ] Replay service (deserialization, comparison logic)
|
||||
- [ ] Schema validation (JSON schema compliance)
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- [ ] End-to-end: Policy Run → Verdict Attestation → Storage → Retrieval → Verification
|
||||
- [ ] End-to-end: Pack Assembly → Storage → Download → Replay → Determinism Validation
|
||||
- [ ] Cross-environment: Create pack on env A, replay on env B (air-gap scenario)
|
||||
- [ ] Signature verification (offline, no network)
|
||||
|
||||
### Performance Tests
|
||||
|
||||
- [ ] Verdict attestation throughput (1M verdicts/hour target)
|
||||
- [ ] Pack assembly time (< 2min for 10K findings)
|
||||
- [ ] Replay time (< 60s for 10K verdicts)
|
||||
- [ ] Storage scaling (100K packs, query performance)
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Cryptographic Guarantees
|
||||
|
||||
- **Verdict Attestations:** DSSE-signed, tamper-evident, optional Rekor transparency
|
||||
- **Evidence Packs:** Manifest signature, per-file digests, determinism hash
|
||||
- **Key Management:** KMS, CryptoPro (GOST), offline signing ceremonies
|
||||
- **Verification:** Offline-capable, no network required
|
||||
|
||||
### Access Control
|
||||
|
||||
- **RBAC Scopes:**
|
||||
- `policy:verdict:read` — View verdict attestations
|
||||
- `policy:pack:create` — Create evidence packs
|
||||
- `policy:pack:read` — Download evidence packs
|
||||
- `policy:replay` — Replay policy evaluations
|
||||
|
||||
- **Tenant Isolation:** All artifacts scoped by `tenantId`, cross-tenant queries blocked
|
||||
|
||||
### Audit Trail
|
||||
|
||||
- All verdict retrievals logged with actor, timestamp, tenant
|
||||
- Pack creation/download/replay logged for compliance
|
||||
- Signature verification failures alerted
|
||||
|
||||
---
|
||||
|
||||
## Determinism Validation
|
||||
|
||||
### Verdict Determinism
|
||||
|
||||
**Inputs:**
|
||||
- Policy definition (P-7 v4)
|
||||
- SBOM (sbom:S-42)
|
||||
- Advisory snapshot (at cursor timestamp)
|
||||
- VEX snapshot (at cursor timestamp)
|
||||
- Environment context
|
||||
|
||||
**Output:** Verdict with `determinismHash` = SHA256(sorted evidence digests)
|
||||
|
||||
**Validation:** Re-evaluate with identical inputs → same `determinismHash`
|
||||
|
||||
### Pack Replay Determinism
|
||||
|
||||
**Inputs:** Evidence pack manifest (all artifacts bundled)
|
||||
|
||||
**Output:** Replay verdicts
|
||||
|
||||
**Validation:** Compare replay verdicts to original verdicts:
|
||||
- Count match: 234 original, 234 replay ✓
|
||||
- Status match: All verdicts have identical status ✓
|
||||
- Hash match: All `determinismHash` values identical ✓
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate Actions (This Week)
|
||||
|
||||
1. **Review & Approve:** Technical designs for SPRINT_3000_0100_0001 and SPRINT_3000_0100_0002
|
||||
2. **Kickoff:** SPRINT_3000_0100_0001 (Signed Delta-Verdicts) implementation
|
||||
3. **Code Generation:** Create C# models from JSON schemas
|
||||
4. **Database Migrations:** Prepare PostgreSQL schema for `verdict_attestations` and `evidence_packs` tables
|
||||
|
||||
### Week 1 Milestones
|
||||
|
||||
- [ ] `VerdictPredicateBuilder` implemented with unit tests
|
||||
- [ ] Policy Engine → Attestor integration wired (feature-flagged)
|
||||
- [ ] `VerdictAttestationHandler` accepts and signs predicates
|
||||
- [ ] Evidence Locker storage + API endpoints (basic CRUD)
|
||||
|
||||
### Month 1 Goal
|
||||
|
||||
- ✅ Every policy run produces signed verdict attestations
|
||||
- ✅ CLI can retrieve and verify verdicts offline
|
||||
- ✅ Evidence packs can be created for policy runs
|
||||
- ✅ Integration tests pass with 100% determinism
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Adoption Metrics
|
||||
|
||||
- **Verdict Attestations:** 100% of policy runs emit signed verdicts
|
||||
- **Evidence Pack Usage:** 10+ packs created per day per tenant
|
||||
- **Replay Success Rate:** 99%+ determinism verification
|
||||
|
||||
### Performance Metrics
|
||||
|
||||
- **Verdict Attestation Latency:** < 100ms per verdict
|
||||
- **Pack Assembly Time:** < 2min for 10K findings
|
||||
- **Replay Time:** < 60s for 10K verdicts
|
||||
- **API Latency:** p95 < 500ms for verdict/pack retrieval
|
||||
|
||||
### Quality Metrics
|
||||
|
||||
- **Test Coverage:** > 90% for attestation + pack code
|
||||
- **Schema Compliance:** 100% of artifacts validate against JSON schemas
|
||||
- **Determinism Rate:** 100% replay verdicts match original
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Sprint Plans:** `docs/implplan/SPRINT_3000_0100_*.md`, `docs/implplan/SPRINT_4000_0100_*.md`
|
||||
- **Schemas:** `docs/schemas/stellaops-policy-verdict.v1.schema.json`, `docs/schemas/stellaops-evidence-pack.v1.schema.json`
|
||||
- **Documentation:** `docs/policy/verdict-attestations.md`, `docs/evidence-locker/evidence-pack-schema.md`
|
||||
- **Advisory:** `docs/product-advisories/23-Dec-2026 - Competitor Scanner UI Breakdown.md`
|
||||
@@ -0,0 +1,714 @@
|
||||
Here’s a compact blueprint for two high‑leverage Stella Ops capabilities that cut false positives and make audits portable across jurisdictions.
|
||||
|
||||
# 1) Patch‑aware backport detector (no humans in loop)
|
||||
|
||||
**Goal:** Stop flagging CVEs when a distro backported the fix but kept the old version string.
|
||||
|
||||
**How it works—in plain terms**
|
||||
|
||||
* **Compile equivalence maps per distro:**
|
||||
|
||||
* BuildID → symbol ranges → hunk hashes for core libraries/kernels.
|
||||
* For each upstream CVE fix, store the minimal “hunk signature” (function, file path, before/after diff hash).
|
||||
* **Auto‑diff at scan time:**
|
||||
|
||||
* From a container/VM, collect ELF BuildIDs and symbol tables (or BTF for kernels).
|
||||
* Match against the equivalence map; if patched hunks are present, mark the artifact “fixed‑by‑backport”.
|
||||
* **Emit proof‑carrying VEX:**
|
||||
|
||||
* Generate a signed VEX entry with `status:not_affected`, `justification: patched-backport`, and attach a **proof blob**: (artifact BuildIDs, matched hunk IDs, upstream commit refs, deterministic diff snippet).
|
||||
* **Release‑gate policy:**
|
||||
|
||||
* Gate only passes if (a) VEX is signed by an approved issuer, (b) proof blob verifies against our equivalence map, (c) CVE scoring policy is met.
|
||||
|
||||
**Minimal data model**
|
||||
|
||||
* `EquivalenceMap{ distro, package, version_like, build_id, [HunkSig{file,func, pre_hash, post_hash, upstream_commit}] }`
|
||||
* `ProofBlob{ artifact_build_ids, matched_hunks[], verifier_log }`
|
||||
* `VEX{ subject=digest/ref, cve, status, justification, issued_by, dsse_sig, proof_ref }`
|
||||
|
||||
**Pipeline sketch (where to run what)**
|
||||
|
||||
* **Feedser**: pulls upstream CVE patches → extracts HunkSig.
|
||||
* **Sbomer**: captures BuildIDs for binaries in SBOM.
|
||||
* **Vexer**: matches hunks → emits VEX + proof.
|
||||
* **Authority/Attestor**: DSSE‑signs; stores in OCI referrers.
|
||||
* **Policy Engine**: enforces “accept only if proof verifies”.
|
||||
|
||||
**Testing targets (fast ROI)**
|
||||
|
||||
* glibc, openssl, zlib, curl, libxml2, Linux kernel LTS (common backports).
|
||||
|
||||
**Why it’s a moat**
|
||||
|
||||
* Precision jump without humans; reproducible proof beats “trust me” advisories.
|
||||
|
||||
---
|
||||
|
||||
# 2) Regional crypto & offline audit packs
|
||||
|
||||
**Goal:** Hand an auditor a single, sealed bundle that **replays identically** anywhere—while satisfying local crypto regimes.
|
||||
|
||||
**What’s inside the bundle**
|
||||
|
||||
* **Evidence:** SBOM (CycloneDX 1.6/SPDX 3.0.1), VEX set, reachability subgraph (source+post‑build), policy ledger with decisions.
|
||||
* **Attestations:** DSSE/in‑toto for each step.
|
||||
* **Replay manifest:** feed snapshots + rule versions + hashing seeds so a third party can re‑execute and get the same verdicts.
|
||||
|
||||
**Dual‑stack signing profiles**
|
||||
|
||||
* eIDAS / ETSI (EU), FIPS (US), GOST/SM (RU/CN regional), plus optional PQC (Dilithium/Falcon) profile.
|
||||
* Same content; different signature suites → auditor picks the locally valid one.
|
||||
|
||||
**Operating modes**
|
||||
|
||||
* **Connected:** push to an OCI registry with referrers and timestamping (Rekor‑compatible mirror).
|
||||
* **Air‑gapped:** tar+CAR archive with embedded TUF root, CRLs, and time‑stamped notary receipts.
|
||||
|
||||
**Verification UX (auditor‑friendly)**
|
||||
|
||||
* One command: `stella verify --bundle bundle.car` → prints
|
||||
(1) signature set validated, (2) replay hash match, (3) policy outcomes, (4) exceptions trail.
|
||||
|
||||
---
|
||||
|
||||
## Lightweight implementation plan (90‑day cut)
|
||||
|
||||
* **Weeks 1–3:**
|
||||
|
||||
* Extract HunkSig from upstream patches (git diff parser + normalizer).
|
||||
* Build ELF symbol/BuildID collector; store per‑distro maps.
|
||||
* **Weeks 4–6:**
|
||||
|
||||
* VEXer: matching engine + `not_affected: patched-backport` schema + ProofBlob.
|
||||
* DSSE signing with pluggable crypto providers; start with eIDAS+FIPS.
|
||||
* **Weeks 7–9:**
|
||||
|
||||
* Offline bundle format (CAR/TAR) + replay manifest + verifier CLI.
|
||||
* Policy gate: “accept if backport proof verifies”.
|
||||
* **Weeks 10–12:**
|
||||
|
||||
* Reachability subgraph export/import; deterministic re‑execution harness.
|
||||
* Docs + sample audits (openssl CVEs across Debian/Ubuntu/RHEL).
|
||||
|
||||
---
|
||||
|
||||
## UI hooks (keep it simple)
|
||||
|
||||
* **Finding:** “Backport Proofs” tab on a CVE detail → shows matched hunks and upstream commit links.
|
||||
* **Deciding:** Release diff view lists CVEs → green badges “Patched via Backport (proof‑verified)”.
|
||||
* **Auditing:** “Export Audit Pack” button at run level; pick signature profile(s); download bundle.
|
||||
|
||||
If you want, I can draft:
|
||||
|
||||
* the `HunkSig` extractor spec (inputs/outputs),
|
||||
* the VEX schema extension and DSSE envelopes,
|
||||
* the verifier CLI contract and sample CAR layout,
|
||||
* or the policy snippets to wire this into your release gates.
|
||||
Below is a developer-grade implementation guide for **patch-aware backport handling** across Alpine, Red Hat, Fedora, Debian, SUSE, Astra Linux, and “all other Linux used as Docker bases”. It is written as if you are building this inside Stella Ops (Feedser/Vexer/Sbomer/Scanner.Webservice, DSSE attestations, deterministic replay, Postgres+Valkey).
|
||||
|
||||
The key principle: **do not rely on upstream version strings**. For distros, “fixed” often means “patch backported with same NEVRA/version”. You must determine fix status by **distro patch metadata** plus **binary/source proof**.
|
||||
|
||||
---
|
||||
|
||||
## 0) What you are building
|
||||
|
||||
### Outputs (what must exist after implementation)
|
||||
|
||||
1. **DistroFix DB** (authoritative normalized knowledge)
|
||||
|
||||
* For each distro release + package + CVE:
|
||||
|
||||
* status: affected / fixed / not_affected / under_investigation / unknown
|
||||
* fixed range expressed in distro terms (epoch/version/release or deb version) and/or advisory IDs
|
||||
* proof pointers (errata, patch commit(s), SRPM/deb source, file hashes, build IDs)
|
||||
2. **Backport Proof Engine**
|
||||
|
||||
* Given an image and its installed packages, produce a **deterministic VEX**:
|
||||
|
||||
* `status=not_affected` with `justification=patched-backport`
|
||||
* proof blob: advisory id, package build provenance, patch signatures matched
|
||||
3. **Policy integration**
|
||||
|
||||
* Gating rules treat “backport proof verified” as first-class evidence.
|
||||
4. **Replayable scans**
|
||||
|
||||
* Same inputs (feed snapshots + rules + image digest) → same verdicts.
|
||||
|
||||
---
|
||||
|
||||
## 1) High-level approach (two-layer truth)
|
||||
|
||||
### Layer A — Distro intelligence (fast and usually sufficient)
|
||||
|
||||
For each distro, ingest its authoritative vulnerability metadata:
|
||||
|
||||
* advisory/errata streams
|
||||
* distro CVE trackers
|
||||
* security databases (Alpine secdb)
|
||||
* OVAL / CPE / CSAF if available
|
||||
* package repositories metadata
|
||||
|
||||
This provides “fixed in release X” at distro level.
|
||||
|
||||
### Layer B — Proof (needed for precision and audits)
|
||||
|
||||
When Layer A says “fixed” but the version looks “old”, prove it:
|
||||
|
||||
* **Source proof**: patch set present in source package (SRPM, debian patches, apkbuild git)
|
||||
* **Binary proof**: vulnerable function/hunk signature is patched in shipped binary (BuildID + symbol/hunk signature match)
|
||||
* **Build proof**: build metadata ties the binary to the source + patch set deterministically
|
||||
|
||||
You will use Layer B to:
|
||||
|
||||
* override false positives
|
||||
* produce auditor-grade evidence
|
||||
* operate offline with sealed snapshots
|
||||
|
||||
---
|
||||
|
||||
## 2) Core data model (Postgres schema guidance)
|
||||
|
||||
### 2.1 Canonical keys
|
||||
|
||||
You must normalize these identifiers:
|
||||
|
||||
* **Distro key**: `distro_family` + `distro_name` + `release` + `arch`
|
||||
|
||||
* e.g. `debian:12`, `rhel:9`, `alpine:3.19`, `sles:15sp5`, `astra:??`
|
||||
* **Package key**: canonical package name plus ecosystem type
|
||||
|
||||
* `apk`, `rpm`, `deb`
|
||||
* **CVE key**: `CVE-YYYY-NNNN`
|
||||
|
||||
### 2.2 Tables (minimum)
|
||||
|
||||
* `distro_release(id, family, name, version, codename, arch, eol_at, source)`
|
||||
* `pkg_name(id, ecosystem, name, normalized_name)`
|
||||
* `pkg_version(id, ecosystem, version_raw, version_norm, epoch, upstream_ver, release_ver)`
|
||||
* `advisory(id, distro_release_id, advisory_type, advisory_id, published_at, url, raw_json_hash, snapshot_id)`
|
||||
* `advisory_pkg(advisory_id, pkg_name_id, fixed_version_id NULL, fixed_range_json NULL, status, notes)`
|
||||
* `cve(id, cve_id, severity, cwe, description_hash)`
|
||||
* `cve_pkg_status(id, cve_id, distro_release_id, pkg_name_id, status, fixed_version_id NULL, advisory_id NULL, confidence, last_seen_snapshot_id)`
|
||||
* `source_artifact(id, type, url, sha256, size, fetched_in_snapshot_id)`
|
||||
|
||||
* SRPM, `.dsc`, `.orig.tar`, `apkbuild`, patch files
|
||||
* `patch_signature(id, cve_id, upstream_commit, file_path, function, pre_hash, post_hash, algo_version)`
|
||||
* `build_provenance(id, distro_release_id, pkg_nevra_or_debver, build_id, source_artifact_id, buildinfo_artifact_id, signer, signed_at)`
|
||||
* `binary_fingerprint(id, artifact_digest, path, elf_build_id, sha256, debuglink, arch)`
|
||||
* `proof_blob(id, subject_digest, cve_id, pkg_name_id, distro_release_id, proof_type, proof_json, sha256)`
|
||||
|
||||
### 2.3 Version comparison engines
|
||||
|
||||
Implement **three comparators**:
|
||||
|
||||
* `rpmvercmp` (RPM EVR rules)
|
||||
* `dpkg --compare-versions` equivalent (Debian version algorithm)
|
||||
* Alpine `apk` version rules (similar to semver-ish but not semver; implement per apk-tools logic)
|
||||
|
||||
Do not “approximate”. Implement exact comparators or call system libraries inside controlled container images.
|
||||
|
||||
---
|
||||
|
||||
## 3) Feed ingestion per distro (Layer A)
|
||||
|
||||
### 3.1 Alpine (apk)
|
||||
|
||||
**Primary data**
|
||||
|
||||
* Alpine secdb repository (per branch) mapping CVEs ↔ packages, fixed versions.
|
||||
|
||||
**Ingestion**
|
||||
|
||||
* Pull secdb for each supported Alpine branch (3.x).
|
||||
* Parse entries into `cve_pkg_status` with `fixed_version`.
|
||||
|
||||
**Package metadata**
|
||||
|
||||
* Pull `APKINDEX.tar.gz` for each repo (main/community) and arch.
|
||||
* Store package version + checksum.
|
||||
|
||||
**Notes**
|
||||
|
||||
* Alpine often explicitly lists fixed versions; backports are less “opaque” than enterprise distros, but still validate.
|
||||
|
||||
### 3.2 Red Hat Enterprise Linux (rhel) & UBI
|
||||
|
||||
**Primary data**
|
||||
|
||||
* Red Hat Security Data: CVE ↔ packages, errata, states.
|
||||
* Errata stream provides authoritative “fixed in RHSA-…”.
|
||||
|
||||
**Ingestion**
|
||||
|
||||
* For each RHEL major/minor you support (8, 9; optionally 7), pull:
|
||||
|
||||
* CVE objects + affected products + package states
|
||||
* Errata (RHSA) objects and their fixed package NEVRAs
|
||||
* Populate `advisory` + `advisory_pkg`.
|
||||
* Derive `cve_pkg_status` from errata.
|
||||
|
||||
**Package metadata**
|
||||
|
||||
* Use repository metadata (repomd.xml + primary.xml.gz) for BaseOS/AppStream/CRB, etc.
|
||||
* Record NEVRA and checksums.
|
||||
|
||||
**Enterprise backport reality**
|
||||
|
||||
* RHEL frequently backports fixes while keeping old upstream version. Your engine must prefer **errata fixed NEVRA** over upstream version meaning.
|
||||
|
||||
### 3.3 Fedora (rpm)
|
||||
|
||||
Fedora is closer to upstream; still ingest advisories.
|
||||
**Primary data**
|
||||
|
||||
* Fedora security advisories / updateinfo (often via repository updateinfo.xml.gz)
|
||||
* OVAL may exist for some streams.
|
||||
|
||||
**Ingestion**
|
||||
|
||||
* Parse updateinfo to map CVE → fixed NEVRA.
|
||||
* For Fedora rawhide/rolling, treat as high churn; snapshots must be time-bounded.
|
||||
|
||||
### 3.4 Debian (deb)
|
||||
|
||||
**Primary data**
|
||||
|
||||
* Debian Security Tracker (CVE status per release + package, fixed versions)
|
||||
* DSA advisories.
|
||||
|
||||
**Ingestion**
|
||||
|
||||
* Pull Debian security tracker data, parse per release (stable, oldstable).
|
||||
* Normalize Debian versions exactly.
|
||||
* Store “fixed in” version.
|
||||
|
||||
**Package metadata**
|
||||
|
||||
* Parse `Packages.gz` from security + main repos.
|
||||
* Optionally `Sources.gz` for source package mapping.
|
||||
|
||||
### 3.5 SUSE (SLES / openSUSE) (rpm)
|
||||
|
||||
**Primary data**
|
||||
|
||||
* SUSE security advisories (often published as CSAF; also SUSE OVAL historically)
|
||||
* Updateinfo in repos.
|
||||
|
||||
**Ingestion**
|
||||
|
||||
* Prefer CSAF/official advisory feed when available; otherwise parse `updateinfo.xml.gz`.
|
||||
* Map CVE → fixed packages.
|
||||
|
||||
### 3.6 Astra Linux (deb-family, often)
|
||||
|
||||
Astra is niche and may have bespoke advisories/mirrors.
|
||||
**Primary data**
|
||||
|
||||
* Astra security bulletins and repository metadata.
|
||||
* If they publish a tracker or advisories in a machine-readable format, ingest it; otherwise:
|
||||
|
||||
* treat repo metadata + changelogs as the canonical signal.
|
||||
|
||||
**Ingestion strategy**
|
||||
|
||||
* Implement a generic “Debian-family fallback”:
|
||||
|
||||
* ingest `Packages.gz` and `Sources.gz` from Astra repos
|
||||
* ingest available security bulletin feed (HTML/JSON); parse with a deterministic extractor
|
||||
* if advisories are sparse, rely on Layer B proof more heavily (source patch presence + binary proof)
|
||||
|
||||
### 3.7 “All other Linux used on docker repositories”
|
||||
|
||||
Handle this by **distro families** plus a plugin pattern:
|
||||
|
||||
* Debian family (Ubuntu, Kali, Astra, Mint): use Debian comparator + `Packages/Sources` + their security tracker if exists
|
||||
* RPM family (RHEL clones: Rocky/Alma/Oracle; Amazon Linux): rpm comparator + updateinfo/OVAL/errata equivalents
|
||||
* Alpine family (Wolfi/apko-like): their own secdb or APKINDEX equivalents
|
||||
* Distroless/scratch: no package manager; you must fall back to binary scanning only (Layer B).
|
||||
|
||||
**Developer action**
|
||||
|
||||
* Create an interface `IDistroProvider` with:
|
||||
|
||||
* `EnumerateReleases()`
|
||||
* `FetchAdvisories(snapshot)`
|
||||
* `FetchRepoMetadata(snapshot)`
|
||||
* `NormalizePackageName(...)`
|
||||
* `CompareVersions(a,b)`
|
||||
* `ParseInstalledPackages(image)` (if package manager exists)
|
||||
* Implement providers: `AlpineProvider`, `DebianProvider`, `RpmProvider`, `SuseProvider`, `AstraProvider`, plus “GenericDebianFamilyProvider”, “GenericRpmFamilyProvider”.
|
||||
|
||||
---
|
||||
|
||||
## 4) Installed package extraction (inside scan)
|
||||
|
||||
### 4.1 Determine OS identity
|
||||
|
||||
From image filesystem:
|
||||
|
||||
* `/etc/os-release` (ID, VERSION_ID)
|
||||
* distro-specific markers:
|
||||
|
||||
* Alpine: `/etc/alpine-release`
|
||||
* Debian: `/etc/debian_version`
|
||||
* RHEL: `/etc/redhat-release`
|
||||
|
||||
Write a deterministic resolver:
|
||||
|
||||
* if `/etc/os-release` missing, fall back to:
|
||||
|
||||
* package DB presence: `/lib/apk/db/installed`, `/var/lib/dpkg/status`, rpmdb paths
|
||||
* ELF libc fingerprint heuristics (last resort)
|
||||
|
||||
### 4.2 Extract installed packages deterministically
|
||||
|
||||
* Alpine: parse `/lib/apk/db/installed`
|
||||
* Debian: parse `/var/lib/dpkg/status`
|
||||
* RPM: parse rpmdb (use `rpm` tooling in a controlled helper container, or implement rpmdb reader; prefer tooling for correctness)
|
||||
|
||||
Store:
|
||||
|
||||
* package name
|
||||
* version string (raw)
|
||||
* arch
|
||||
* source package mapping if available (Debian’s `Source:` fields; RPM’s `Sourcerpm`)
|
||||
|
||||
---
|
||||
|
||||
## 5) The backport proof engine (Layer B)
|
||||
|
||||
This is the “precision jump”. It has three proof modes; implement all three and choose best available.
|
||||
|
||||
### Proof mode 1 — Advisory fixed NEVRA/version match (fast)
|
||||
|
||||
If the distro’s errata/DSA/updateinfo says fixed in `X`, and installed package version compares ≥ X (using correct comparator):
|
||||
|
||||
* mark fixed with `confidence=high`
|
||||
* attach advisory reference only
|
||||
|
||||
This already addresses many cases.
|
||||
|
||||
### Proof mode 2 — Source patch presence (best for distros with source repos)
|
||||
|
||||
Prove the patch is in the source package even if version looks old.
|
||||
|
||||
#### Debian-family
|
||||
|
||||
* Determine source package:
|
||||
|
||||
* from `dpkg status` “Source:” if present; otherwise map binary→source via `Sources.gz`
|
||||
* Fetch source:
|
||||
|
||||
* `.dsc` + referenced tarballs + `debian/patches/*` (or `debian/patches/series`)
|
||||
* Patch signature verification:
|
||||
|
||||
* For CVE, you maintain `patch_signature` derived from upstream fix commits:
|
||||
|
||||
* identify file/function/hunk; store normalized diff hashes (ignore whitespace/context drift)
|
||||
* Apply:
|
||||
|
||||
* check if any distro patch file contains the “post” signature (or the vulnerable code is absent)
|
||||
* Record in `proof_blob`:
|
||||
|
||||
* source artifact SHA256
|
||||
* patch file names
|
||||
* matching signature IDs
|
||||
* deterministic verifier log
|
||||
|
||||
#### RPM-family (RHEL/Fedora/SUSE)
|
||||
|
||||
* Determine SRPM from installed RPM metadata (Sourcerpm field).
|
||||
* Fetch SRPM from source repo (or debug/source channel).
|
||||
* Extract patches from SRPM spec + sources.
|
||||
* Verify patch signatures as above.
|
||||
|
||||
#### Alpine
|
||||
|
||||
* Determine `apkbuild` and patches for the package version (Alpine aports)
|
||||
* Verify patch signature.
|
||||
|
||||
### Proof mode 3 — Binary hunk/signature match (works even without source repos)
|
||||
|
||||
This is your universal fallback (also for distroless).
|
||||
|
||||
#### Build fingerprints
|
||||
|
||||
* For each ELF binary in the package or image:
|
||||
|
||||
* compute `sha256`
|
||||
* read `ELF BuildID` if present
|
||||
* capture `.gnu_debuglink` if present
|
||||
* capture symbols (when available)
|
||||
|
||||
#### Signature strategy
|
||||
|
||||
For each CVE fix, create one or more **binary-checkable predicates**:
|
||||
|
||||
* vulnerable function contains a known byte sequence that disappears after fix
|
||||
* or patched function includes a new basic block pattern
|
||||
* or a string constant changes (weak, but sometimes useful)
|
||||
* or the compile-time feature toggles
|
||||
|
||||
Implement as `BinaryPredicate` objects:
|
||||
|
||||
* `type`: bytepattern | cfghash | symbolrangehash | rodata-string
|
||||
* `scope`: file path patterns / package name constraints
|
||||
* `arch`: x86_64/aarch64 etc.
|
||||
* `algo_version`: so you can evolve without breaking replay
|
||||
|
||||
Evaluation:
|
||||
|
||||
* locate candidate binaries (package manifest, common library paths)
|
||||
* apply predicate in a stable order
|
||||
* if “fixed predicate” matches and “vulnerable predicate” does not:
|
||||
|
||||
* produce proof
|
||||
|
||||
#### Evidence quality
|
||||
|
||||
Binary proof must include:
|
||||
|
||||
* file path + sha256
|
||||
* BuildID if available
|
||||
* predicate ID + algorithm version
|
||||
* extractor/verifier version hashes
|
||||
|
||||
---
|
||||
|
||||
## 6) Building the patch signature corpus (no humans)
|
||||
|
||||
### 6.1 Upstream patch harvesting (Feedser)
|
||||
|
||||
For each CVE:
|
||||
|
||||
* find upstream fix commits (NVD references, project advisories, distro patch references)
|
||||
* fetch git diffs
|
||||
* normalize to `patch_signature`:
|
||||
|
||||
* (file path, function name if detectable, pre hash, post hash)
|
||||
* store multiple signatures per CVE if multiple upstream branches
|
||||
|
||||
You will not always find perfect fix commits. When missing:
|
||||
|
||||
* fall back to distro-specific patch extraction (learn signatures from distro patch itself)
|
||||
* mark `signature_origin=distro-learned` but keep it auditable
|
||||
|
||||
### 6.2 Deterministic normalization rules
|
||||
|
||||
* strip diff metadata that varies
|
||||
* normalize whitespace
|
||||
* compute hashes over:
|
||||
|
||||
* token stream (C/C++ tokens; for others line-based)
|
||||
* include hunk context windows
|
||||
* store `algo_version` and never change semantics without bumping
|
||||
|
||||
---
|
||||
|
||||
## 7) Decision algorithm (deterministic, ordered, explainable)
|
||||
|
||||
For each `(image_digest, distro_release, pkg, cve)`:
|
||||
|
||||
1. **If distro provider has explicit status “not affected”** (e.g., vulnerable code not present in that distro build):
|
||||
|
||||
* emit VEX not_affected with advisory proof
|
||||
2. **Else if advisory says fixed in version/NEVRA** and installed compares as fixed:
|
||||
|
||||
* emit VEX fixed with advisory proof
|
||||
3. **Else if source proof succeeds**:
|
||||
|
||||
* emit VEX not_affected / fixed (depending on semantics) with `justification=patched-backport`
|
||||
4. **Else if binary proof succeeds**:
|
||||
|
||||
* emit VEX not_affected / fixed with binary proof
|
||||
5. Else:
|
||||
|
||||
* affected/unknown depending on policy, but always attach “why unknown” in evidence.
|
||||
|
||||
This order is critical to keep runtime reasonable and proofs consistent.
|
||||
|
||||
---
|
||||
|
||||
## 8) Engineering constraints for Docker base images
|
||||
|
||||
### 8.1 Multi-stage images and removed package DBs
|
||||
|
||||
Many production images delete package databases to slim.
|
||||
Your scan must handle:
|
||||
|
||||
* no dpkg status, no rpmdb, no apk db
|
||||
In this case:
|
||||
* try SBOM from build provenance (if you have it)
|
||||
* otherwise treat as **binary-only**:
|
||||
|
||||
* scan ELF binaries + shared libs
|
||||
* map to known package/binary fingerprints where possible
|
||||
* rely on Proof mode 3
|
||||
|
||||
### 8.2 Minimal images (distroless, scratch)
|
||||
|
||||
* There is no OS metadata; don’t pretend.
|
||||
* Mark distro as `unknown`, skip Layer A, go straight to binary proof.
|
||||
* Policy should treat unknowns explicitly (your existing “unknown budget” moat).
|
||||
|
||||
---
|
||||
|
||||
## 9) Implementation structure in .NET 10 (practical module map)
|
||||
|
||||
### 9.1 Services and boundaries
|
||||
|
||||
* **Feedser**
|
||||
|
||||
* pulls distro advisories/trackers/repo metadata
|
||||
* produces normalized `DistroFix` snapshots
|
||||
* **Sbomer**
|
||||
|
||||
* produces SBOM + captures file fingerprints, BuildIDs
|
||||
* **Scanner.Webservice**
|
||||
|
||||
* runs the deterministic evaluation and lattice/policy logic (per your standing rule)
|
||||
* does proof verification + emits signed verdicts
|
||||
* **Vexer**
|
||||
|
||||
* aggregates VEX claims + attaches proof blobs (but evaluation logic stays in Scanner.Webservice)
|
||||
* **Authority/Attestor**
|
||||
|
||||
* DSSE signing, OCI referrers, audit pack exports
|
||||
|
||||
### 9.2 Core libraries
|
||||
|
||||
Create a library `StellaOps.Security.Distro`:
|
||||
|
||||
* `IDistroProvider`
|
||||
* `IVersionComparator`
|
||||
* `IInstalledPackageExtractor`
|
||||
* `IAdvisoryParser`
|
||||
* `ISourceProofVerifier`
|
||||
* `IBinaryProofVerifier`
|
||||
|
||||
Each provider implements:
|
||||
|
||||
* parsing
|
||||
* comparator
|
||||
* extraction for its ecosystem
|
||||
|
||||
### 9.3 Determinism rules (must be enforced)
|
||||
|
||||
* Every scan references a specific `snapshot_id` for feeds.
|
||||
* Proof computations are pure functions of:
|
||||
|
||||
* image digest
|
||||
* extracted artifacts
|
||||
* snapshot content hashes
|
||||
* algorithm version hashes
|
||||
* Logs included in proof blobs must be stable (no timestamps unless separately recorded).
|
||||
|
||||
---
|
||||
|
||||
## 10) Test strategy (non-negotiable)
|
||||
|
||||
### 10.1 Golden corpus images
|
||||
|
||||
Build a repo of fixtures:
|
||||
|
||||
* `alpine:3.18`, `alpine:3.19`
|
||||
* `debian:11`, `debian:12`
|
||||
* `ubuntu:22.04`, `ubuntu:24.04`
|
||||
* `ubi9`, `ubi8` (or rhel-like equivalents you can legally test)
|
||||
* `fedora:40+`
|
||||
* `opensuse/leap`, `sles` if accessible
|
||||
* Astra base images if you use them internally
|
||||
|
||||
For each fixture:
|
||||
|
||||
* pick 10 known CVEs across openssl, curl, zlib, glibc, libxml2
|
||||
* store expected decisions:
|
||||
|
||||
* vulnerable vs fixed, including backported cases
|
||||
* run in CI with locked snapshots
|
||||
|
||||
### 10.2 Comparator test suites
|
||||
|
||||
For RPM and Debian version compare:
|
||||
|
||||
* ingest official comparator test vectors (or recreate known tricky cases)
|
||||
* unit tests must include:
|
||||
|
||||
* epoch handling
|
||||
* tilde ordering in Debian versions
|
||||
* rpm release ordering
|
||||
|
||||
### 10.3 Proof verifier tests
|
||||
|
||||
* source proof: patch signature detection on extracted SRPM/deb sources
|
||||
* binary proof: fixed/vulnerable predicate detection on controlled binaries
|
||||
|
||||
---
|
||||
|
||||
## 11) Practical rollout plan (how developers should implement)
|
||||
|
||||
### Phase 1 — Layer A for all major distros (fast coverage)
|
||||
|
||||
1. Implement comparators: rpm, deb, apk.
|
||||
2. Implement providers:
|
||||
|
||||
* Alpine secdb + APKINDEX
|
||||
* Debian security tracker + Packages/Sources
|
||||
* RHEL errata/CVE feed + repo metadata
|
||||
* Fedora updateinfo + repo metadata
|
||||
* SUSE advisory/updateinfo
|
||||
* Generic Debian/RPM fallback providers
|
||||
3. Produce `cve_pkg_status` snapshots and basic VEX results using only Layer A.
|
||||
|
||||
### Phase 2 — Source proof (removes most false positives)
|
||||
|
||||
1. Implement upstream patch harvesting → `patch_signature`.
|
||||
2. Implement Debian source fetch + verification.
|
||||
3. Implement SRPM fetch + verification.
|
||||
4. Wire into decision algorithm, emit proof blobs.
|
||||
|
||||
### Phase 3 — Binary proof (covers stripped/minimal images)
|
||||
|
||||
1. Implement ELF fingerprint extraction + BuildID store.
|
||||
2. Implement predicate framework + initial predicates for top libraries.
|
||||
3. Add caching (Valkey) for predicate results keyed by `(file sha256, predicate_id, algo_version)`.
|
||||
|
||||
### Phase 4 — Astra and niche distros hardening
|
||||
|
||||
1. Implement Astra provider:
|
||||
|
||||
* repo metadata ingestion
|
||||
* advisory parsing if available
|
||||
* otherwise rely on source/binary proof
|
||||
2. Add distro onboarding kit:
|
||||
|
||||
* define endpoints for repo metadata
|
||||
* define advisory parsing rules
|
||||
* define comparator family
|
||||
|
||||
---
|
||||
|
||||
## 12) What “done” means (acceptance criteria)
|
||||
|
||||
A developer story is “complete” only if:
|
||||
|
||||
* For each supported distro family, you can:
|
||||
|
||||
* identify distro release
|
||||
* extract installed packages OR fall back to binary-only
|
||||
* compute fix status for at least top 50 packages
|
||||
* produce VEX with either advisory or proof
|
||||
* At least 100 backport scenarios across RHEL/Debian/SUSE pass golden tests.
|
||||
* Scan is replayable:
|
||||
|
||||
* freeze snapshot, rerun, identical verdict hash.
|
||||
|
||||
---
|
||||
|
||||
If you want this converted into your internal sprintable format (epics/stories/tasks + acceptance tests + file/module layout in a .NET 10 repo), I can output it as:
|
||||
|
||||
* `SPECS.md` section “Patch-aware Backport Handling”
|
||||
* `CONTRACTS.md` (provider interfaces, proof blob schema, DSSE envelopes)
|
||||
* `DB_REPOSITORIES.md` migrations outline
|
||||
* `IMPLEMENTATION.md` with step-by-step task breakdown per distro.
|
||||
Reference in New Issue
Block a user