Files
git.stella-ops.org/docs/contracts/witness-v1.md
master 00d2c99af9 feat: add Attestation Chain and Triage Evidence API clients and models
- Implemented Attestation Chain API client with methods for verifying, fetching, and managing attestation chains.
- Created models for Attestation Chain, including DSSE envelope structures and verification results.
- Developed Triage Evidence API client for fetching finding evidence, including methods for evidence retrieval by CVE and component.
- Added models for Triage Evidence, encapsulating evidence responses, entry points, boundary proofs, and VEX evidence.
- Introduced mock implementations for both API clients to facilitate testing and development.
2025-12-18 13:15:13 +02:00

222 lines
6.1 KiB
Markdown

# Witness Schema v1 Contract
> **Version**: `stellaops.witness.v1`
> **Status**: Draft
> **Sprint**: `SPRINT_3700_0001_0001_witness_foundation`
---
## Overview
A **witness** is a cryptographically-signed proof of a reachability path from an entrypoint to a vulnerable sink. Witnesses provide:
1. **Auditability** - Proof that a path was found at scan time
2. **Offline verification** - Verify claims without re-running analysis
3. **Provenance** - Links to the source graph and analysis context
4. **Transparency** - Can be published to transparency logs
---
## Schema Definition
### PathWitness
```json
{
"$schema": "https://stellaops.org/schemas/witness-v1.json",
"schema_version": "stellaops.witness.v1",
"witness_id": "uuid",
"witness_hash": "blake3:abcd1234...",
"witness_type": "reachability_path",
"created_at": "2025-12-18T12:00:00Z",
"provenance": {
"graph_hash": "blake3:efgh5678...",
"scan_id": "uuid",
"run_id": "uuid",
"analyzer_version": "1.0.0",
"analysis_timestamp": "2025-12-18T11:59:00Z"
},
"path": {
"entrypoint": {
"fqn": "com.example.MyController.handleRequest",
"kind": "http_handler",
"location": {
"file": "src/main/java/com/example/MyController.java",
"line": 42
}
},
"sink": {
"fqn": "org.apache.log4j.Logger.log",
"cve": "CVE-2021-44228",
"package": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"
},
"steps": [
{
"index": 0,
"fqn": "com.example.MyController.handleRequest",
"call_site": "MyController.java:45",
"edge_type": "call"
},
{
"index": 1,
"fqn": "com.example.LoggingService.logMessage",
"call_site": "LoggingService.java:23",
"edge_type": "call"
},
{
"index": 2,
"fqn": "org.apache.log4j.Logger.log",
"call_site": "Logger.java:156",
"edge_type": "sink"
}
],
"hop_count": 3
},
"gates": [
{
"type": "auth_required",
"location": "MyController.java:40",
"description": "Requires authenticated user"
}
],
"evidence": {
"graph_fragment_hash": "blake3:ijkl9012...",
"path_hash": "blake3:mnop3456..."
}
}
```
---
## Field Definitions
### Root Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `schema_version` | string | Yes | Must be `stellaops.witness.v1` |
| `witness_id` | UUID | Yes | Unique identifier |
| `witness_hash` | string | Yes | BLAKE3 hash of canonical JSON |
| `witness_type` | enum | Yes | `reachability_path`, `gate_proof` |
| `created_at` | ISO8601 | Yes | Witness creation timestamp (UTC) |
### Provenance
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `graph_hash` | string | Yes | BLAKE3 hash of source rich graph |
| `scan_id` | UUID | No | Scan that produced the graph |
| `run_id` | UUID | No | Analysis run identifier |
| `analyzer_version` | string | Yes | Analyzer version |
| `analysis_timestamp` | ISO8601 | Yes | When analysis was performed |
### Path
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `entrypoint` | object | Yes | Entry point of the path |
| `sink` | object | Yes | Vulnerable sink at end of path |
| `steps` | array | Yes | Ordered list of path steps |
| `hop_count` | integer | Yes | Number of edges in path |
### Path Step
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `index` | integer | Yes | Position in path (0-indexed) |
| `fqn` | string | Yes | Fully qualified name of node |
| `call_site` | string | No | Source location of call |
| `edge_type` | enum | Yes | `call`, `virtual`, `static`, `sink` |
### Gates
Optional array of protective controls encountered along the path.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | enum | Yes | `auth_required`, `feature_flag`, `admin_only`, `non_default_config` |
| `location` | string | No | Source location of gate |
| `description` | string | No | Human-readable description |
---
## Hash Computation
The `witness_hash` is computed as:
1. Serialize the witness to canonical JSON (sorted keys, no whitespace)
2. Exclude `witness_id`, `witness_hash`, and `created_at` fields
3. Compute BLAKE3 hash of the canonical bytes
4. Prefix with `blake3:` and hex-encode
```csharp
var canonical = JsonSerializer.Serialize(witness, canonicalOptions);
var hash = Blake3.Hasher.Hash(Encoding.UTF8.GetBytes(canonical));
var witnessHash = $"blake3:{Convert.ToHexString(hash.AsSpan()).ToLowerInvariant()}";
```
---
## DSSE Signing
Witnesses are signed using [DSSE (Dead Simple Signing Envelope)](https://github.com/secure-systems-lab/dsse):
```json
{
"payloadType": "application/vnd.stellaops.witness.v1+json",
"payload": "<base64url-encoded witness JSON>",
"signatures": [
{
"keyid": "sha256:abcd1234...",
"sig": "<base64url-encoded signature>"
}
]
}
```
### Verification
1. Decode the payload from base64url
2. Parse as PathWitness JSON
3. Recompute witness_hash and compare
4. Verify signature against known public key
5. Optionally check transparency log for inclusion
---
## Storage
Witnesses are stored in `scanner.witnesses` table:
| Column | Type | Description |
|--------|------|-------------|
| `witness_id` | UUID | Primary key |
| `witness_hash` | TEXT | BLAKE3 hash (unique) |
| `payload_json` | JSONB | Full witness JSON |
| `dsse_envelope` | JSONB | Signed envelope (nullable) |
| `graph_hash` | TEXT | Source graph reference |
| `sink_cve` | TEXT | CVE for quick lookup |
---
## API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/v1/witnesses/{id}` | Get witness by ID |
| `GET` | `/api/v1/witnesses?cve={cve}` | List witnesses for CVE |
| `GET` | `/api/v1/witnesses?scan={scanId}` | List witnesses for scan |
| `POST` | `/api/v1/witnesses/{id}/verify` | Verify witness signature |
---
## Related Documents
- [Rich Graph Contract](richgraph-v1.md)
- [DSSE Specification](https://github.com/secure-systems-lab/dsse)
- [BLAKE3 Hash Function](https://github.com/BLAKE3-team/BLAKE3)