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>
5.0 KiB
5.0 KiB
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)
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 > Nin prod.require_guard_evidencefor claims like “feature off”.max_paths/max_depthto keep proofs compact.source-first-but-fallback-binaryselection.
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.