This commit is contained in:
StellaOps Bot
2025-12-22 09:56:20 +02:00
parent 00bc4f79dd
commit dfaa2079aa
7 changed files with 1574 additions and 12 deletions

View File

@@ -0,0 +1,336 @@
# Evidence Hooks Reference
## Overview
**Evidence Hooks** require specific attestations before an exception can be approved. This ensures exceptions are backed by verifiable proof, not just assertions.
## Hook Model
```yaml
evidenceHooks:
- hookId: "feature-flag-off"
type: FeatureFlagDisabled
description: "Feature flag must be disabled in production"
isMandatory: true
maxAge: PT24H # ISO 8601 duration
minTrustScore: 0.8
```
## Hook Types
### FeatureFlagDisabled
Requires attestation that a feature flag is disabled.
| Field | Type | Description |
|-------|------|-------------|
| flagName | string | Name of the feature flag |
| environment | string | Target environment |
| attestedAt | timestamp | When flag state was verified |
**Evidence Example:**
```json
{
"type": "FeatureFlagDisabled",
"flagName": "EXPERIMENTAL_TEMPLATE_ENGINE",
"environment": "production",
"attestedAt": "2024-12-22T10:00:00Z",
"source": "launchdarkly"
}
```
### BackportMerged
Requires attestation that a security backport was merged.
| Field | Type | Description |
|-------|------|-------------|
| prUrl | string | Pull request URL |
| commitHash | string | Merged commit hash |
| mergedAt | timestamp | When PR was merged |
**Evidence Example:**
```json
{
"type": "BackportMerged",
"prUrl": "https://github.com/org/repo/pull/123",
"commitHash": "abc123...",
"mergedAt": "2024-12-22T09:30:00Z",
"mergedBy": "security-team"
}
```
### CompensatingControl
Requires attestation of a compensating security control.
| Field | Type | Description |
|-------|------|-------------|
| controlType | string | Type of control (WAF, RASP, etc.) |
| controlId | string | Control identifier |
| description | string | How control mitigates risk |
**Evidence Example:**
```json
{
"type": "CompensatingControl",
"controlType": "WAF",
"controlId": "rule-block-template-injection",
"description": "WAF rule blocks template injection patterns",
"deployedAt": "2024-12-22T08:00:00Z"
}
```
### SecurityReview
Requires attestation of completed security review.
| Field | Type | Description |
|-------|------|-------------|
| reviewId | string | Review identifier |
| reviewer | string | Who performed review |
| outcome | string | Review outcome |
### RuntimeMitigation
Requires attestation of runtime mitigation in place.
| Field | Type | Description |
|-------|------|-------------|
| mitigationType | string | Type of mitigation |
| configuration | object | Mitigation configuration |
### WAFRuleDeployed
Requires attestation of WAF rule deployment.
| Field | Type | Description |
|-------|------|-------------|
| ruleId | string | WAF rule identifier |
| provider | string | WAF provider |
| deployedAt | timestamp | Deployment time |
### CustomAttestation
Generic attestation for custom evidence types.
| Field | Type | Description |
|-------|------|-------------|
| predicateType | string | Custom predicate type URI |
| payload | object | Custom payload |
## Validation Rules
### Freshness (maxAge)
Evidence must be recent enough:
```yaml
maxAge: PT24H # 24 hours
maxAge: P7D # 7 days
maxAge: PT1H # 1 hour
```
If evidence is older than maxAge, it's marked as **Expired**.
### Trust Score (minTrustScore)
Evidence source must meet minimum trust:
```yaml
minTrustScore: 0.8 # 80% trust required
```
Trust scores come from the source registry.
### Signature Verification
If evidence includes a DSSE envelope, signature is verified:
```json
{
"content": { ... },
"dsseEnvelope": "eyJwYXlsb2FkIjoi...",
"signatureVerified": true
}
```
### Schema Validation
Custom attestations can require schema validation:
```yaml
validationSchema: "https://stellaops.io/schemas/evidence/feature-flag/v1"
```
## Validation States
| State | Description |
|-------|-------------|
| `Pending` | Evidence submitted, not yet validated |
| `Valid` | Evidence passes all validation |
| `Invalid` | Evidence fails validation |
| `Expired` | Evidence older than maxAge |
| `InsufficientTrust` | Source trust score too low |
## Submission Flow
```
1. User selects exception to approve
2. System shows required evidence hooks
3. User submits evidence for each hook:
a. Upload attestation file
b. Link to external system
c. Generate attestation in-place
4. System validates each submission
5. If all mandatory hooks satisfied:
a. Exception can be approved
6. If any mandatory hooks unsatisfied:
a. Approval blocked
b. Missing evidence highlighted
```
## API Endpoints
### POST /exceptions/{id}/evidence
Submit evidence for a hook.
**Request:**
```json
{
"hookId": "feature-flag-off",
"type": "FeatureFlagDisabled",
"reference": "launchdarkly://flags/EXPERIMENTAL_TEMPLATE_ENGINE",
"content": {
"flagName": "EXPERIMENTAL_TEMPLATE_ENGINE",
"environment": "production",
"state": "off"
}
}
```
### GET /exceptions/{id}/evidence
Get all submitted evidence for an exception.
### GET /exceptions/{id}/evidence/status
Get evidence satisfaction status.
**Response:**
```json
{
"isSatisfied": false,
"missingEvidence": [
{
"hookId": "backport-merged",
"type": "BackportMerged",
"description": "Security backport must be merged"
}
],
"validEvidence": [
{
"hookId": "feature-flag-off",
"type": "FeatureFlagDisabled",
"validatedAt": "2024-12-22T10:00:00Z"
}
]
}
```
## UI Integration
### Evidence Requirements Panel
Shows required evidence with status:
```
Evidence Requirements
---------------------
[x] Feature flag disabled (Verified 2h ago)
[ ] Backport PR merged (Missing)
[x] WAF rule deployed (Verified 1d ago)
[Submit Missing Evidence]
```
### Evidence Upload Modal
For each hook type:
1. File upload for attestations
2. URL input for external references
3. Form for in-place attestation
### Blocking Indicator
When evidence is missing:
- Approve button disabled
- Clear message: "Cannot approve: missing evidence"
- Link to evidence requirements
## Best Practices
1. **Mandatory = Critical**: Only mark truly required evidence as mandatory
2. **Reasonable maxAge**: Balance freshness with operational burden
3. **Trust Scores**: Configure source trust appropriately
4. **Documentation**: Document what each evidence type means
5. **Automation**: Integrate with systems to auto-generate attestations
## DSSE Attestation Format
Evidence can be wrapped in DSSE for integrity:
```json
{
"payloadType": "application/vnd.stellaops.evidence+json",
"payload": "<base64-encoded-evidence>",
"signatures": [
{
"keyid": "key-123",
"sig": "<base64-signature>"
}
]
}
```
## Example Hook Configurations
### Critical CVE Policy
```yaml
evidenceHooks:
- hookId: "security-review"
type: SecurityReview
description: "Security team review required"
isMandatory: true
- hookId: "compensating-control"
type: CompensatingControl
description: "Compensating control must be in place"
isMandatory: true
- hookId: "stakeholder-approval"
type: CustomAttestation
description: "Business stakeholder approval"
isMandatory: true
validationSchema: "https://stellaops.io/schemas/evidence/stakeholder-approval/v1"
```
### Standard Policy
```yaml
evidenceHooks:
- hookId: "justification"
type: CustomAttestation
description: "Written justification required"
isMandatory: true
- hookId: "compensating-control"
type: CompensatingControl
description: "Compensating control recommended"
isMandatory: false
```
## Related Documentation
- [Recheck Policy](./recheck-policy.md)
- [Exception Workflow](../../api/exceptions.md)
- [DSSE Attestations](../attestor/dsse.md)

