Files
git.stella-ops.org/docs/schemas/reachability-evidence-chain.schema.json
StellaOps Bot 8768c27f30
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals DSSE Sign & Evidence Locker / sign-signals-artifacts (push) Has been cancelled
Signals DSSE Sign & Evidence Locker / verify-signatures (push) Has been cancelled
Add signal contracts for reachability, exploitability, trust, and unknown symbols
- Introduced `ReachabilityState`, `RuntimeHit`, `ExploitabilitySignal`, `ReachabilitySignal`, `SignalEnvelope`, `SignalType`, `TrustSignal`, and `UnknownSymbolSignal` records to define various signal types and their properties.
- Implemented JSON serialization attributes for proper data interchange.
- Created project files for the new signal contracts library and corresponding test projects.
- Added deterministic test fixtures for micro-interaction testing.
- Included cryptographic keys for secure operations with cosign.
2025-12-05 00:27:00 +02:00

1002 lines
27 KiB
JSON

{
"$id": "https://stella.ops/schema/reachability-evidence-chain.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ReachabilityEvidenceChain",
"description": "Contract for function-level reachability evidence chains, linking vulnerable code paths to application entry points with signed proofs. Unblocks CLI-401-007 (stella graph explain) and CLI-401-021 (CI/attestor integration).",
"type": "object",
"oneOf": [
{ "$ref": "#/$defs/ReachabilityExplainRequest" },
{ "$ref": "#/$defs/ReachabilityExplainResponse" },
{ "$ref": "#/$defs/ReachabilityEvidenceBundle" },
{ "$ref": "#/$defs/ReachabilityVerificationResult" }
],
"$defs": {
"ReachabilityExplainRequest": {
"type": "object",
"description": "Request to explain reachability for a vulnerability/package",
"required": ["requestType", "requestId", "tenantId", "subject"],
"properties": {
"requestType": {
"type": "string",
"const": "EXPLAIN_REACHABILITY"
},
"requestId": {
"type": "string",
"format": "uuid"
},
"correlationId": {
"type": "string"
},
"tenantId": {
"type": "string"
},
"subject": {
"$ref": "#/$defs/ReachabilitySubject"
},
"options": {
"$ref": "#/$defs/ExplainOptions"
}
}
},
"ReachabilityExplainResponse": {
"type": "object",
"description": "Response containing reachability explanation with call paths and evidence",
"required": ["responseType", "requestId", "status"],
"properties": {
"responseType": {
"type": "string",
"const": "REACHABILITY_EXPLAINED"
},
"requestId": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"enum": ["SUCCESS", "PARTIAL", "NOT_FOUND", "ERROR"]
},
"reachabilityState": {
"$ref": "#/$defs/ReachabilityState"
},
"evidenceChain": {
"$ref": "#/$defs/EvidenceChain"
},
"callPaths": {
"type": "array",
"items": {
"$ref": "#/$defs/CallPath"
},
"description": "Ordered call paths from entry points to vulnerable symbol"
},
"runtimeHits": {
"type": "array",
"items": {
"$ref": "#/$defs/RuntimeHit"
},
"description": "Runtime observations confirming reachability"
},
"attestations": {
"type": "array",
"items": {
"$ref": "#/$defs/AttestationReference"
},
"description": "DSSE attestations backing the evidence"
},
"analysisMetadata": {
"$ref": "#/$defs/AnalysisMetadata"
},
"error": {
"$ref": "#/$defs/ReachabilityError"
}
}
},
"ReachabilityEvidenceBundle": {
"type": "object",
"description": "Complete evidence bundle for offline verification",
"required": ["bundleType", "bundleId", "bundleDigest", "createdAt", "subject", "evidence"],
"properties": {
"bundleType": {
"type": "string",
"const": "REACHABILITY_EVIDENCE"
},
"bundleId": {
"type": "string",
"format": "uuid"
},
"bundleDigest": {
"type": "string",
"pattern": "^(sha256|blake3):[a-f0-9]{64}$",
"description": "Content-addressable digest of bundle"
},
"casUri": {
"type": "string",
"format": "uri",
"description": "CAS storage URI (e.g., cas://reachability/evidence/{digest})"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"expiresAt": {
"type": "string",
"format": "date-time",
"description": "When evidence may become stale"
},
"tenantId": {
"type": "string"
},
"subject": {
"$ref": "#/$defs/ReachabilitySubject"
},
"evidence": {
"$ref": "#/$defs/EvidenceChain"
},
"callGraph": {
"$ref": "#/$defs/CallGraphReference"
},
"dsseEnvelope": {
"$ref": "#/$defs/DsseEnvelopeReference"
},
"rekorEntry": {
"$ref": "#/$defs/TransparencyLogReference"
}
}
},
"ReachabilityVerificationResult": {
"type": "object",
"description": "Result of verifying reachability evidence",
"required": ["resultType", "verified", "verifiedAt"],
"properties": {
"resultType": {
"type": "string",
"const": "VERIFICATION_RESULT"
},
"verified": {
"type": "boolean"
},
"verifiedAt": {
"type": "string",
"format": "date-time"
},
"bundleDigest": {
"type": "string",
"pattern": "^(sha256|blake3):[a-f0-9]{64}$"
},
"graphHashVerified": {
"type": "boolean",
"description": "Whether call graph hash matches"
},
"signatureVerified": {
"type": "boolean",
"description": "Whether DSSE signature is valid"
},
"transparencyVerified": {
"type": "boolean",
"description": "Whether Rekor entry is valid"
},
"pathsVerified": {
"type": "integer",
"minimum": 0,
"description": "Number of call paths verified"
},
"warnings": {
"type": "array",
"items": {
"type": "string"
}
},
"error": {
"$ref": "#/$defs/ReachabilityError"
}
}
},
"ReachabilitySubject": {
"type": "object",
"description": "Subject being analyzed for reachability",
"required": ["purl"],
"properties": {
"purl": {
"type": "string",
"description": "Package URL of the component"
},
"cve": {
"type": "string",
"pattern": "^CVE-\\d{4}-\\d+$",
"description": "CVE identifier if analyzing vulnerability"
},
"vulnerableSymbol": {
"type": "string",
"description": "Vulnerable function/method name"
},
"imageDigest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "Container image digest"
},
"scanId": {
"type": "string",
"description": "Scan job identifier"
},
"artifactDigest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "Artifact content digest"
}
}
},
"ReachabilityState": {
"type": "object",
"description": "Lattice-based reachability determination",
"required": ["state", "confidence"],
"properties": {
"state": {
"type": "string",
"enum": [
"REACHABLE",
"UNREACHABLE",
"POTENTIALLY_REACHABLE",
"UNKNOWN",
"UNDER_REVIEW"
],
"description": "Reachability lattice state"
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Confidence score (0.0-1.0)"
},
"analysisMethod": {
"type": "string",
"enum": ["static", "dynamic", "hybrid", "runtime", "inferred"],
"description": "Analysis method used"
},
"callPathCount": {
"type": "integer",
"minimum": 0,
"description": "Number of paths reaching vulnerable symbol"
},
"minCallDepth": {
"type": "integer",
"minimum": 0,
"description": "Minimum call depth from entry point"
},
"maxCallDepth": {
"type": "integer",
"minimum": 0,
"description": "Maximum call depth from entry point"
},
"runtimeHitCount": {
"type": "integer",
"minimum": 0,
"description": "Number of runtime observations"
}
}
},
"EvidenceChain": {
"type": "object",
"description": "Chain of evidence supporting reachability determination",
"required": ["evidenceId", "evidenceType"],
"properties": {
"evidenceId": {
"type": "string",
"format": "uuid"
},
"evidenceType": {
"type": "string",
"enum": ["CALL_GRAPH", "RUNTIME_TRACE", "HYBRID", "MANUAL"],
"description": "Type of evidence"
},
"graphEvidence": {
"$ref": "#/$defs/GraphEvidence"
},
"runtimeEvidence": {
"$ref": "#/$defs/RuntimeEvidence"
},
"codeAnchors": {
"type": "array",
"items": {
"$ref": "#/$defs/CodeAnchor"
},
"description": "Immutable code identity anchors"
},
"entryPoints": {
"type": "array",
"items": {
"$ref": "#/$defs/EntryPoint"
},
"description": "Application entry points analyzed"
},
"unknowns": {
"type": "array",
"items": {
"$ref": "#/$defs/UnknownRecord"
},
"description": "Unresolved symbols/edges"
}
}
},
"GraphEvidence": {
"type": "object",
"description": "Static call graph analysis evidence",
"required": ["graphHash"],
"properties": {
"graphHash": {
"type": "string",
"pattern": "^blake3:[a-f0-9]{64}$",
"description": "BLAKE3 hash of canonical graph"
},
"graphCasUri": {
"type": "string",
"format": "uri",
"description": "CAS URI to graph (cas://reachability/graphs/{hash})"
},
"graphKind": {
"type": "string",
"enum": ["richgraph-v1", "simplecg-v1", "entry-trace-v1"],
"description": "Graph schema version"
},
"nodeCount": {
"type": "integer",
"minimum": 0
},
"edgeCount": {
"type": "integer",
"minimum": 0
},
"coveragePercent": {
"type": "number",
"minimum": 0,
"maximum": 100,
"description": "Percentage of code covered by analysis"
},
"analyzer": {
"$ref": "#/$defs/AnalyzerInfo"
}
}
},
"RuntimeEvidence": {
"type": "object",
"description": "Runtime observation evidence",
"properties": {
"traceHash": {
"type": "string",
"pattern": "^blake3:[a-f0-9]{64}$"
},
"traceCasUri": {
"type": "string",
"format": "uri"
},
"observationWindow": {
"type": "object",
"properties": {
"start": {
"type": "string",
"format": "date-time"
},
"end": {
"type": "string",
"format": "date-time"
}
}
},
"hitCount": {
"type": "integer",
"minimum": 0
},
"uniqueFunctionsHit": {
"type": "integer",
"minimum": 0
},
"probeType": {
"type": "string",
"enum": ["EventPipe", "JFR", "eBPF", "Instrumentation"],
"description": "Runtime probe type"
}
}
},
"CodeAnchor": {
"type": "object",
"description": "Immutable code identity anchor (code_id)",
"required": ["format", "artifactDigest"],
"properties": {
"format": {
"type": "string",
"enum": ["ELF", "PE", "MachO", "JVM", "CLR", "WASM", "SOURCE"],
"description": "Binary/source format"
},
"artifactDigest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "Artifact content digest"
},
"buildId": {
"type": "string",
"description": "Build ID (.note.gnu.build-id or equivalent)"
},
"section": {
"type": "string",
"description": "Section name (e.g., .text, .init)"
},
"startAddress": {
"type": "string",
"pattern": "^0x[a-f0-9]+$",
"description": "Start address (hex)"
},
"length": {
"type": "integer",
"minimum": 0,
"description": "Code block length in bytes"
},
"codeBlockHash": {
"type": "string",
"pattern": "^blake3:[a-f0-9]{64}$",
"description": "Optional hash of code bytes"
},
"symbol": {
"$ref": "#/$defs/SymbolInfo"
}
}
},
"SymbolInfo": {
"type": "object",
"description": "Symbol information with demangling",
"properties": {
"mangled": {
"type": "string",
"description": "Mangled symbol name"
},
"demangled": {
"type": "string",
"description": "Demangled/human-readable name"
},
"source": {
"type": "string",
"enum": ["DWARF", "PDB", "SYM", "STABS", "EXPORTS", "none"],
"description": "Symbol source"
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Symbol resolution confidence"
},
"language": {
"type": "string",
"enum": ["c", "cpp", "rust", "go", "java", "csharp", "python", "javascript", "unknown"],
"description": "Inferred source language"
}
}
},
"EntryPoint": {
"type": "object",
"description": "Application entry point",
"required": ["entryPointId", "type"],
"properties": {
"entryPointId": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"MAIN",
"HTTP_HANDLER",
"EVENT_HANDLER",
"SCHEDULED_TASK",
"INIT_ARRAY",
"CONSTRUCTOR",
"CLI_COMMAND",
"GRPC_METHOD",
"MESSAGE_HANDLER",
"OTHER"
]
},
"name": {
"type": "string"
},
"route": {
"type": "string",
"description": "HTTP route pattern if applicable"
},
"codeAnchor": {
"$ref": "#/$defs/CodeAnchor"
},
"phase": {
"type": "string",
"enum": ["load", "init", "runtime"],
"description": "Execution phase"
}
}
},
"CallPath": {
"type": "object",
"description": "Single call path from entry point to vulnerable symbol",
"required": ["pathId", "depth", "nodes"],
"properties": {
"pathId": {
"type": "string"
},
"depth": {
"type": "integer",
"minimum": 0
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0
},
"pathType": {
"type": "string",
"enum": ["static", "dynamic", "inferred"],
"description": "How path was discovered"
},
"entryPoint": {
"$ref": "#/$defs/EntryPoint"
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/$defs/CallPathNode"
},
"minItems": 1
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/CallEdge"
}
}
}
},
"CallPathNode": {
"type": "object",
"description": "Node in a call path",
"required": ["nodeId"],
"properties": {
"nodeId": {
"type": "string"
},
"functionName": {
"type": "string"
},
"purl": {
"type": "string",
"description": "Package URL of containing package"
},
"codeAnchor": {
"$ref": "#/$defs/CodeAnchor"
},
"isVulnerable": {
"type": "boolean",
"description": "Whether this is the vulnerable function"
},
"isEntryPoint": {
"type": "boolean"
},
"runtimeHitCount": {
"type": "integer",
"minimum": 0
}
}
},
"CallEdge": {
"type": "object",
"description": "Edge between call path nodes",
"required": ["from", "to", "kind"],
"properties": {
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"kind": {
"type": "string",
"enum": ["static", "virtual", "dynamic", "import", "callback", "reflection"],
"description": "Call edge type"
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0
},
"evidence": {
"type": "array",
"items": {
"type": "string"
},
"description": "Evidence sources (e.g., reloc:.plt.got, bb-target:0x40f0ff)"
},
"reason": {
"type": "string",
"enum": ["direct", "indirect", "runtime-observed", "inferred", "contested"],
"description": "Reason for edge"
},
"revoked": {
"type": "boolean",
"default": false,
"description": "Whether edge was revoked/disproven"
}
}
},
"RuntimeHit": {
"type": "object",
"description": "Runtime observation of function execution",
"required": ["symbolId", "hitCount", "observedAt"],
"properties": {
"symbolId": {
"type": "string"
},
"codeAnchor": {
"$ref": "#/$defs/CodeAnchor"
},
"hitCount": {
"type": "integer",
"minimum": 1
},
"observedAt": {
"type": "string",
"format": "date-time"
},
"loaderBase": {
"type": "string",
"pattern": "^0x[a-f0-9]+$",
"description": "Runtime loader base address"
},
"processId": {
"type": "string"
},
"containerId": {
"type": "string"
},
"casUri": {
"type": "string",
"format": "uri",
"description": "CAS URI to raw trace data"
}
}
},
"UnknownRecord": {
"type": "object",
"description": "Unresolved symbol or edge for uncertainty tracking",
"required": ["unknownType", "identifier"],
"properties": {
"unknownType": {
"type": "string",
"enum": ["SYMBOL", "EDGE", "IMPORT", "REFERENCE"]
},
"identifier": {
"type": "string"
},
"context": {
"type": "string"
},
"uncertaintyLevel": {
"type": "string",
"enum": ["U1", "U2", "U3"],
"description": "Uncertainty tier"
}
}
},
"CallGraphReference": {
"type": "object",
"description": "Reference to call graph artifact",
"required": ["graphHash"],
"properties": {
"graphHash": {
"type": "string",
"pattern": "^blake3:[a-f0-9]{64}$"
},
"casUri": {
"type": "string",
"format": "uri"
},
"dsseUri": {
"type": "string",
"format": "uri",
"description": "URI to DSSE envelope (cas://.../{hash}.dsse)"
},
"kind": {
"type": "string",
"enum": ["richgraph-v1", "simplecg-v1", "entry-trace-v1"]
}
}
},
"AttestationReference": {
"type": "object",
"description": "Reference to DSSE attestation",
"required": ["predicateType", "digest"],
"properties": {
"predicateType": {
"type": "string",
"format": "uri",
"examples": [
"https://stella.ops/attestation/reachability/v1",
"https://stella.ops/attestation/graph/v1",
"https://stella.ops/attestation/vexDecision/v1"
]
},
"digest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$"
},
"casUri": {
"type": "string",
"format": "uri"
},
"signerId": {
"type": "string"
},
"signedAt": {
"type": "string",
"format": "date-time"
},
"rekorLogIndex": {
"type": "integer",
"description": "Rekor transparency log index"
}
}
},
"DsseEnvelopeReference": {
"type": "object",
"description": "Reference to DSSE envelope for evidence",
"properties": {
"envelopeDigest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$"
},
"casUri": {
"type": "string",
"format": "uri"
},
"predicateType": {
"type": "string",
"format": "uri"
},
"keyId": {
"type": "string"
}
}
},
"TransparencyLogReference": {
"type": "object",
"description": "Reference to Rekor transparency log entry",
"properties": {
"logId": {
"type": "string"
},
"logIndex": {
"type": "integer"
},
"integratedTime": {
"type": "string",
"format": "date-time"
},
"entryUri": {
"type": "string",
"format": "uri"
},
"inclusionProof": {
"type": "string",
"description": "Base64-encoded inclusion proof"
}
}
},
"AnalyzerInfo": {
"type": "object",
"description": "Information about the analyzer that produced evidence",
"required": ["name", "version"],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"digest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "Analyzer binary/image digest"
},
"configHash": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "Hash of analyzer configuration"
}
}
},
"AnalysisMetadata": {
"type": "object",
"description": "Metadata about the analysis",
"properties": {
"analysisId": {
"type": "string",
"format": "uuid"
},
"startedAt": {
"type": "string",
"format": "date-time"
},
"completedAt": {
"type": "string",
"format": "date-time"
},
"durationMs": {
"type": "integer",
"minimum": 0
},
"analyzer": {
"$ref": "#/$defs/AnalyzerInfo"
},
"replayable": {
"type": "boolean",
"description": "Whether analysis can be replayed"
},
"replayManifestUri": {
"type": "string",
"format": "uri"
}
}
},
"ExplainOptions": {
"type": "object",
"description": "Options for explain request",
"properties": {
"maxPaths": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 10,
"description": "Maximum number of paths to return"
},
"maxDepth": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 20,
"description": "Maximum call depth to analyze"
},
"includeRuntimeHits": {
"type": "boolean",
"default": true
},
"includeUnknowns": {
"type": "boolean",
"default": false,
"description": "Include unresolved symbols"
},
"requireAttestation": {
"type": "boolean",
"default": false,
"description": "Only return attested evidence"
},
"format": {
"type": "string",
"enum": ["json", "sarif", "graphviz"],
"default": "json"
}
}
},
"ReachabilityError": {
"type": "object",
"required": ["code", "message"],
"properties": {
"code": {
"type": "string",
"enum": [
"SUBJECT_NOT_FOUND",
"GRAPH_NOT_AVAILABLE",
"ANALYSIS_FAILED",
"ATTESTATION_INVALID",
"TRANSPARENCY_UNAVAILABLE",
"TIMEOUT",
"INTERNAL_ERROR"
]
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
},
"examples": [
{
"responseType": "REACHABILITY_EXPLAINED",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"status": "SUCCESS",
"reachabilityState": {
"state": "REACHABLE",
"confidence": 0.92,
"analysisMethod": "hybrid",
"callPathCount": 3,
"minCallDepth": 4,
"runtimeHitCount": 127
},
"evidenceChain": {
"evidenceId": "660e8400-e29b-41d4-a716-446655440001",
"evidenceType": "HYBRID",
"graphEvidence": {
"graphHash": "blake3:7d9cd5f1a2a0dd9a41a2c43a5b7d8a0bcd9e34cf39b3f43a70595c834f0a4aee",
"graphCasUri": "cas://reachability/graphs/7d9cd5f1a2a0dd9a41a2c43a5b7d8a0bcd9e34cf39b3f43a70595c834f0a4aee",
"graphKind": "richgraph-v1",
"nodeCount": 1247,
"edgeCount": 3891,
"coveragePercent": 87.3,
"analyzer": {
"name": "stellaops-scanner",
"version": "1.5.0",
"digest": "sha256:abc123def456..."
}
}
},
"callPaths": [
{
"pathId": "path-001",
"depth": 4,
"confidence": 0.95,
"pathType": "static",
"nodes": [
{
"nodeId": "node-001",
"functionName": "handleRequest",
"purl": "pkg:npm/express@4.18.2",
"isEntryPoint": true
},
{
"nodeId": "node-002",
"functionName": "parseBody",
"purl": "pkg:npm/body-parser@1.20.0"
},
{
"nodeId": "node-003",
"functionName": "deserialize",
"purl": "pkg:npm/qs@6.11.0"
},
{
"nodeId": "node-004",
"functionName": "vulnerableFunction",
"purl": "pkg:npm/lodash@4.17.20",
"isVulnerable": true,
"runtimeHitCount": 42
}
],
"edges": [
{
"from": "node-001",
"to": "node-002",
"kind": "static",
"confidence": 0.99
},
{
"from": "node-002",
"to": "node-003",
"kind": "static",
"confidence": 0.98
},
{
"from": "node-003",
"to": "node-004",
"kind": "dynamic",
"confidence": 0.91,
"evidence": ["import:lodash", "bb-target:0x40f0ff"]
}
]
}
],
"attestations": [
{
"predicateType": "https://stella.ops/attestation/reachability/v1",
"digest": "sha256:8d9cd5f1a2a0dd9a41a2c43a5b7d8a0bcd9e34cf39b3f43a70595c834f0a4aef",
"signerId": "scanner-signing-key-001",
"signedAt": "2025-11-21T10:15:00Z",
"rekorLogIndex": 12345678
}
]
}
]
}