Files
git.stella-ops.org/docs/reachability/slice-schema.md
StellaOps Bot df94136727 feat: Implement distro-native version comparison for RPM, Debian, and Alpine packages
- Add RpmVersionComparer for RPM version comparison with epoch, version, and release handling.
- Introduce DebianVersion for parsing Debian EVR (Epoch:Version-Release) strings.
- Create ApkVersion for parsing Alpine APK version strings with suffix support.
- Define IVersionComparator interface for version comparison with proof-line generation.
- Implement VersionComparisonResult struct to encapsulate comparison results and proof lines.
- Add tests for Debian and RPM version comparers to ensure correct functionality and edge case handling.
- Create project files for the version comparison library and its tests.
2025-12-22 09:49:53 +02:00

288 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Reachability Slice Schema
_Last updated: 2025-12-22. Owner: Scanner Guild._
This document defines the **Reachability Slice** schema—a minimal, attestable proof unit that answers whether a vulnerable symbol is reachable from application entrypoints.
---
## 1. Overview
A **slice** is a focused subgraph extracted from a full reachability graph, containing only the nodes and edges relevant to answering a specific reachability query (e.g., "Is CVE-2024-1234's vulnerable function reachable?").
### Key Properties
| Property | Description |
|----------|-------------|
| **Minimal** | Contains only nodes/edges on paths between entrypoints and targets |
| **Attestable** | DSSE-signed with in-toto predicate format |
| **Reproducible** | Same inputs → same bytes (deterministic) |
| **Content-addressed** | Retrieved by BLAKE3 digest |
---
## 2. Schema Definition
### 2.1 DSSE Predicate Type
```
https://stellaops.dev/predicates/reachability-slice/v1
```
### 2.2 Full Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://stellaops.dev/schemas/reachability-slice.v1.schema.json",
"title": "Reachability Slice",
"type": "object",
"required": ["_type", "inputs", "query", "subgraph", "verdict", "manifest"],
"properties": {
"_type": {
"const": "https://stellaops.dev/predicates/reachability-slice/v1"
},
"inputs": { "$ref": "#/$defs/SliceInputs" },
"query": { "$ref": "#/$defs/SliceQuery" },
"subgraph": { "$ref": "#/$defs/SliceSubgraph" },
"verdict": { "$ref": "#/$defs/SliceVerdict" },
"manifest": { "$ref": "#/$defs/ScanManifest" }
},
"$defs": {
"SliceInputs": {
"type": "object",
"required": ["graphDigest", "binaryDigests"],
"properties": {
"graphDigest": { "type": "string", "pattern": "^blake3:[a-f0-9]{64}$" },
"binaryDigests": {
"type": "array",
"items": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }
},
"sbomDigest": { "type": "string" },
"layerDigests": { "type": "array", "items": { "type": "string" } }
}
},
"SliceQuery": {
"type": "object",
"properties": {
"cveId": { "type": "string", "pattern": "^CVE-\\d{4}-\\d+$" },
"targetSymbols": { "type": "array", "items": { "type": "string" } },
"entrypoints": { "type": "array", "items": { "type": "string" } },
"policyHash": { "type": "string" }
}
},
"SliceSubgraph": {
"type": "object",
"required": ["nodes", "edges"],
"properties": {
"nodes": {
"type": "array",
"items": { "$ref": "#/$defs/SliceNode" }
},
"edges": {
"type": "array",
"items": { "$ref": "#/$defs/SliceEdge" }
}
}
},
"SliceNode": {
"type": "object",
"required": ["id", "symbol", "kind"],
"properties": {
"id": { "type": "string" },
"symbol": { "type": "string" },
"kind": { "enum": ["entrypoint", "intermediate", "target", "unknown"] },
"file": { "type": "string" },
"line": { "type": "integer" },
"purl": { "type": "string" },
"attributes": { "type": "object" }
}
},
"SliceEdge": {
"type": "object",
"required": ["from", "to", "confidence"],
"properties": {
"from": { "type": "string" },
"to": { "type": "string" },
"kind": { "enum": ["direct", "plt", "iat", "dynamic", "unknown"] },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"evidence": { "type": "string" },
"gate": { "$ref": "#/$defs/GateInfo" },
"observed": { "$ref": "#/$defs/ObservedInfo" }
}
},
"GateInfo": {
"type": "object",
"properties": {
"type": { "enum": ["feature_flag", "auth", "config", "admin_only"] },
"condition": { "type": "string" },
"satisfied": { "type": "boolean" }
}
},
"ObservedInfo": {
"type": "object",
"properties": {
"firstObserved": { "type": "string", "format": "date-time" },
"lastObserved": { "type": "string", "format": "date-time" },
"count": { "type": "integer" }
}
},
"SliceVerdict": {
"type": "object",
"required": ["status", "confidence"],
"properties": {
"status": { "enum": ["reachable", "unreachable", "unknown", "gated"] },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"reasons": { "type": "array", "items": { "type": "string" } },
"pathWitnesses": { "type": "array", "items": { "type": "string" } },
"unknownCount": { "type": "integer" },
"gatedPaths": { "type": "array", "items": { "$ref": "#/$defs/GateInfo" } }
}
},
"ScanManifest": {
"type": "object",
"required": ["analyzerVersion", "createdAt"],
"properties": {
"analyzerVersion": { "type": "string" },
"rulesetHash": { "type": "string" },
"feedVersions": { "type": "object" },
"createdAt": { "type": "string", "format": "date-time" },
"toolchain": { "type": "string" }
}
}
}
}
```
---
## 3. Verdict Status Definitions
| Status | Meaning | Confidence Range |
|--------|---------|------------------|
| `reachable` | Path exists from entrypoint to target | ≥0.7 |
| `unreachable` | No path found, no unknowns | ≥0.9 |
| `unknown` | Unknowns present on potential paths | 0.30.7 |
| `gated` | Path exists but gated by feature flag/auth | 0.50.8 |
### Verdict Computation Rules
```
reachable := path_exists AND min(path_confidence) ≥ 0.7 AND unknown_edges = 0
unreachable := NOT path_exists AND unknown_edges = 0
gated := path_exists AND all_paths_gated AND gates_not_satisfied
unknown := unknown_edges > 0 OR min(path_confidence) < 0.5
```
---
## 4. Example Slice
```json
{
"_type": "https://stellaops.dev/predicates/reachability-slice/v1",
"inputs": {
"graphDigest": "blake3:a1b2c3d4e5f6789012345678901234567890123456789012345678901234abcd",
"binaryDigests": ["sha256:deadbeef..."],
"sbomDigest": "sha256:cafebabe..."
},
"query": {
"cveId": "CVE-2024-1234",
"targetSymbols": ["openssl:EVP_PKEY_decrypt"],
"entrypoints": ["main", "http_handler"]
},
"subgraph": {
"nodes": [
{"id": "node:1", "symbol": "main", "kind": "entrypoint", "file": "/app/main.c", "line": 42},
{"id": "node:2", "symbol": "process_request", "kind": "intermediate", "file": "/app/handler.c", "line": 100},
{"id": "node:3", "symbol": "decrypt_data", "kind": "intermediate", "file": "/app/crypto.c", "line": 55},
{"id": "node:4", "symbol": "EVP_PKEY_decrypt", "kind": "target", "purl": "pkg:generic/openssl@3.0.0"}
],
"edges": [
{"from": "node:1", "to": "node:2", "kind": "direct", "confidence": 1.0},
{"from": "node:2", "to": "node:3", "kind": "direct", "confidence": 0.95},
{"from": "node:3", "to": "node:4", "kind": "plt", "confidence": 0.9}
]
},
"verdict": {
"status": "reachable",
"confidence": 0.9,
"reasons": ["Direct call path from main() to EVP_PKEY_decrypt()"],
"pathWitnesses": ["main → process_request → decrypt_data → EVP_PKEY_decrypt"]
},
"manifest": {
"analyzerVersion": "scanner.native:1.2.0",
"rulesetHash": "sha256:...",
"createdAt": "2025-12-22T10:00:00Z",
"toolchain": "iced-x86:1.21.0"
}
}
```
---
## 5. DSSE Envelope Format
Slices are wrapped in DSSE envelopes for attestation:
```json
{
"payloadType": "application/vnd.in-toto+json",
"payload": "<base64-encoded slice JSON>",
"signatures": [
{
"keyid": "sha256:abc123...",
"sig": "<base64-encoded signature>"
}
]
}
```
---
## 6. Storage & Retrieval
### CAS URI Format
```
cas://slices/blake3:<digest>
```
### OCI Artifact Format
```json
{
"mediaType": "application/vnd.stellaops.slice.v1+json",
"digest": "sha256:...",
"annotations": {
"org.stellaops.slice.cve": "CVE-2024-1234",
"org.stellaops.slice.verdict": "reachable"
}
}
```
---
## 7. Determinism Requirements
For reproducible slices:
1. **Node ordering**: Sort by `id` lexicographically
2. **Edge ordering**: Sort by `(from, to)` tuple
3. **Timestamps**: Use UTC ISO-8601 with Z suffix
4. **Floating point**: Round to 6 decimal places
5. **JSON serialization**: No whitespace, sorted keys
---
## 8. Related Documentation
- [Binary Reachability Schema](./binary-reachability-schema.md)
- [RichGraph Contract](../contracts/richgraph-v1.md)
- [Function-Level Evidence](./function-level-evidence.md)
- [Replay Verification](./replay-verification.md)
---
_Created: 2025-12-22. See Sprint 3810 for implementation details._