View File

@@ -0,0 +1,251 @@
# Recheck Policy Reference
## Overview
A **Recheck Policy** defines conditions that trigger automatic re-evaluation of an exception. When conditions are met, the exception may be flagged for review, require re-approval, or be automatically revoked.
## Policy Model
```yaml
recheckPolicy:
policyId: "policy-critical-cves"
name: "Critical CVE Recheck"
conditions:
- type: EPSSAbove
threshold: 0.5
action: RequireReapproval
- type: ReachGraphChange
action: Block
- type: KEVFlagged
action: Block
- type: ExpiryWithin
threshold: 7 # days
action: Warn
defaultAction: Warn
isActive: true
```
## Condition Types
### EPSSAbove
Triggers when EPSS score exceeds threshold.
| Parameter | Type | Description |
|-----------|------|-------------|
| threshold | decimal | EPSS score threshold (0.0-1.0) |
| action | RecheckAction | Action when triggered |
**Example:**
```yaml
- type: EPSSAbove
threshold: 0.5
action: RequireReapproval
```
### CVSSAbove
Triggers when CVSS score exceeds threshold.
| Parameter | Type | Description |
|-----------|------|-------------|
| threshold | decimal | CVSS score threshold (0.0-10.0) |
| action | RecheckAction | Action when triggered |
### ReachGraphChange
Triggers when reachability graph changes (new paths discovered).
| Parameter | Type | Description |
|-----------|------|-------------|
| action | RecheckAction | Action when triggered |
**Use case:** Exception was based on "unreachable" status; new analysis shows reachability.
### UnknownsAbove
Triggers when unknown budget exceeds threshold.
| Parameter | Type | Description |
|-----------|------|-------------|
| threshold | integer | Maximum allowed unknowns |
| action | RecheckAction | Action when triggered |
### KEVFlagged
Triggers when CVE is added to CISA KEV catalog.
| Parameter | Type | Description |
|-----------|------|-------------|
| action | RecheckAction | Action when triggered |
**Best practice:** Always use `Block` action for KEV additions.
### VEXStatusChange
Triggers when VEX status changes (e.g., NotAffected → Affected).
| Parameter | Type | Description |
|-----------|------|-------------|
| action | RecheckAction | Action when triggered |
### NewCVEInPackage
Triggers when new CVE is discovered in the same package.
| Parameter | Type | Description |
|-----------|------|-------------|
| action | RecheckAction | Action when triggered |
### ExpiryWithin
Triggers when exception nears expiry.
| Parameter | Type | Description |
|-----------|------|-------------|
| threshold | integer | Days before expiry |
| action | RecheckAction | Action when triggered |
### PackageVersionChange
Triggers when package version changes in artifact.
| Parameter | Type | Description |
|-----------|------|-------------|
| action | RecheckAction | Action when triggered |
## Actions
### Warn
Log warning but allow exception to remain active.
- Appears in audit log
- Visible in exception details
- Does not block deployment
### RequireReapproval
Move exception back to "pending" status requiring re-approval.
- Notifies original approvers
- Exception inactive until re-approved
- Evidence may need updating
### Revoke
Automatically revoke the exception.
- Exception becomes inactive immediately
- Audit log entry created
- Notification sent
### Block
Fail build/deployment pipeline.
- CI/CD gate returns failure
- Requires manual intervention
- Most severe action
## Environment Scoping
Conditions can be scoped to specific environments:
```yaml
- type: EPSSAbove
threshold: 0.3
environmentScope:
- prod
- staging
action: Block
- type: EPSSAbove
threshold: 0.7
environmentScope:
- dev
action: Warn
```
## Evaluation Flow
```
1. Scan triggered
2. Get active exceptions for artifact
3. For each exception with recheck policy:
a. Evaluate each condition
b. Check environment scope
c. Record triggered conditions
4. Determine highest-priority action
5. Apply action (warn/reapproval/revoke/block)
6. Update exception with recheck result
```
## Build Gate Integration
Recheck policies integrate with build gates:
```yaml
# In CI/CD pipeline
- name: check-exceptions
uses: stellaops/exception-gate@v1
with:
artifact: ${{ env.IMAGE_DIGEST }}
environment: production
fail-on: block
```
## Best Practices
1. **Start with Warn**: Begin with warning actions, escalate based on data
2. **KEV = Block**: Always block on KEV additions
3. **Environment Tiers**: Stricter policies for production
4. **Regular Review**: Review triggered conditions monthly
5. **Document Rationale**: Explain threshold choices
## Example Policies
### High-Security Policy
```yaml
recheckPolicy:
policyId: "high-security"
name: "High Security Recheck"
conditions:
- type: EPSSAbove
threshold: 0.3
action: Block
- type: CVSSAbove
threshold: 7.0
action: RequireReapproval
- type: KEVFlagged
action: Block
- type: ReachGraphChange
action: Block
- type: VEXStatusChange
action: RequireReapproval
defaultAction: Warn
```
### Standard Policy
```yaml
recheckPolicy:
policyId: "standard"
name: "Standard Recheck"
conditions:
- type: EPSSAbove
threshold: 0.7
action: RequireReapproval
- type: KEVFlagged
action: Block
- type: ExpiryWithin
threshold: 14
action: Warn
defaultAction: Warn
```
## Related Documentation
- [Evidence Hooks](./evidence-hooks.md)
- [Exception API](../../api/exceptions.md)
- [Build Gates](../ci/recipes.md)

