sprints completion. new product advisories prepared
This commit is contained in:
@@ -945,19 +945,239 @@ Binary extraction and fingerprint generation MUST run with:
|
||||
|
||||
### 7.3 Ops Endpoints
|
||||
|
||||
> **Sprint:** SPRINT_20260112_007_BINIDX_binaryindex_user_config
|
||||
|
||||
BinaryIndex exposes read-only ops endpoints for health, bench, cache, and effective configuration:
|
||||
|
||||
- GET `/api/v1/ops/binaryindex/health` -> BinaryIndexOpsHealthResponse
|
||||
- POST `/api/v1/ops/binaryindex/bench/run` -> BinaryIndexBenchResponse
|
||||
- GET `/api/v1/ops/binaryindex/cache` -> BinaryIndexFunctionCacheStats
|
||||
- GET `/api/v1/ops/binaryindex/config` -> BinaryIndexEffectiveConfig
|
||||
| Endpoint | Method | Response Schema | Description |
|
||||
|----------|--------|-----------------|-------------|
|
||||
| `/api/v1/ops/binaryindex/health` | GET | `BinaryIndexOpsHealthResponse` | Health status, lifter warmness per ISA, cache availability |
|
||||
| `/api/v1/ops/binaryindex/bench/run` | POST | `BinaryIndexBenchResponse` | Run latency benchmark, return min/max/mean/p50/p95/p99 stats |
|
||||
| `/api/v1/ops/binaryindex/cache` | GET | `BinaryIndexFunctionCacheStats` | Function cache hit/miss/eviction statistics |
|
||||
| `/api/v1/ops/binaryindex/config` | GET | `BinaryIndexEffectiveConfig` | Effective configuration with secrets redacted |
|
||||
|
||||
#### 7.3.1 Response Schemas
|
||||
|
||||
**BinaryIndexOpsHealthResponse:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2026-01-16T12:00:00Z",
|
||||
"components": {
|
||||
"lifterPool": { "status": "healthy", "message": null },
|
||||
"functionCache": { "status": "healthy", "message": null },
|
||||
"persistence": { "status": "healthy", "message": null }
|
||||
},
|
||||
"lifterWarmness": {
|
||||
"intel-64": { "isa": "intel-64", "warm": true, "poolSize": 4, "acquireTimeMs": 12 },
|
||||
"armv8-64": { "isa": "armv8-64", "warm": true, "poolSize": 2, "acquireTimeMs": 8 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**BinaryIndexBenchResponse:**
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-16T12:00:00Z",
|
||||
"sampleSize": 100,
|
||||
"latencySummary": {
|
||||
"minMs": 5.2,
|
||||
"maxMs": 142.8,
|
||||
"meanMs": 28.4,
|
||||
"p50Ms": 22.1,
|
||||
"p95Ms": 78.3,
|
||||
"p99Ms": 121.5
|
||||
},
|
||||
"operations": [
|
||||
{ "operation": "lifterAcquire", "samples": 100, "meanMs": 12.4 },
|
||||
{ "operation": "irNormalization", "samples": 100, "meanMs": 8.7 },
|
||||
{ "operation": "cacheLookup", "samples": 100, "meanMs": 1.2 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**BinaryIndexFunctionCacheStats:**
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"backend": "valkey",
|
||||
"hits": 15234,
|
||||
"misses": 892,
|
||||
"evictions": 45,
|
||||
"hitRate": 0.944,
|
||||
"keyPrefix": "stellaops:binidx:funccache:",
|
||||
"cacheTtlSeconds": 14400,
|
||||
"estimatedEntries": 12500,
|
||||
"estimatedMemoryBytes": 52428800
|
||||
}
|
||||
```
|
||||
|
||||
**BinaryIndexEffectiveConfig:**
|
||||
```json
|
||||
{
|
||||
"b2r2Pool": {
|
||||
"maxPoolSizePerIsa": 4,
|
||||
"warmPreload": ["intel-64", "armv8-64"],
|
||||
"acquireTimeoutMs": 5000,
|
||||
"enableMetrics": true
|
||||
},
|
||||
"semanticLifting": {
|
||||
"b2r2Version": "1.5.0",
|
||||
"normalizationRecipeVersion": "2024.1",
|
||||
"maxInstructionsPerFunction": 10000,
|
||||
"maxFunctionsPerBinary": 5000,
|
||||
"functionLiftTimeoutMs": 30000,
|
||||
"enableDeduplication": true
|
||||
},
|
||||
"functionCache": {
|
||||
"connectionString": "********",
|
||||
"keyPrefix": "stellaops:binidx:funccache:",
|
||||
"cacheTtlSeconds": 14400,
|
||||
"maxTtlSeconds": 86400,
|
||||
"earlyExpiryPercent": 0.1,
|
||||
"maxEntrySizeBytes": 1048576
|
||||
},
|
||||
"persistence": {
|
||||
"schema": "binaries",
|
||||
"minPoolSize": 5,
|
||||
"maxPoolSize": 20,
|
||||
"commandTimeoutSeconds": 30,
|
||||
"retryOnFailure": true,
|
||||
"batchSize": 100
|
||||
},
|
||||
"backendVersions": {
|
||||
"b2r2": "1.5.0",
|
||||
"valkey": "7.2.0",
|
||||
"postgres": "15.4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 7.3.2 Rate Limiting
|
||||
|
||||
The `/bench/run` endpoint is rate-limited to prevent load spikes:
|
||||
- Default: 5 requests per minute per tenant
|
||||
- Configurable via `BinaryIndex:Ops:BenchRateLimitPerMinute`
|
||||
|
||||
#### 7.3.3 Secret Redaction
|
||||
|
||||
The config endpoint automatically redacts sensitive keys:
|
||||
|
||||
| Redacted Keys | Pattern |
|
||||
|---------------|---------|
|
||||
| `connectionString` | Replaced with `********` |
|
||||
| `password` | Replaced with `********` |
|
||||
| `secret*` | Any key starting with "secret" |
|
||||
| `apiKey` | Replaced with `********` |
|
||||
| `token` | Replaced with `********` |
|
||||
|
||||
Redaction is applied recursively to nested objects.
|
||||
|
||||
---
|
||||
|
||||
## 8. Configuration
|
||||
|
||||
> **Sprint:** SPRINT_20260112_007_BINIDX_binaryindex_user_config
|
||||
|
||||
### 8.1 Configuration Sections
|
||||
|
||||
All configuration is under the `BinaryIndex` section in `appsettings.yaml` or environment variables with `BINARYINDEX__` prefix.
|
||||
|
||||
#### 8.1.1 B2R2 Lifter Pool (`BinaryIndex:B2R2Pool`)
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `MaxPoolSizePerIsa` | int | 4 | Maximum lifter instances per ISA |
|
||||
| `WarmPreload` | string[] | ["intel-64", "armv8-64"] | ISAs to warm on startup |
|
||||
| `AcquireTimeoutMs` | int | 5000 | Timeout for lifter acquisition |
|
||||
| `EnableMetrics` | bool | true | Emit Prometheus metrics for pool |
|
||||
|
||||
```yaml
|
||||
# binaryindex.yaml
|
||||
BinaryIndex:
|
||||
B2R2Pool:
|
||||
MaxPoolSizePerIsa: 4
|
||||
WarmPreload:
|
||||
- intel-64
|
||||
- armv8-64
|
||||
AcquireTimeoutMs: 5000
|
||||
EnableMetrics: true
|
||||
```
|
||||
|
||||
#### 8.1.2 Semantic Lifting (`BinaryIndex:SemanticLifting`)
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `B2R2Version` | string | "1.5.0" | B2R2 disassembler version |
|
||||
| `NormalizationRecipeVersion` | string | "2024.1" | IR normalization recipe version |
|
||||
| `MaxInstructionsPerFunction` | int | 10000 | Max instructions to lift per function |
|
||||
| `MaxFunctionsPerBinary` | int | 5000 | Max functions to process per binary |
|
||||
| `FunctionLiftTimeoutMs` | int | 30000 | Timeout for lifting single function |
|
||||
| `EnableDeduplication` | bool | true | Deduplicate IR before fingerprinting |
|
||||
|
||||
```yaml
|
||||
BinaryIndex:
|
||||
SemanticLifting:
|
||||
MaxInstructionsPerFunction: 10000
|
||||
MaxFunctionsPerBinary: 5000
|
||||
FunctionLiftTimeoutMs: 30000
|
||||
EnableDeduplication: true
|
||||
```
|
||||
|
||||
#### 8.1.3 Function Cache (`BinaryIndex:FunctionCache`)
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `ConnectionString` | string | — | Valkey connection string (secret) |
|
||||
| `KeyPrefix` | string | "stellaops:binidx:funccache:" | Cache key prefix |
|
||||
| `CacheTtlSeconds` | int | 14400 | Default cache TTL (4 hours) |
|
||||
| `MaxTtlSeconds` | int | 86400 | Maximum TTL (24 hours) |
|
||||
| `EarlyExpiryPercent` | decimal | 0.1 | Early expiry jitter (10%) |
|
||||
| `MaxEntrySizeBytes` | int | 1048576 | Max entry size (1 MB) |
|
||||
|
||||
```yaml
|
||||
BinaryIndex:
|
||||
FunctionCache:
|
||||
ConnectionString: ${VALKEY_CONNECTION} # from env
|
||||
KeyPrefix: "stellaops:binidx:funccache:"
|
||||
CacheTtlSeconds: 14400
|
||||
MaxEntrySizeBytes: 1048576
|
||||
```
|
||||
|
||||
#### 8.1.4 Persistence (`Postgres:BinaryIndex`)
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `Schema` | string | "binaries" | PostgreSQL schema name |
|
||||
| `MinPoolSize` | int | 5 | Minimum connection pool size |
|
||||
| `MaxPoolSize` | int | 20 | Maximum connection pool size |
|
||||
| `CommandTimeoutSeconds` | int | 30 | Command execution timeout |
|
||||
| `RetryOnFailure` | bool | true | Retry transient failures |
|
||||
| `BatchSize` | int | 100 | Batch insert size |
|
||||
|
||||
```yaml
|
||||
Postgres:
|
||||
BinaryIndex:
|
||||
Schema: binaries
|
||||
MinPoolSize: 5
|
||||
MaxPoolSize: 20
|
||||
CommandTimeoutSeconds: 30
|
||||
RetryOnFailure: true
|
||||
BatchSize: 100
|
||||
```
|
||||
|
||||
#### 8.1.5 Ops Configuration (`BinaryIndex:Ops`)
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `EnableHealthEndpoint` | bool | true | Enable /health endpoint |
|
||||
| `EnableBenchEndpoint` | bool | true | Enable /bench/run endpoint |
|
||||
| `BenchRateLimitPerMinute` | int | 5 | Rate limit for bench endpoint |
|
||||
| `RedactedKeys` | string[] | See 7.3.3 | Keys to redact in config output |
|
||||
|
||||
### 8.2 Legacy Configuration
|
||||
|
||||
```yaml
|
||||
# binaryindex.yaml (corpus configuration)
|
||||
binaryindex:
|
||||
enabled: true
|
||||
|
||||
@@ -995,12 +1215,6 @@ binaryindex:
|
||||
rustfs_bucket: stellaops/binaryindex
|
||||
```
|
||||
|
||||
Additional appsettings sections (case-insensitive):
|
||||
- `BinaryIndex:B2R2Pool` - lifter pool sizing and warm ISA list.
|
||||
- `BinaryIndex:SemanticLifting` - LowUIR enablement and deterministic controls.
|
||||
- `BinaryIndex:FunctionCache` - Valkey function cache configuration.
|
||||
- `Postgres:BinaryIndex` - persistence for canonical IR fingerprints.
|
||||
|
||||
---
|
||||
|
||||
## 9. Testing Strategy
|
||||
|
||||
@@ -19,6 +19,131 @@ stella attest list --tenant default --issuer dev-kms --format table
|
||||
stella attest show --id a1b2c3 --output json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verify Offline (Air-Gapped Environments)
|
||||
|
||||
Verify attestation bundles completely offline without network access.
|
||||
|
||||
### Synopsis
|
||||
|
||||
```bash
|
||||
stella attest verify-offline --bundle <path.tar.gz> [options]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Alias | Description |
|
||||
|--------|-------|-------------|
|
||||
| `--bundle <path>` | `-b` | **Required.** Path to attestation bundle (tar.gz). |
|
||||
| `--checkpoint <path>` | `-c` | Path to Rekor checkpoint signature file. |
|
||||
| `--trust-root <dir>` | `-r` | Path to trust root directory containing CA certificates. |
|
||||
| `--artifact <digest>` | `-a` | Expected artifact digest (sha256:...) to verify against. |
|
||||
| `--predicate-type <type>` | `-p` | Expected predicate type (e.g., https://slsa.dev/provenance/v1). |
|
||||
| `--output <file>` | `-o` | Write verification report to file instead of stdout. |
|
||||
| `--format <fmt>` | `-f` | Output format: `json`, `summary` (default), or `html`. |
|
||||
| `--strict` | | Fail if any optional verification step fails. |
|
||||
| `--verbose` | | Show detailed verification progress. |
|
||||
|
||||
### Verification Checks
|
||||
|
||||
The command performs the following verification checks:
|
||||
|
||||
1. **DSSE Envelope Signature**: Validates the DSSE envelope structure and signatures.
|
||||
2. **Merkle Inclusion Proof**: Verifies Rekor transparency log inclusion proof.
|
||||
3. **Checkpoint Signature**: Validates checkpoint signature against trusted keys.
|
||||
4. **Content Hash**: Ensures all file hashes match the manifest.
|
||||
|
||||
### Exit Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| 0 | Verification passed |
|
||||
| 1 | Verification failed (one or more checks failed) |
|
||||
| 2 | Error (file not found, parse error, etc.) |
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Basic offline verification
|
||||
stella attest verify-offline --bundle evidence.tar.gz
|
||||
|
||||
# Full verification with all options
|
||||
stella attest verify-offline \
|
||||
--bundle evidence.tar.gz \
|
||||
--checkpoint checkpoint.sig \
|
||||
--trust-root /path/to/roots/ \
|
||||
--artifact sha256:abc123def456 \
|
||||
--predicate-type https://slsa.dev/provenance/v1
|
||||
|
||||
# Generate JSON verification report
|
||||
stella attest verify-offline \
|
||||
--bundle evidence.tar.gz \
|
||||
--format json \
|
||||
--output report.json
|
||||
|
||||
# Strict mode (fail on optional check failures)
|
||||
stella attest verify-offline --bundle evidence.tar.gz --strict
|
||||
```
|
||||
|
||||
### Sample Output
|
||||
|
||||
```
|
||||
Attestation Verification Report
|
||||
================================
|
||||
Bundle: evidence.tar.gz
|
||||
Status: VERIFIED
|
||||
|
||||
Checks:
|
||||
[PASS] DSSE envelope signature valid
|
||||
[PASS] Merkle inclusion proof verified (log index: 12345)
|
||||
[PASS] Checkpoint signature valid (origin: rekor.sigstore.dev)
|
||||
[PASS] Content hash matches manifest
|
||||
|
||||
Artifact: sha256:abc123...
|
||||
Signed by: identity@example.com
|
||||
Timestamp: 2026-01-14T10:30:00Z
|
||||
```
|
||||
|
||||
### Bundle Format
|
||||
|
||||
The attestation bundle should be a tar.gz archive containing:
|
||||
|
||||
```
|
||||
evidence.tar.gz
|
||||
├── attestation.dsse.json # DSSE envelope with signature
|
||||
├── manifest.json # File inventory with SHA-256 hashes
|
||||
├── metadata.json # Generation timestamp, tool versions
|
||||
├── certs/
|
||||
│ ├── signing-cert.pem # Signing certificate
|
||||
│ └── fulcio-root.pem # Fulcio root CA (optional)
|
||||
└── rekor-proof/ # Transparency log proof (optional)
|
||||
├── inclusion-proof.json
|
||||
└── checkpoint.sig
|
||||
```
|
||||
|
||||
### Air-Gap Workflow
|
||||
|
||||
1. **Export bundle** on connected system:
|
||||
```bash
|
||||
stella evidence export --scan-id <id> --output bundle.tar.gz
|
||||
```
|
||||
|
||||
2. **Transfer bundle** to air-gapped system via secure media.
|
||||
|
||||
3. **Verify offline** on air-gapped system:
|
||||
```bash
|
||||
stella attest verify-offline --bundle bundle.tar.gz --trust-root /roots/
|
||||
```
|
||||
|
||||
### Cross-Platform Determinism
|
||||
|
||||
The verification output is deterministic across platforms:
|
||||
- Line endings normalized to LF
|
||||
- Hex digests always lowercase
|
||||
- Timestamps in ISO 8601 UTC format
|
||||
- Paths use forward slashes
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- `stella sbom generate --image <ref> [--output sbom.spdx.json] [--offline]`
|
||||
- `stella sbom compose --fragment <path> --output composition.json --offline`
|
||||
- `stella sbom verify --file <sbom> --signature <sig> --key <keyfile>`
|
||||
- `stella sbom verify --archive <path.tar.gz> [--offline] [--trust-root <dir>]` — Verify signed SBOM archive
|
||||
|
||||
## Flags (common)
|
||||
- `--offline`: no network pulls; use local cache/OCI archive.
|
||||
@@ -23,3 +24,114 @@
|
||||
## Offline/air-gap notes
|
||||
- With `--offline`, image sources must already be cached (tar/OCI archive); command fails with exit code 5 if it would fetch remotely.
|
||||
- Verification uses local trust roots; no remote key fetch.
|
||||
|
||||
---
|
||||
|
||||
## stella sbom verify — Signed Archive Verification
|
||||
|
||||
### Synopsis
|
||||
|
||||
```bash
|
||||
stella sbom verify --archive <path.tar.gz> [options]
|
||||
```
|
||||
|
||||
Verify a signed SBOM archive (tar.gz) containing SBOM, DSSE envelope, manifest, and verification materials.
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Alias | Description |
|
||||
|--------|-------|-------------|
|
||||
| `--archive <path>` | `-a` | **Required.** Path to signed SBOM archive (tar.gz). |
|
||||
| `--offline` | | Perform offline verification using bundled certificates. |
|
||||
| `--trust-root <dir>` | `-r` | Path to trust root directory containing CA certificates. |
|
||||
| `--output <file>` | `-o` | Write verification report to file instead of stdout. |
|
||||
| `--format <fmt>` | `-f` | Output format: `json`, `summary` (default), or `html`. |
|
||||
| `--strict` | | Fail if any optional verification step fails. |
|
||||
| `--verbose` | | Show detailed verification progress. |
|
||||
|
||||
### Verification Checks
|
||||
|
||||
The command performs the following verification checks:
|
||||
|
||||
1. **Archive Integrity**: Validates all file hashes against `manifest.json`.
|
||||
2. **DSSE Envelope Signature**: Verifies the DSSE envelope structure and signatures.
|
||||
3. **SBOM Schema**: Validates SBOM content against SPDX or CycloneDX schemas.
|
||||
4. **Tool Version**: Verifies tool version metadata is present and valid.
|
||||
5. **Timestamp Validity**: Checks generation timestamp is within acceptable window.
|
||||
|
||||
### Exit Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------|---------|
|
||||
| 0 | Verification passed |
|
||||
| 1 | Verification failed (one or more checks failed) |
|
||||
| 2 | Error (file not found, parse error, etc.) |
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Verify a signed SBOM archive with summary output
|
||||
stella sbom verify --archive signed-sbom-sha256-abc123.tar.gz
|
||||
|
||||
# Verify offline with custom trust root
|
||||
stella sbom verify --archive signed-sbom.tar.gz --offline --trust-root /path/to/roots/
|
||||
|
||||
# Generate JSON verification report
|
||||
stella sbom verify --archive signed-sbom.tar.gz --format json --output report.json
|
||||
|
||||
# Generate HTML report for sharing
|
||||
stella sbom verify --archive signed-sbom.tar.gz --format html --output report.html
|
||||
|
||||
# Strict mode (fail on optional check failures)
|
||||
stella sbom verify --archive signed-sbom.tar.gz --strict
|
||||
```
|
||||
|
||||
### Sample Output
|
||||
|
||||
```
|
||||
SBOM Verification Report
|
||||
========================
|
||||
Archive: signed-sbom-sha256-abc123.tar.gz
|
||||
Status: VERIFIED
|
||||
|
||||
Checks:
|
||||
[PASS] Archive integrity (All 4 file hashes verified)
|
||||
[PASS] DSSE envelope signature (Valid, 1 signature(s))
|
||||
[PASS] SBOM schema (Valid, SPDX 2.3)
|
||||
[PASS] Tool version (Suite: 2027.Q1, Scanner: 1.2.3)
|
||||
[PASS] Timestamp validity (Within validity window, 2026-01-15)
|
||||
|
||||
SBOM Details:
|
||||
Format: SPDX 2.3
|
||||
Components: 142
|
||||
Artifact: sha256:abc123def456
|
||||
Generated: 2026-01-15T10:30:00Z
|
||||
Tool: StellaOps Scanner v2027.Q1
|
||||
```
|
||||
|
||||
### Archive Format
|
||||
|
||||
The signed SBOM archive follows the format defined in `SPRINT_20260112_016_SCANNER_signed_sbom_archive_spec`:
|
||||
|
||||
```
|
||||
signed-sbom-{digest}-{timestamp}.tar.gz
|
||||
├── sbom.spdx.json (or sbom.cdx.json)
|
||||
├── sbom.dsse.json
|
||||
├── manifest.json
|
||||
├── metadata.json
|
||||
├── certs/
|
||||
│ ├── signing-cert.pem
|
||||
│ └── fulcio-root.pem
|
||||
├── rekor-proof/
|
||||
│ ├── inclusion-proof.json
|
||||
│ └── checkpoint.sig
|
||||
├── schemas/
|
||||
│ └── ...
|
||||
└── VERIFY.md
|
||||
```
|
||||
|
||||
### Related Commands
|
||||
|
||||
- `stella sbom generate` — Generate SBOM from container image
|
||||
- `stella attest verify --offline` — Verify attestation bundles offline
|
||||
- `stella evidence export` — Export evidence bundle with signed SBOM
|
||||
|
||||
@@ -38,3 +38,113 @@ observability:
|
||||
|
||||
## Profiles (planned)
|
||||
- Profiles will live under `profiles/<name>.yaml` and can be selected with `--profile <name>`; until shipped, stick to the single default config file.
|
||||
|
||||
---
|
||||
|
||||
## Config Inspection Commands
|
||||
|
||||
> **Sprint:** SPRINT_20260112_014_CLI_config_viewer
|
||||
|
||||
The CLI provides unified config inspection across all StellaOps modules.
|
||||
|
||||
### List All Config Paths
|
||||
|
||||
```bash
|
||||
# List all supported config paths
|
||||
stella config list
|
||||
|
||||
# Output:
|
||||
# Path Alias Module
|
||||
# ────────────────────────────────────────────────────────────────────────
|
||||
# policy.determinization policy:determinization Policy
|
||||
# policy.confidenceweights policy:weights Policy
|
||||
# scanner scanner Scanner
|
||||
# scanner.reachability.prgate scanner:prgate Scanner
|
||||
# attestor.rekor attestor:rekor Attestor
|
||||
# signals.evidenceweightedscore signals:ews Signals
|
||||
# ...
|
||||
|
||||
# Filter by module
|
||||
stella config list --module policy
|
||||
|
||||
# Output as JSON
|
||||
stella config list --output json
|
||||
```
|
||||
|
||||
### Show Effective Config
|
||||
|
||||
```bash
|
||||
# Show effective config for a path
|
||||
stella config policy.determinization show
|
||||
|
||||
# Output:
|
||||
# Effective Determinization Config
|
||||
# ─────────────────────────────────
|
||||
# Source: Service (api/v1/policy/config/determinization)
|
||||
#
|
||||
# Reanalysis Triggers:
|
||||
# epssDeltaThreshold: 0.2
|
||||
# triggerOnThresholdCrossing: true
|
||||
# triggerOnRekorEntry: true
|
||||
# triggerOnVexStatusChange: true
|
||||
# triggerOnRuntimeTelemetryChange: true
|
||||
# triggerOnPatchProofAdded: true
|
||||
# triggerOnDsseValidationChange: true
|
||||
# triggerOnToolVersionChange: false
|
||||
#
|
||||
# Conflict Handling:
|
||||
# vexReachabilityContradiction: RequireManualReview
|
||||
# ...
|
||||
|
||||
# Use path alias
|
||||
stella config policy:determinization show
|
||||
|
||||
# Output as JSON
|
||||
stella config policy.determinization show --output json
|
||||
|
||||
# Show from config file (bypass service)
|
||||
stella config policy.determinization show --config /etc/stella/config.yaml
|
||||
```
|
||||
|
||||
### Config Path Normalization
|
||||
|
||||
Path matching is case-insensitive with flexible separators:
|
||||
|
||||
| Input | Normalized | Valid |
|
||||
|-------|------------|-------|
|
||||
| `policy.determinization` | `policy.determinization` | ✓ |
|
||||
| `Policy:Determinization` | `policy.determinization` | ✓ |
|
||||
| `POLICY.DETERMINIZATION` | `policy.determinization` | ✓ |
|
||||
| `policy:determinization` | `policy.determinization` | ✓ |
|
||||
|
||||
### Secret Redaction
|
||||
|
||||
Secrets are automatically redacted in config output:
|
||||
|
||||
```bash
|
||||
stella config database show
|
||||
|
||||
# Output:
|
||||
# database:
|
||||
# host: pg.stella.local
|
||||
# port: 5432
|
||||
# database: stella
|
||||
# username: stella_app
|
||||
# password: ******** # Redacted
|
||||
# connectionString: ******** # Redacted
|
||||
```
|
||||
|
||||
### Popular Config Paths
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `policy.determinization` | Determinization triggers and thresholds |
|
||||
| `policy.confidenceweights` | Evidence confidence weight values |
|
||||
| `scanner` | Core scanner settings |
|
||||
| `attestor.rekor` | Rekor transparency log settings |
|
||||
| `signals.evidenceweightedscore` | EWS calculation settings |
|
||||
| `excititor.mirror` | VEX mirror configuration |
|
||||
| `airgap.bundlesigning` | Offline kit bundle signing |
|
||||
| `signer.keyless` | Sigstore keyless signing |
|
||||
|
||||
See the full config inventory in `docs/implplan/SPRINT_20260112_014_CLI_config_viewer.md`.
|
||||
|
||||
@@ -394,6 +394,9 @@ public sealed record GateResult
|
||||
| **SourceQuotaGate** | Prevent single-source dominance without corroboration | `gates.sourceQuota` |
|
||||
| **ReachabilityRequirementGate** | Require reachability proof for critical CVEs | `gates.reachabilityRequirement` |
|
||||
| **EvidenceFreshnessGate** | Reject stale evidence below freshness threshold | `gates.evidenceFreshness` |
|
||||
| **CvssThresholdGate** | Block findings above CVSS score threshold | `gates.cvssThreshold` |
|
||||
| **SbomPresenceGate** | Require valid SBOM for release artifacts | `gates.sbomPresence` |
|
||||
| **SignatureRequiredGate** | Require signatures on specified evidence types | `gates.signatureRequired` |
|
||||
|
||||
#### MinimumConfidenceGate
|
||||
|
||||
@@ -466,6 +469,112 @@ gates:
|
||||
|
||||
- **Behavior**: Fails when CRITICAL/HIGH CVE marked `not_affected` lacks reachability proof (unless bypass reason applies).
|
||||
|
||||
#### CvssThresholdGate
|
||||
|
||||
> **Sprint:** SPRINT_20260112_017_POLICY_cvss_threshold_gate
|
||||
|
||||
Blocks findings above a configurable CVSS score threshold per environment:
|
||||
|
||||
```yaml
|
||||
gates:
|
||||
cvssThreshold:
|
||||
enabled: true
|
||||
priority: 15
|
||||
defaultThreshold: 7.0
|
||||
thresholds:
|
||||
production: 7.0
|
||||
staging: 8.0
|
||||
development: 9.0
|
||||
cvssVersionPreference: highest # v3.1, v4.0, or highest
|
||||
failOnMissingCvss: false
|
||||
requireAllVersionsPass: false
|
||||
allowlist:
|
||||
- CVE-2024-XXXXX # False positive
|
||||
denylist:
|
||||
- CVE-2024-YYYYY # Always block
|
||||
```
|
||||
|
||||
- **Behavior**: Fails when CVSS base score exceeds environment threshold.
|
||||
- **CVSS Versions**: Supports both CVSS v3.1 and v4.0; preference configurable.
|
||||
- **Allowlist**: CVEs that bypass threshold enforcement.
|
||||
- **Denylist**: CVEs that always fail regardless of score.
|
||||
- **Offline**: Operates without external lookups; uses injected or metadata scores.
|
||||
|
||||
#### SbomPresenceGate
|
||||
|
||||
> **Sprint:** SPRINT_20260112_017_POLICY_sbom_presence_gate
|
||||
|
||||
Requires valid SBOM presence for release artifacts:
|
||||
|
||||
```yaml
|
||||
gates:
|
||||
sbomPresence:
|
||||
enabled: true
|
||||
priority: 5
|
||||
enforcement:
|
||||
production: required
|
||||
staging: required
|
||||
development: optional
|
||||
acceptedFormats:
|
||||
- spdx-2.3
|
||||
- spdx-3.0.1
|
||||
- cyclonedx-1.5
|
||||
- cyclonedx-1.6
|
||||
minimumComponents: 1
|
||||
requireSignature: true
|
||||
schemaValidation: true
|
||||
requirePrimaryComponent: true
|
||||
```
|
||||
|
||||
- **Enforcement Levels**: `required` (fail), `recommended` (warn), `optional` (pass).
|
||||
- **Format Validation**: Validates SBOM format against accepted list; normalizes format names.
|
||||
- **Schema Validation**: Validates SBOM against bundled JSON schemas.
|
||||
- **Signature Requirement**: Optionally requires signed SBOM.
|
||||
- **Minimum Components**: Ensures SBOM has meaningful inventory.
|
||||
|
||||
#### SignatureRequiredGate
|
||||
|
||||
> **Sprint:** SPRINT_20260112_017_POLICY_signature_required_gate
|
||||
|
||||
Requires cryptographic signatures on specified evidence types:
|
||||
|
||||
```yaml
|
||||
gates:
|
||||
signatureRequired:
|
||||
enabled: true
|
||||
priority: 3
|
||||
evidenceTypes:
|
||||
sbom:
|
||||
required: true
|
||||
trustedIssuers:
|
||||
- "*@company.com"
|
||||
- "build-service@ci.example.com"
|
||||
acceptedAlgorithms:
|
||||
- ES256
|
||||
- RS256
|
||||
vex:
|
||||
required: true
|
||||
trustedIssuers:
|
||||
- "*@vendor.com"
|
||||
attestation:
|
||||
required: true
|
||||
enableKeylessVerification: true
|
||||
fulcioRoots: /etc/stella/trust/fulcio-roots.pem
|
||||
requireTransparencyLogInclusion: true
|
||||
environments:
|
||||
development:
|
||||
requiredOverride: false
|
||||
skipEvidenceTypes:
|
||||
- sbom
|
||||
```
|
||||
|
||||
- **Per-Evidence-Type**: Configure requirements per evidence type (SBOM, VEX, attestation).
|
||||
- **Issuer Constraints**: Wildcard support (`*@domain.com`) for email patterns.
|
||||
- **Algorithm Enforcement**: Limit accepted signature algorithms.
|
||||
- **Keyless (Fulcio)**: Support Sigstore keyless signatures with Fulcio certificate verification.
|
||||
- **Transparency Log**: Optionally require Rekor inclusion proof.
|
||||
- **Environment Overrides**: Relax requirements for non-production environments.
|
||||
|
||||
#### Gate Registry
|
||||
|
||||
Gates are registered via DI and evaluated in sequence:
|
||||
@@ -496,6 +605,9 @@ public interface IPolicyGateRegistry
|
||||
| SourceQuotaGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/SourceQuotaGate.cs` |
|
||||
| ReachabilityRequirementGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/ReachabilityRequirementGate.cs` |
|
||||
| EvidenceFreshnessGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/EvidenceFreshnessGate.cs` |
|
||||
| CvssThresholdGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/CvssThresholdGate.cs` |
|
||||
| SbomPresenceGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/SbomPresenceGate.cs` |
|
||||
| SignatureRequiredGate | `src/Policy/__Libraries/StellaOps.Policy/Gates/SignatureRequiredGate.cs` |
|
||||
|
||||
See `etc/policy-gates.yaml.sample` for complete gate configuration options.
|
||||
|
||||
|
||||
@@ -216,3 +216,216 @@ services.AddPolicyEngine(); // Includes determinization
|
||||
---
|
||||
|
||||
*Last updated: 2026-01-07 (Sprint 20260106_001_003)*
|
||||
|
||||
---
|
||||
|
||||
## 10. Unknown Mapping and Grey Queue Semantics
|
||||
|
||||
> **Sprint:** SPRINT_20260112_004_POLICY_unknowns_determinization_greyqueue
|
||||
|
||||
When evidence is incomplete or conflicting, the Determinization Gate produces outcomes that map to the "Grey Queue" for operator review.
|
||||
|
||||
### 10.1 Unknown State Mapping
|
||||
|
||||
The Grey Queue captures observations with uncertain status:
|
||||
|
||||
| Policy Verdict | Observation State | OpenVEX Mapping | Description |
|
||||
|----------------|------------------|-----------------|-------------|
|
||||
| `GuardedPass` | `PendingDeterminization` | `under_investigation` | Allowed with guardrails; monitoring required |
|
||||
| `Deferred` | `PendingDeterminization` | `under_investigation` | Decision deferred; needs additional evidence |
|
||||
| `Escalated` (conflict) | `Disputed` | `under_investigation` | Conflicting evidence; manual adjudication required |
|
||||
|
||||
### 10.2 Reanalysis Fingerprint
|
||||
|
||||
Each unknown is assigned a deterministic fingerprint enabling reproducible replays:
|
||||
|
||||
```json
|
||||
{
|
||||
"fingerprintId": "sha256:abc123...",
|
||||
"dsseBundleDigest": "sha256:def456...",
|
||||
"evidenceDigests": [
|
||||
"sha256:111...",
|
||||
"sha256:222..."
|
||||
],
|
||||
"toolVersions": {
|
||||
"scanner": "2.1.0",
|
||||
"reachability": "1.5.2"
|
||||
},
|
||||
"productVersion": "1.0.0",
|
||||
"policyConfigHash": "sha256:789...",
|
||||
"signalWeightsHash": "sha256:aaa...",
|
||||
"computedAt": "2026-01-15T10:00:00Z",
|
||||
"triggers": [
|
||||
{
|
||||
"type": "epss.updated@1",
|
||||
"receivedAt": "2026-01-15T09:55:00Z",
|
||||
"delta": 0.15
|
||||
}
|
||||
],
|
||||
"nextActions": ["await_vex", "run_reachability"]
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3 Conflict Detection and Routing
|
||||
|
||||
Conflicting evidence automatically routes to `Disputed` state:
|
||||
|
||||
| Conflict Type | Detection | Adjudication Path |
|
||||
|---------------|-----------|-------------------|
|
||||
| `VexReachabilityContradiction` | VEX not_affected + confirmed reachable | Manual review |
|
||||
| `StaticRuntimeContradiction` | Static unreachable + runtime execution | Auto-escalate |
|
||||
| `VexStatusConflict` | Multiple providers with conflicting status | Trust-weighted resolution or manual |
|
||||
| `BackportStatusConflict` | Backport claimed + affected status | Manual review |
|
||||
| `EpssRiskContradiction` | Low EPSS + KEV or high exploitation | Auto-escalate |
|
||||
|
||||
### 10.4 Trigger Events for Reanalysis
|
||||
|
||||
The Grey Queue tracks triggers that caused reanalysis:
|
||||
|
||||
| Event Type | Version | Delta Threshold | Description |
|
||||
|------------|---------|-----------------|-------------|
|
||||
| `epss.updated` | 1 | 0.1 | EPSS score changed significantly |
|
||||
| `vex.updated` | 1 | N/A | VEX statement added/modified |
|
||||
| `reachability.updated` | 1 | N/A | Reachability analysis completed |
|
||||
| `runtime.updated` | 1 | N/A | Runtime observation recorded |
|
||||
| `sbom.updated` | 1 | N/A | SBOM content changed |
|
||||
| `dsse_validation.changed` | 1 | N/A | DSSE validation status changed |
|
||||
| `rekor_entry.added` | 1 | N/A | New Rekor transparency entry |
|
||||
|
||||
### 10.5 Next Actions
|
||||
|
||||
Each unknown suggests next actions for resolution:
|
||||
|
||||
| Action | Description |
|
||||
|--------|-------------|
|
||||
| `await_vex` | Wait for vendor VEX statement |
|
||||
| `run_reachability` | Execute reachability analysis |
|
||||
| `enable_runtime` | Deploy runtime telemetry |
|
||||
| `verify_backport` | Confirm backport availability |
|
||||
| `manual_review` | Escalate to security team |
|
||||
| `trust_resolution` | Resolve issuer trust conflict |
|
||||
|
||||
---
|
||||
|
||||
## 11. Related Documentation
|
||||
|
||||
- [Determinization Library](./determinization-architecture.md) - Core determinization models
|
||||
- [Policy Engine Architecture](./architecture.md) - Overall policy engine design
|
||||
- [Signal Snapshot Models](../../api/signals/reachability-contract.md) - Signal data structures
|
||||
- [VEX Consensus Guide](../../VEX_CONSENSUS_GUIDE.md) - VEX correlation and consensus
|
||||
|
||||
---
|
||||
|
||||
## 12. Determinization Configuration
|
||||
|
||||
> **Sprint:** SPRINT_20260112_012_POLICY_determinization_reanalysis_config
|
||||
|
||||
The Determinization Gate uses persisted configuration for reanalysis triggers, conflict handling, and per-environment thresholds.
|
||||
|
||||
### 12.1 Configuration Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"reanalysisTriggers": {
|
||||
"epssDeltaThreshold": 0.2,
|
||||
"triggerOnThresholdCrossing": true,
|
||||
"triggerOnRekorEntry": true,
|
||||
"triggerOnVexStatusChange": true,
|
||||
"triggerOnRuntimeTelemetryChange": true,
|
||||
"triggerOnPatchProofAdded": true,
|
||||
"triggerOnDsseValidationChange": true,
|
||||
"triggerOnToolVersionChange": false
|
||||
},
|
||||
"conflictHandling": {
|
||||
"vexReachabilityContradiction": "RequireManualReview",
|
||||
"staticRuntimeContradiction": "RequireManualReview",
|
||||
"vexStatusConflict": "RequestVendorClarification",
|
||||
"backportStatusConflict": "RequireManualReview",
|
||||
"escalationSeverityThreshold": 0.85,
|
||||
"conflictTtlHours": 48
|
||||
},
|
||||
"environmentThresholds": {
|
||||
"production": {
|
||||
"minConfidence": 0.75,
|
||||
"maxEntropy": 0.3,
|
||||
"epssThreshold": 0.3,
|
||||
"requireReachability": true
|
||||
},
|
||||
"staging": {
|
||||
"minConfidence": 0.60,
|
||||
"maxEntropy": 0.5,
|
||||
"epssThreshold": 0.4,
|
||||
"requireReachability": true
|
||||
},
|
||||
"development": {
|
||||
"minConfidence": 0.40,
|
||||
"maxEntropy": 0.7,
|
||||
"epssThreshold": 0.6,
|
||||
"requireReachability": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 12.2 Reanalysis Trigger Defaults
|
||||
|
||||
| Trigger | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `epssDeltaThreshold` | 0.2 | Minimum EPSS delta to trigger reanalysis |
|
||||
| `triggerOnThresholdCrossing` | true | Trigger when EPSS crosses a bucket threshold |
|
||||
| `triggerOnRekorEntry` | true | Trigger on new Rekor transparency entry |
|
||||
| `triggerOnVexStatusChange` | true | Trigger when VEX status changes |
|
||||
| `triggerOnRuntimeTelemetryChange` | true | Trigger on runtime exploit/reachability signals |
|
||||
| `triggerOnPatchProofAdded` | true | Trigger when binary patch proof is added |
|
||||
| `triggerOnDsseValidationChange` | true | Trigger when DSSE validation state changes |
|
||||
| `triggerOnToolVersionChange` | false | Trigger on tool version updates (disabled by default) |
|
||||
|
||||
### 12.3 Conflict Handling Actions
|
||||
|
||||
| Action | Description |
|
||||
|--------|-------------|
|
||||
| `AutoResolve` | System resolves using trust scores |
|
||||
| `RequireManualReview` | Route to Grey Queue for operator review |
|
||||
| `RequestVendorClarification` | Queue for vendor outreach |
|
||||
| `Escalate` | Escalate to security team |
|
||||
| `Block` | Block until conflict is resolved |
|
||||
|
||||
### 12.4 Environment Threshold Presets
|
||||
|
||||
| Preset | MinConfidence | MaxEntropy | EPSS Threshold |
|
||||
|--------|---------------|------------|----------------|
|
||||
| Relaxed (dev) | 0.40 | 0.7 | 0.6 |
|
||||
| Standard (staging) | 0.60 | 0.5 | 0.4 |
|
||||
| Strict (production) | 0.75 | 0.3 | 0.3 |
|
||||
|
||||
### 12.5 Configuration API
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v1/policy/config/determinization` | GET | Get effective config for tenant |
|
||||
| `/api/v1/policy/config/determinization/defaults` | GET | Get system defaults |
|
||||
| `/api/v1/policy/config/determinization/audit` | GET | Get configuration change history |
|
||||
| `/api/v1/policy/config/determinization` | PUT | Update config (policy-admin required) |
|
||||
| `/api/v1/policy/config/determinization/validate` | POST | Validate config without saving |
|
||||
|
||||
### 12.6 Configuration Binding
|
||||
|
||||
In `appsettings.yaml`:
|
||||
|
||||
```yaml
|
||||
Policy:
|
||||
Determinization:
|
||||
ReanalysisTriggers:
|
||||
EpssDeltaThreshold: 0.2
|
||||
TriggerOnThresholdCrossing: true
|
||||
TriggerOnRekorEntry: true
|
||||
TriggerOnVexStatusChange: true
|
||||
TriggerOnToolVersionChange: false
|
||||
ConflictHandling:
|
||||
VexReachabilityContradiction: RequireManualReview
|
||||
EscalationSeverityThreshold: 0.85
|
||||
EnvironmentThresholds:
|
||||
Production:
|
||||
MinConfidence: 0.75
|
||||
MaxEntropy: 0.3
|
||||
```
|
||||
|
||||
@@ -43,6 +43,58 @@ Findings can have special flags indicating evidence quality:
|
||||
| `proven-path` | Checkmark | Blue | Verified reachability path confirmed |
|
||||
| `vendor-na` | Strikethrough | Gray | Vendor marked as not affected |
|
||||
| `speculative` | Question mark | Orange | Evidence is speculative/unconfirmed |
|
||||
| `anchored` | [A] | Violet | Score anchored with DSSE/Rekor attestation |
|
||||
| `hard-fail` | [!] | Red | Policy hard-fail triggered |
|
||||
|
||||
## Grey Queue Components
|
||||
|
||||
> **Sprint:** SPRINT_20260112_011_FE_policy_unknowns_queue_integration
|
||||
|
||||
The Grey Queue component suite handles observations with uncertain status requiring operator attention.
|
||||
|
||||
### Components
|
||||
|
||||
| Component | Purpose | Location |
|
||||
|-----------|---------|----------|
|
||||
| GreyQueuePanel | Display grey queue item with fingerprint, triggers, conflicts, and actions | `features/unknowns/` |
|
||||
| GreyQueueDashboard | Dashboard view with filtering and deterministic ordering | `features/unknowns/` |
|
||||
| DeterminizationReview | Detailed review context for grey queue items | `features/unknowns/` |
|
||||
|
||||
### Observation States
|
||||
|
||||
| State | Badge Color | Description |
|
||||
|-------|-------------|-------------|
|
||||
| `PendingDeterminization` | Yellow | Evidence incomplete; monitoring active |
|
||||
| `Disputed` | Orange | Conflicting evidence; manual adjudication required |
|
||||
| `GuardedPass` | Blue | Allowed with runtime guardrails |
|
||||
| `Resolved` | Green | Operator has made a determination |
|
||||
|
||||
### Usage
|
||||
|
||||
```typescript
|
||||
// Grey queue components
|
||||
import {
|
||||
GreyQueuePanelComponent,
|
||||
GreyQueueDashboardComponent,
|
||||
DeterminizationReviewComponent,
|
||||
} from '@app/features/unknowns';
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- Grey Queue Panel -->
|
||||
<app-grey-queue-panel
|
||||
[unknown]="policyUnknown"
|
||||
(triageAction)="onTriageAction($event)"
|
||||
/>
|
||||
|
||||
<!-- Grey Queue Dashboard -->
|
||||
<app-grey-queue-dashboard
|
||||
[unknowns]="unknownsList"
|
||||
(selectUnknown)="onSelectUnknown($event)"
|
||||
/>
|
||||
```
|
||||
|
||||
See `docs/UI_GUIDE.md#grey-queue-and-unknowns-triage` for operator workflow documentation.
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
@@ -81,6 +81,23 @@ Filter by active score flags:
|
||||
- Proven Path
|
||||
- Vendor N/A
|
||||
- Speculative
|
||||
- Anchored (DSSE/Rekor attested)
|
||||
- Hard Fail (policy triggered)
|
||||
|
||||
### Row Visual Indicators
|
||||
|
||||
#### Hard Fail Rows
|
||||
Findings with `hard-fail` flag are highlighted with:
|
||||
- Red left border (`3px solid #dc2626`)
|
||||
- Subtle red background tint
|
||||
- CSS class: `hard-fail-row`
|
||||
|
||||
#### Anchored Rows
|
||||
Findings with `anchored` flag display:
|
||||
- Violet left border (`3px solid #7c3aed`)
|
||||
- CSS class: `anchored-row`
|
||||
|
||||
Note: If a finding is both anchored and hard-fail, hard-fail styling takes visual precedence.
|
||||
|
||||
### Search
|
||||
Text search across advisory ID and package name.
|
||||
|
||||
@@ -25,10 +25,12 @@ The `ScoreBadgeComponent` displays evidence quality flags that provide context a
|
||||
|
||||
| Type | Icon | Color | Description |
|
||||
|------|------|-------|-------------|
|
||||
| `live-signal` | Signal wave | Green (`#16A34A`) | Active runtime signals detected from deployed environments |
|
||||
| `live-signal` | Signal wave | Green (`#059669`) | Active runtime signals detected from deployed environments |
|
||||
| `proven-path` | Checkmark | Blue (`#2563EB`) | Verified reachability path to vulnerable code |
|
||||
| `vendor-na` | Strikethrough | Gray (`#6B7280`) | Vendor has marked as not affected |
|
||||
| `speculative` | Question mark | Orange (`#D97706`) | Evidence is speculative or unconfirmed |
|
||||
| `speculative` | Question mark | Orange (`#F97316`) | Evidence is speculative or unconfirmed |
|
||||
| `anchored` | [A] | Violet (`#7C3AED`) | Score is anchored with DSSE attestation and/or Rekor transparency log |
|
||||
| `hard-fail` | [!] | Red (`#DC2626`) | Policy hard-fail triggered - requires immediate remediation |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -45,6 +47,8 @@ The `ScoreBadgeComponent` displays evidence quality flags that provide context a
|
||||
<stella-score-badge type="proven-path" />
|
||||
<stella-score-badge type="vendor-na" />
|
||||
<stella-score-badge type="speculative" />
|
||||
<stella-score-badge type="anchored" />
|
||||
<stella-score-badge type="hard-fail" />
|
||||
```
|
||||
|
||||
### Size Variants
|
||||
@@ -128,6 +132,30 @@ The evidence for this vulnerability is speculative or based on incomplete analys
|
||||
- Heuristic-based detection
|
||||
- Unverified reports
|
||||
|
||||
### anchored (Violet - Attested)
|
||||
The score calculation has been cryptographically anchored via DSSE attestation and/or inclusion in a Rekor transparency log. This provides verifiable proof of the score at a specific point in time.
|
||||
|
||||
**Attestation Types:**
|
||||
- DSSE envelope with signed payload
|
||||
- Rekor log index and entry ID
|
||||
- Offline ledger verification
|
||||
|
||||
**Visual Behavior:**
|
||||
- Subtle violet glow effect via `anchored-glow` CSS class
|
||||
|
||||
### hard-fail (Red - Immediate Action)
|
||||
A policy hard-fail condition has been triggered. This indicates the vulnerability meets criteria for mandatory immediate remediation, bypassing normal triage workflow.
|
||||
|
||||
**Triggers:**
|
||||
- Known Exploited Vulnerability (KEV) list inclusion
|
||||
- Active exploitation confirmed
|
||||
- Critical severity with confirmed reachability
|
||||
- Policy override by security team
|
||||
|
||||
**Visual Behavior:**
|
||||
- Red alert pulse animation via `alert` CSS class
|
||||
- Row highlighting in findings lists
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Uses `role="img"` with descriptive `aria-label`
|
||||
|
||||
@@ -57,6 +57,35 @@ interface EvidenceWeightedScoreResult {
|
||||
};
|
||||
policyDigest: string;
|
||||
calculatedAt: string; // ISO 8601
|
||||
|
||||
// Sprint: SPRINT_20260112_004_FE_attested_score_ui
|
||||
// Reduction profile, hard-fail, and anchor fields
|
||||
reductionProfile?: ReductionProfile;
|
||||
shortCircuitReason?: ShortCircuitReason;
|
||||
hardFailStatus?: HardFailStatus;
|
||||
isHardFail?: boolean;
|
||||
proofAnchor?: ScoreProofAnchor;
|
||||
}
|
||||
|
||||
interface ReductionProfile {
|
||||
mode: 'none' | 'light' | 'standard' | 'aggressive' | 'custom';
|
||||
originalScore: number;
|
||||
reductionAmount: number;
|
||||
reductionFactor: number;
|
||||
contributingEvidence: string[];
|
||||
cappedByPolicy: boolean;
|
||||
}
|
||||
|
||||
interface ScoreProofAnchor {
|
||||
anchored: boolean;
|
||||
dsseDigest?: string;
|
||||
rekorLogIndex?: number;
|
||||
rekorEntryId?: string;
|
||||
rekorLogId?: string;
|
||||
attestationUri?: string;
|
||||
verifiedAt?: string;
|
||||
verificationStatus?: 'verified' | 'pending' | 'failed' | 'offline';
|
||||
verificationError?: string;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -129,22 +158,44 @@ export class ScoreDialogComponent {
|
||||
### 1. Header
|
||||
Displays the overall score with bucket label and color.
|
||||
|
||||
### 2. Dimensions Chart
|
||||
### 2. Hard Fail Alert (Conditional)
|
||||
If `isHardFail` is true, displays a prominent red warning section with the hard-fail reason (KEV, exploited, critical reachable, or policy override).
|
||||
|
||||
### 3. Dimensions Chart
|
||||
Horizontal bar chart showing all six dimensions with their normalized values (0-100%).
|
||||
|
||||
### 3. Flags Section
|
||||
Active flags displayed as badges. See [ScoreBadge](./score-badge.md) for flag types.
|
||||
### 4. Reduction Profile (Conditional)
|
||||
When a reduction profile is present, shows:
|
||||
- Reduction mode (light, standard, aggressive, custom)
|
||||
- Original vs reduced score
|
||||
- Contributing evidence types
|
||||
- Policy cap indicator
|
||||
|
||||
### 4. Guardrails Section
|
||||
### 5. Short-Circuit Info (Conditional)
|
||||
When the score was short-circuited, shows the reason (vendor not affected, VEX not affected, runtime confirmed, anchor verified).
|
||||
|
||||
### 6. Flags Section
|
||||
Active flags displayed as badges. See [ScoreBadge](./score-badge.md) for flag types including:
|
||||
- `anchored` - Cryptographic attestation present
|
||||
- `hard-fail` - Policy hard-fail triggered
|
||||
|
||||
### 7. Guardrails Section
|
||||
Applied caps and floors:
|
||||
- **Speculative Cap**: Score limited due to unconfirmed evidence
|
||||
- **Not Affected Cap**: Score reduced due to vendor VEX
|
||||
- **Runtime Floor**: Score elevated due to active runtime signals
|
||||
|
||||
### 5. Explanations
|
||||
### 8. Proof Anchor Details (Conditional)
|
||||
When anchored, shows attestation details:
|
||||
- DSSE envelope digest (truncated)
|
||||
- Rekor log index and entry ID
|
||||
- Verification status and timestamp
|
||||
- Attestation URI link
|
||||
|
||||
### 9. Explanations
|
||||
Human-readable explanations of factors affecting the score.
|
||||
|
||||
### 6. Footer
|
||||
### 10. Footer
|
||||
- Policy digest (truncated SHA-256)
|
||||
- Calculation timestamp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user