View File

@@ -0,0 +1,250 @@
# Policy Merge Preview
## Overview
The **Policy Merge Preview** shows how VEX statements from different sources combine using lattice logic. This visualization helps analysts understand:
1. What each source contributes
2. How conflicts are resolved
3. What evidence is missing
4. The final merged status
## Merge Semantics
StellaOps uses a three-layer merge model:
```
vendor ⊕ distro ⊕ internal = final
```
Where ⊕ represents the lattice join operation.
### Layer Hierarchy
| Layer | Description | Typical Trust |
|-------|-------------|---------------|
| **Vendor** | Software vendor's VEX statements | 0.95-1.0 |
| **Distro** | Distribution maintainer's assessments | 0.85-0.95 |
| **Internal** | Organization's own assessments | 0.70-0.90 |
### Lattice Operations
Using K4 (Kleene's 4-valued logic):
| Status | Lattice Position |
|--------|-----------------|
| Affected | Top (Both) |
| UnderInvestigation | Unknown (Neither) |
| Fixed | True |
| NotAffected | False |
Join table (⊕):
```
| Affected | Under... | Fixed | NotAffected
---------+----------+----------+-------+------------
Affected | A | A | A | A
Under... | A | U | U | U
Fixed | A | U | F | F
NotAff | A | U | F | N
```
## API Endpoint
### GET /policy/merge-preview/{cveId}
**Parameters:**
- `cveId`: CVE identifier
- `artifact`: Artifact digest (query param)
**Response:**
```json
{
"cveId": "CVE-2024-1234",
"artifactDigest": "sha256:abc...",
"contributions": [
{
"layer": "vendor",
"sources": ["lodash-security"],
"status": "NotAffected",
"trustScore": 0.95,
"statements": [...],
"mergeTrace": {
"explanation": "Vendor states not affected due to version"
}
},
{
"layer": "distro",
"sources": ["redhat-csaf"],
"status": "Affected",
"trustScore": 0.90,
"statements": [...],
"mergeTrace": {
"explanation": "Distro states affected without context"
}
},
{
"layer": "internal",
"sources": [],
"status": null,
"trustScore": 0,
"statements": [],
"mergeTrace": null
}
],
"finalStatus": "NotAffected",
"finalConfidence": 0.925,
"missingEvidence": [
{
"type": "internal-assessment",
"description": "Add internal security assessment",
"priority": "medium"
}
],
"latticeType": "K4",
"generatedAt": "2024-12-22T12:00:00Z"
}
```
## Conflict Resolution
When sources disagree, resolution follows:
1. **Trust Weight**: Higher trust wins
2. **Lattice Position**: If trust equal, higher lattice position wins
3. **Freshness**: If still tied, more recent statement wins
4. **Tie**: First statement wins
### Resolution Trace
Each merge includes explanation:
```json
{
"leftSource": "vendor:lodash",
"rightSource": "distro:redhat",
"leftStatus": "NotAffected",
"rightStatus": "Affected",
"leftTrust": 0.95,
"rightTrust": 0.90,
"resultStatus": "NotAffected",
"explanation": "'vendor:lodash' has higher trust weight than 'distro:redhat'"
}
```
## UI Components
### Layer Cards
Each layer shows:
- Source names
- Current status badge
- Trust score bar
- Statement count
### Merge Flow Diagram
Visual representation:
```
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
│ Vendor │ ──⊕─│ Distro │ ──⊕─│ Internal │ ──=─│ Final │
│ NotAff. │ │ Affected│ │ — │ │ NotAff. │
│ (0.95) │ │ (0.90) │ │ │ │ (0.925) │
└─────────┘ └─────────┘ └──────────┘ └─────────┘
```
### Missing Evidence CTA
Prominent call-to-action for missing evidence:
```
┌─────────────────────────────────────────┐
│ ⚠ Improve Confidence │
│ │
│ [+] Add internal security assessment │
│ Increases confidence by ~5% │
│ │
│ [+] Add reachability analysis │
│ Determines if code is called │
└─────────────────────────────────────────┘
```
### Merge Traces (Expandable)
Detailed explanation of each merge:
```
▼ Merge Details
Vendor layer:
Sources: lodash-security
Status: NotAffected (trust: 95%)
Distro layer:
Sources: redhat-csaf
Status: Affected (trust: 90%)
Merge: 'lodash-security' has higher trust weight
Internal layer:
No statements
Final: NotAffected (confidence: 92.5%)
```
## Configuration
### Trust Weights
Configure in `trust.yaml`:
```yaml
sources:
vendor: 1.0
distro: 0.9
nvd: 0.8
internal: 0.85
community: 0.5
unknown: 0.3
```
### Lattice Type
Configure lattice in `policy.yaml`:
```yaml
lattice:
type: K4 # or Boolean, 8-state
joinStrategy: trust-weighted
```
## Use Cases
### 1. Understanding Disagreement
When vendor says "not affected" but NVD says "affected":
- View merge preview
- See trust scores
- Understand why vendor wins
- Decide if internal assessment needed
### 2. Adding Internal Context
When external sources lack context:
- View missing evidence
- Click "Add evidence"
- Submit internal VEX statement
- See confidence increase
### 3. Audit Documentation
For compliance:
- Export merge preview
- Include in audit report
- Document decision rationale
## Best Practices
1. **Review Conflicts**: When layers disagree, investigate why
2. **Add Internal Context**: Your reachability data often resolves conflicts
3. **Trust Calibration**: Adjust trust weights based on source accuracy
4. **Document Decisions**: Use merge preview in exception justifications
## Related Documentation
- [VEX Trust Scoring](../excititor/scoring.md)
- [Lattice Configuration](../policy/implementation_plan.md)
- [REPLAY.yaml Specification](./replay-yaml.md)

View File

@@ -0,0 +1,295 @@
# REPLAY.yaml Manifest Specification
## Overview
The **REPLAY.yaml** manifest defines the complete set of inputs required to reproduce a StellaOps evaluation. It is the root document in a `.stella-replay.tgz` bundle.
## File Location
```
.stella-replay.tgz
├── REPLAY.yaml # This manifest
├── sboms/
├── vex/
├── reach/
├── exceptions/
├── policies/
├── feeds/
├── config/
└── SIGNATURE.sig # Optional DSSE signature
```
## Schema Version
Current schema version: `1.0.0`
```yaml
version: "1.0.0"
```
## Complete Example
```yaml
version: "1.0.0"
snapshot:
id: "snap-20241222-abc123"
createdAt: "2024-12-22T12:00:00Z"
artifact: "sha256:abc123..."
previousId: "snap-20241221-xyz789"
inputs:
sboms:
- path: "sboms/cyclonedx.json"
format: "cyclonedx-1.6"
digest: "sha256:def456..."
- path: "sboms/spdx.json"
format: "spdx-3.0.1"
digest: "sha256:ghi789..."
vex:
- path: "vex/vendor-lodash.json"
source: "vendor:lodash"
format: "openvex"
digest: "sha256:jkl012..."
trustScore: 0.95
- path: "vex/redhat-csaf.json"
source: "distro:redhat"
format: "csaf"
digest: "sha256:mno345..."
trustScore: 0.90
reachability:
- path: "reach/api-handler.json"
entryPoint: "/api/handler"
digest: "sha256:pqr678..."
nodeCount: 42
edgeCount: 57
exceptions:
- path: "exceptions/exc-001.json"
exceptionId: "exc-001"
digest: "sha256:stu901..."
policies:
bundlePath: "policies/bundle.tar.gz"
digest: "sha256:vwx234..."
version: "2.1.0"
rulesHash: "sha256:yza567..."
feeds:
- feedId: "nvd"
name: "National Vulnerability Database"
version: "2024-12-22T00:00:00Z"
digest: "sha256:bcd890..."
fetchedAt: "2024-12-22T06:00:00Z"
- feedId: "ghsa"
name: "GitHub Security Advisories"
version: "2024-12-22T01:00:00Z"
digest: "sha256:efg123..."
fetchedAt: "2024-12-22T06:15:00Z"
lattice:
type: "K4"
configDigest: "sha256:hij456..."
trust:
configDigest: "sha256:klm789..."
defaultWeight: 0.5
outputs:
verdictPath: "verdict.json"
verdictDigest: "sha256:nop012..."
findingsPath: "findings.ndjson"
findingsDigest: "sha256:qrs345..."
seeds:
rng: 12345678
sampling: 87654321
environment:
STELLAOPS_POLICY_VERSION: "2.1.0"
STELLAOPS_LATTICE_TYPE: "K4"
signature:
algorithm: "ecdsa-p256"
keyId: "signing-key-prod-2024"
value: "MEUCIQDx..."
```
## Field Reference
### snapshot
Metadata about the snapshot itself.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| id | string | Yes | Unique snapshot identifier |
| createdAt | datetime | Yes | ISO 8601 timestamp |
| artifact | string | Yes | Artifact digest being evaluated |
| previousId | string | No | Previous snapshot for diff |
### inputs.sboms
SBOM documents included in bundle.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| path | string | Yes | Path within bundle |
| format | string | Yes | `cyclonedx-1.6` or `spdx-3.0.1` |
| digest | string | Yes | Content digest |
### inputs.vex
VEX documents from various sources.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| path | string | Yes | Path within bundle |
| source | string | Yes | Source identifier (vendor:*, distro:*, etc.) |
| format | string | Yes | `openvex`, `csaf`, `cyclonedx-vex` |
| digest | string | Yes | Content digest |
| trustScore | number | Yes | Trust weight (0.0-1.0) |
### inputs.reachability
Reachability subgraph data.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| path | string | Yes | Path within bundle |
| entryPoint | string | Yes | Entry point identifier |
| digest | string | Yes | Content digest |
| nodeCount | integer | No | Number of nodes |
| edgeCount | integer | No | Number of edges |
### inputs.exceptions
Active exceptions at snapshot time.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| path | string | Yes | Path within bundle |
| exceptionId | string | Yes | Exception identifier |
| digest | string | Yes | Content digest |
### inputs.policies
Policy bundle reference.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| bundlePath | string | Yes | Path to policy bundle |
| digest | string | Yes | Bundle digest |
| version | string | No | Policy version |
| rulesHash | string | Yes | Hash of compiled rules |
### inputs.feeds
Advisory feed versions at snapshot time.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| feedId | string | Yes | Feed identifier |
| name | string | No | Human-readable name |
| version | string | Yes | Feed version/timestamp |
| digest | string | Yes | Feed content digest |
| fetchedAt | datetime | Yes | When feed was fetched |
### inputs.lattice
Lattice configuration for merge semantics.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| type | string | Yes | `K4`, `Boolean`, `8-state` |
| configDigest | string | Yes | Configuration hash |
### inputs.trust
Trust weight configuration.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| configDigest | string | Yes | Configuration hash |
| defaultWeight | number | No | Default trust weight |
### outputs
Evaluation outputs for verification.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| verdictPath | string | Yes | Path to verdict file |
| verdictDigest | string | Yes | Verdict content digest |
| findingsPath | string | No | Path to findings file |
| findingsDigest | string | No | Findings content digest |
### seeds
Random seeds for deterministic evaluation.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| rng | integer | No | Random number generator seed |
| sampling | integer | No | Sampling algorithm seed |
### environment
Environment variables captured (non-sensitive).
Key-value pairs of environment configuration.
### signature
DSSE signature over manifest.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| algorithm | string | Yes | Signing algorithm |
| keyId | string | Yes | Signing key identifier |
| value | string | Yes | Base64-encoded signature |
## Digest Format
All digests use the format:
```
sha256:<64-char-hex>
```
Example:
```
sha256:a1b2c3d4e5f6...
```
## Validation
Bundle validation checks:
1. REPLAY.yaml exists at bundle root
2. All referenced files exist
3. All digests match content
4. Schema validates against JSON Schema
5. Signature verifies (if present)
## CLI Usage
```bash
# Create bundle
stella snapshot export --output snapshot.stella-replay.tgz
# Verify bundle
stella snapshot verify snapshot.stella-replay.tgz
# Replay from bundle
stella replay --bundle snapshot.stella-replay.tgz
# View manifest
stella snapshot manifest snapshot.stella-replay.tgz
```
## Related Documentation
- [Knowledge Snapshot Model](./knowledge-snapshot.md)
- [Merge Preview](./merge-preview.md)
- [Replay Engine](../../modules/policy/implementation_plan.md)

View File

@@ -0,0 +1,176 @@
# Exploit Path Inbox Architecture
## Overview
The Exploit Path Inbox provides a triage workflow that groups vulnerabilities by their complete attack chain rather than individual CVEs. This enables analysts to assess and remediate entire exploit paths at once, improving efficiency and ensuring comprehensive coverage.
## Key Concepts
### Exploit Path
An **Exploit Path** represents the complete chain from an entry point to a vulnerable symbol:
```
Artifact → Package → Vulnerable Symbol → Entry Point
```
For example:
```
sha256:abc... → pkg:npm/lodash@4.17.19 → _.template() → /api/render
```
### Path ID Generation
Path IDs are deterministic hashes ensuring stable references:
```
PathId = SHA256(artifactDigest | packagePurl | symbolName | entryPointName)
```
This allows:
- Consistent tracking across scans
- Stable exception targeting
- Reproducible audits
### Grouping Logic
Findings are grouped into exploit paths based on:
1. **Reachability Graph**: If reachability data exists, group by actual call paths
2. **Fallback**: If no reachability, group by package only
## Data Model
### ExploitPath
| Field | Type | Description |
|-------|------|-------------|
| `pathId` | string | Stable deterministic identifier |
| `artifactDigest` | string | Container image digest |
| `package` | PackageRef | Package containing vulnerability |
| `symbol` | VulnerableSymbol | Vulnerable function/method |
| `entryPoint` | EntryPoint | Entry point exposing the path |
| `cveIds` | string[] | All CVEs affecting this path |
| `reachability` | ReachabilityStatus | Reachability lattice state |
| `riskScore` | PathRiskScore | Aggregated risk metrics |
| `evidence` | PathEvidence | Supporting evidence |
| `activeExceptions` | ExceptionRef[] | Active suppressions |
| `isQuiet` | boolean | Whether path is suppressed |
### ReachabilityStatus
| State | Description |
|-------|-------------|
| `Unknown` | No reachability analysis performed |
| `StaticallyReachable` | Static analysis found a path |
| `RuntimeConfirmed` | Runtime observation confirmed reachability |
| `Unreachable` | Confirmed not reachable |
| `Contested` | Conflicting evidence |
## API Endpoints
### GET /triage/inbox
Returns exploit paths for a given scope.
**Query Parameters:**
- `artifactDigest` (string): Filter by artifact
- `environment` (string): Filter by environment
- `quiet` (boolean): Filter by suppression status
- `minCvss` (number): Minimum CVSS score
- `reachability` (string): Filter by reachability status
- `offset` (number): Pagination offset
- `limit` (number): Page size (default 50)
**Response:**
```json
{
"paths": [...],
"totalCount": 42,
"quietCount": 12,
"activeCount": 30,
"offset": 0,
"limit": 50
}
```
### GET /triage/paths/{pathId}
Returns detailed exploit path information.
### GET /triage/paths/{pathId}/proof
Returns proof bundle (see proof-bundle-spec.md).
## UI Components
### Three-Pane Layout
1. **Left Pane (Path List)**
- Exploit paths sorted by risk
- Quiet/Active toggle
- Search by CVE, package, symbol
- Risk score badges
2. **Center Pane (Path Detail)**
- CVE list with scores
- Package and symbol info
- Entry point context
- Active exceptions
- "Create Exception" button
3. **Right Pane (Proof Viewer)**
- Reach subgraph visualization
- Symbol map with source links
- VEX claims with trust badges
- "Export Proof" button
## Integration Points
### Exception System
Exceptions can target exploit paths via `pathId`:
```yaml
scope:
pathId: "path:abc123..."
```
This suppresses all CVEs in the path at once.
### Build Gates
Build gates can query by exploit path reachability:
```yaml
gates:
- name: block-reachable-critical
condition: reachability == "RuntimeConfirmed" && severity == "Critical"
action: block
```
### VEX Generation
VEX statements can reference exploit paths for context:
```json
{
"vulnerability": "CVE-2024-1234",
"product": "sha256:abc...",
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"context": {
"exploitPathId": "path:abc123..."
}
}
```
## Best Practices
1. **Triage by Path**: Address entire exploit paths, not individual CVEs
2. **Use Reachability**: Prioritize runtime-confirmed paths
3. **Document Evidence**: Attach proof bundles to exceptions
4. **Regular Review**: Re-evaluate paths when reachability changes
## Related Documentation
- [Proof Bundle Specification](./proof-bundle-spec.md)
- [Recheck Policy](../policy/recheck-policy.md)
- [Evidence Hooks](../policy/evidence-hooks.md)

View File

@@ -0,0 +1,235 @@
# Proof Bundle Specification
## Overview
A **Proof Bundle** aggregates all evidence supporting an exploit path assessment. It provides a complete, self-contained package for audit, compliance, and decision-making.
## Bundle Contents
### 1. Reach Subgraph
The reachability subgraph shows the call path from entry point to vulnerable symbol.
```json
{
"nodes": [
{
"id": "node-001",
"label": "handleRequest",
"type": "entryPoint",
"depth": 0,
"isVulnerable": false,
"isEntryPoint": true
},
{
"id": "node-002",
"label": "renderTemplate",
"type": "function",
"depth": 1,
"isVulnerable": false,
"isEntryPoint": false
},
{
"id": "node-003",
"label": "_.template",
"type": "vulnerableSymbol",
"depth": 2,
"isVulnerable": true,
"isEntryPoint": false
}
],
"edges": [
{
"sourceId": "node-001",
"targetId": "node-002",
"label": "calls",
"weight": 0.95
},
{
"sourceId": "node-002",
"targetId": "node-003",
"label": "calls",
"weight": 0.90
}
],
"entryPointId": "node-001",
"vulnerableSymbolId": "node-003",
"totalNodes": 3,
"totalEdges": 2
}
```
### 2. Symbol Map
Maps symbol identifiers to source code locations.
```json
{
"symbols": [
{
"id": "node-001",
"fullyQualifiedName": "src.api.handleRequest",
"sourceFile": "src/api/handler.js",
"lineNumber": 42,
"language": "javascript",
"signature": "function handleRequest(req, res)"
},
{
"id": "node-003",
"fullyQualifiedName": "lodash.template",
"sourceFile": "node_modules/lodash/template.js",
"lineNumber": 156,
"language": "javascript",
"signature": "function template(string, options)"
}
],
"sourceFiles": [
"src/api/handler.js",
"node_modules/lodash/template.js"
]
}
```
### 3. VEX Claims
VEX statements from various sources with trust scores.
```json
{
"vexClaims": [
{
"cveId": "CVE-2024-1234",
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"source": "vendor:lodash",
"trustScore": 0.95,
"timestamp": "2024-12-22T10:00:00Z",
"signatureValid": true
},
{
"cveId": "CVE-2024-1234",
"status": "affected",
"justification": null,
"source": "nvd",
"trustScore": 0.80,
"timestamp": "2024-12-20T08:00:00Z",
"signatureValid": false
}
]
}
```
### 4. Trust Scores
Aggregated confidence metrics.
```json
{
"trustScores": {
"reachabilityConfidence": 0.90,
"vexConfidence": 0.85,
"overallConfidence": 0.875,
"evidenceCount": 5
}
}
```
## API Endpoint
### GET /triage/paths/{pathId}/proof
Returns the complete proof bundle.
**Response:**
```json
{
"pathId": "path:abc123...",
"generatedAt": "2024-12-22T12:00:00Z",
"reachSubgraph": { ... },
"symbolMap": { ... },
"vexClaims": [ ... ],
"trustScores": { ... },
"bundleDigest": "sha256:def456..."
}
```
### GET /triage/paths/{pathId}/proof/export
Returns proof bundle as downloadable JSON file.
## Bundle Integrity
Each bundle includes a digest for integrity verification:
```
bundleDigest = SHA256(canonical_json(bundle_without_digest))
```
This allows:
- Tamper detection
- Audit trail verification
- Reproducible exports
## Visualization
### Reach Graph Rendering
Use Cytoscape.js or similar for interactive visualization:
- Nodes colored by type (entry point, intermediate, vulnerable)
- Edge width indicates confidence weight
- Collapsible for large graphs
### Symbol Navigation
Click-through from symbols to source code:
- IDE integration (VS Code, JetBrains)
- GitHub/GitLab links
- Line number highlighting
### VEX Claim Comparison
Side-by-side view of conflicting VEX statements:
- Trust score comparison
- Timestamp ordering
- Signature verification badges
## Use Cases
### Exception Creation
When creating an exception, attach proof bundle:
```yaml
exception:
pathId: "path:abc123..."
proofBundleDigest: "sha256:def456..."
evidence:
- type: proof-bundle
reference: "/triage/paths/path:abc123.../proof"
```
### Compliance Audit
Export proof bundles for compliance documentation:
1. Query all active exceptions
2. Export proof bundle for each
3. Generate PDF report with embedded evidence
### Dispute Resolution
When VEX claims conflict:
1. View all claims in proof bundle
2. Compare trust scores and timestamps
3. Document resolution rationale
## Schema Validation
Proof bundles must validate against JSON Schema:
```
$id: https://stellaops.io/schemas/proof-bundle/v1
```
## Related Documentation
- [Exploit Path Inbox](./exploit-path-inbox.md)
- [VEX Trust Scoring](../excititor/scoring.md)
- [Reachability Analysis](../scanner/operations/entrypoint.md)

View File

@@ -1,17 +1,17 @@
Heres a tight, firsttimefriendly blueprint for two StellaOps UX pillars—**Triage & Exceptions** and **Knowledge Snapshots & Merge Semantics**—with just enough background plus concrete specs your PMs/devs can ship. Here's a tight, firsttimefriendly blueprint for two Stella Ops UX pillars—**Triage & Exceptions** and **Knowledge Snapshots & Merge Semantics**—with just enough background plus concrete specs your PMs/devs can ship.
--- ---
# Triage & Exceptions (quietbydesign) # Triage & Exceptions (quietbydesign)
**Why it matters (plain English):** Most scanners drown users in alerts. Quietbydesign shows only *provable, reachable* risks and lets you create **auditable exceptions** (temporary waivers) that autofeed compliance packs. **Why it matters (plain English):** Most scanners drown users in alerts. "Quietbydesign" shows only *provable, reachable* risks and lets you create **auditable exceptions** (temporary waivers) that autofeed compliance packs.
**User flow** **User flow**
1. **Inbox grouped by exploit path** 1. **Inbox grouped by exploit path**
* Group key = `(artifact → package → vulnerable symbol → runtime path)`. * Group key = `(artifact → package → vulnerable symbol → runtime path)`.
* Each group shows: risk score, blast radius (count of dependents), EPSS/CVSS, and a Proof button. * Each group shows: risk score, blast radius (count of dependents), EPSS/CVSS, and a "Proof" button.
2. **Open a path → Proof bundle** 2. **Open a path → Proof bundle**
* **Reach subgraph** (who calls what). * **Reach subgraph** (who calls what).
@@ -19,7 +19,7 @@ Heres a tight, firsttimefriendly blueprint for two StellaOps UX pill
* **VEX claims** (vendor/distro/internal) with trust score + signatures. * **VEX claims** (vendor/distro/internal) with trust score + signatures.
3. **Raise Exception** (timeboxed) 3. **Raise Exception** (timeboxed)
* **Required fields:** attested reason (dropdown + free text), expiry date, recheck policy (e.g., fail build if new reachable path appears, fail if EPSS > X). * **Required fields:** attested reason (dropdown + free text), expiry date, recheck policy (e.g., "fail build if new reachable path appears", "fail if EPSS > X").
* **Attestation:** DSSEsigned exception object, OCIattached to artifact digest. * **Attestation:** DSSEsigned exception object, OCIattached to artifact digest.
* Autolands in **Audit Pack** (PDF/JSON bundle) and **Timeline**. * Autolands in **Audit Pack** (PDF/JSON bundle) and **Timeline**.
@@ -64,7 +64,7 @@ record ExceptionObj(
# Knowledge Snapshots & Merge Semantics # Knowledge Snapshots & Merge Semantics
**Plain English:** Take a sealed photo of everything you *know* at a point in time—SBOM, VEX, attestations, policies—so audits and incident reviews can be replayed exactly. **Plain English:** Take a sealed "photo" of everything you *know* at a point in time—SBOM, VEX, attestations, policies—so audits and incident reviews can be replayed exactly.
**Lifecycle: Snapshot → Seal → Export** **Lifecycle: Snapshot → Seal → Export**
@@ -82,19 +82,19 @@ record ExceptionObj(
**Policy pane with merge semantics** **Policy pane with merge semantics**
* Default preview: **vendor ⊕ distro ⊕ internal** (not vendor > distro > internal). * Default preview: **vendor ⊕ distro ⊕ internal** (not "vendor > distro > internal").
* **Lattice rules** define resolution (e.g., `NOT_AFFECTED ⊕ AFFECTED → AFFECTED unless Evidence(feature_flag_off)`). * **Lattice rules** define resolution (e.g., `NOT_AFFECTED ⊕ AFFECTED → AFFECTED unless Evidence(feature_flag_off)`).
* **Evidence hooks (required):** * **Evidence hooks (required):**
* Not affected because feature X off → must include **featureflag attestation** (envscoped, signed). * "Not affected because feature X off" → must include **featureflag attestation** (envscoped, signed).
* Backported patch → must include **patchindex** mapping (`fixedsymbols`, commit OIDs). * "Backported patch" → must include **patchindex** mapping (`fixedsymbols`, commit OIDs).
* Compensating control → must include **control attestation** (control ID, monitoring link, SLO). * "Compensating control" → must include **control attestation** (control ID, monitoring link, SLO).
**UI essentials** **UI essentials**
* **Snapshot panel:** shows inputs (feed versions, rules hash), diff vs last snapshot, Seal & Export button. * **Snapshot panel:** shows inputs (feed versions, rules hash), diff vs last snapshot, "Seal & Export" button.
* **Policy pane:** interactive merge preview; failed hooks highlighted with Add evidence CTA. * **Policy pane:** interactive merge preview; failed hooks highlighted with "Add evidence" CTA.
* **Replay check:** Verify determinism runs local reeval; shows PASS/FAIL badge. * **Replay check:** "Verify determinism" runs local reeval; shows PASS/FAIL badge.
**APIs** **APIs**
@@ -138,3 +138,22 @@ record ExceptionObj(
--- ---
If you want, I can turn this into: (a) Swagger stubs, (b) EF Core schema + migrations, or (c) a Figmaready UI spec with screen flows and copy. If you want, I can turn this into: (a) Swagger stubs, (b) EF Core schema + migrations, or (c) a Figmaready UI spec with screen flows and copy.
---
## Archive Note
**Archived:** 2025-12-22
**Disposition:** Converted to implementation sprints:
- `SPRINT_3900_0003_0001_exploit_path_inbox_proof_bundles.md`
- `SPRINT_3900_0003_0002_recheck_policy_evidence_hooks.md`
- `SPRINT_4100_0003_0001_snapshot_merge_preview_replay_ui.md`
**Documentation created:**
- `docs/modules/triage/exploit-path-inbox.md`
- `docs/modules/triage/proof-bundle-spec.md`
- `docs/modules/policy/recheck-policy.md`
- `docs/modules/policy/evidence-hooks.md`
- `docs/modules/snapshot/replay-yaml.md`
- `docs/modules/snapshot/merge-preview.md`