Files
git.stella-ops.org/docs/modules/scanner/README.md
2025-12-25 23:10:09 +02:00

308 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# StellaOps Scanner
Scanner analyses container images layer-by-layer, producing deterministic SBOM fragments, diffs, and signed reports.
## Latest updates (2025-12-12)
- Deterministic SBOM composition fixture published at `docs/modules/scanner/fixtures/deterministic-compose/` with DSSE, `_composition.json`, BOM, and hashes; doc `deterministic-sbom-compose.md` promoted to Ready v1.0 with offline verification steps.
- Node analyzer now ingests npm/yarn/pnpm lockfiles, emitting `DeclaredOnly` components with lock provenance. The CLI companion command `stella node lock-validate` runs the collector offline, surfaces declared-only or missing-lock packages, and emits telemetry via `stellaops.cli.node.lock_validate.count`. See `docs/modules/scanner/analyzers-node.md` and bench scenario `node_detection_gaps_fixture`.
- Python analyzer picks up `requirements*.txt`, `Pipfile.lock`, and `poetry.lock`, tagging installed distributions with lock provenance and generating declared-only components for policy. Use `stella python lock-validate` to run the same checks locally before images are built.
- Java analyzer now parses `gradle.lockfile`, `gradle/dependency-locks/**/*.lockfile`, and `pom.xml` dependencies via the new `JavaLockFileCollector`, merging lock metadata onto jar evidence and emitting declared-only components when jars are absent. The new CLI verb `stella java lock-validate` reuses that collector offline (table/JSON output) and records `stellaops.cli.java.lock_validate.count{outcome}` for observability.
- Worker/WebService now resolve cache roots and feature flags via `StellaOps.Scanner.Surface.Env`; misconfiguration warnings are documented in `docs/modules/scanner/design/surface-env.md` and surfaced through startup validation.
- Platform events rollout (2025-10-19) continues to publish scanner.report.ready@1 and scanner.scan.completed@1 envelopes with embedded DSSE payloads (see docs/updates/2025-10-19-scanner-policy.md and docs/updates/2025-10-19-platform-events.md). Service and consumer tests should round-trip the canonical samples under docs/events/samples/.
- OS/non-language analyzers: evidence is rootfs-relative, warnings are structured/capped, hashing is bounded, and Linux OS analyzers support surface-cache reuse. See `os-analyzers-evidence.md`.
## Responsibilities
- Expose APIs (WebService) for scan orchestration, diffing, and artifact retrieval.
- Run Worker analyzers for OS, language, and native ecosystems with restart-only plug-ins.
- Store SBOM fragments and artifacts in RustFS/object storage.
- Publish DSSE-ready metadata for Signer/Attestor and downstream policy evaluation.
## Key components
- `StellaOps.Scanner.WebService` minimal API host.
- `StellaOps.Scanner.Worker` analyzer executor.
- Analyzer libraries under `StellaOps.Scanner.Analyzers.*`.
## Integrations & dependencies
- Scheduler for job intake and retries.
- Policy Engine for evidence handoff.
- Export Center / Offline Kit for artifact packaging.
## Operational notes
- CAS caches, bounded retries, DSSE integration.
- Monitoring dashboards (see ./operations/analyzers-grafana-dashboard.json).
- RustFS migration playbook.
## Related resources
- ./operations/analyzers.md
- ./operations/analyzers-grafana-dashboard.json
- ./operations/rustfs-migration.md
- ./operations/entrypoint.md
- ./analyzers-node.md
- ./analyzers-go.md
- ./operations/secret-leak-detection.md
- ./operations/dsse-rekor-operator-guide.md
- ./os-analyzers-evidence.md
- ./design/macos-analyzer.md
- ./design/windows-analyzer.md
- ../benchmarks/scanner/deep-dives/macos.md
- ../benchmarks/scanner/deep-dives/windows.md
- ../benchmarks/scanner/windows-macos-demand.md
- ../benchmarks/scanner/windows-macos-interview-template.md
- ./operations/field-engagement.md
- ./design/README.md
## Backlog references
- DOCS-SCANNER updates tracked in ../../TASKS.md.
- Analyzer parity work in src/Scanner/**/TASKS.md.
## Implementation Status
### Phase 1 Control plane & job queue (Complete)
- Scanner WebService with queue abstraction (Valkey/NATS)
- Job leasing with retries and dead-letter handling
- CAS layer cache and artifact catalog
- REST API endpoints for scan management
### Phase 2 Analyzer parity & SBOM assembly (In Progress)
- OS analyzers: apk/dpkg/rpm with deterministic metadata
- Language analyzers: Java, Node, Python, Go, .NET, Rust with lock file support
- Native analyzers: ELF/PE/MachO for binary analysis
- SBOM views: inventory/usage with CycloneDX/SPDX emitters
- Entry trace resolution and dependency analysis
### Phase 3 Diff & attestations (In Progress)
- Three-way diff engine (base, target, runtime)
- DSSE SBOM/report signing pipeline
- Attestation hand-off to Signer/Attestor
- Metadata for Export Center integration
### Phase 4 Integrations & exports (Planned)
- Policy Engine integration for evaluation
- Vuln Explorer metadata delivery
- Export Center artifact packaging
- CLI/Console workflows and buildx plugin
### Phase 5 Observability & resilience (Planned)
- Metrics: queue depth, scan latency, cache hit/miss, analyzer timing
- Queue backpressure handling and cache eviction
- SLO dashboards and alerting
- Smoke tests and runbooks
### Key Acceptance Criteria
- Scans produce deterministic SBOM inventory/usage with stable component identity
- Queue/worker pipeline handles retries, backpressure, offline kits
- DSSE attestations exported for Signer/Attestor without transformation
- CLI/Console parity for scan submission, diffing, exports, verification
- Offline scanning supported with local caches and manifest verification
### Technical Decisions & Risks
- Analyzer drift prevented via golden fixtures, hash-based regression tests, deterministic sorting
- Queue overload mitigated with adaptive backpressure, worker scaling, priority lanes
- Storage growth managed via CAS dedupe, ILM policies, offline bundle pruning
- Lock file integration (npm/yarn/pnpm, pip/poetry, gradle) with declared-only components
- Surface cache reuse for Linux OS analyzers with rootfs-relative evidence
### Recent Enhancements (2025-12-12)
- Deterministic SBOM composition with DSSE fixtures and offline verification
- Node/Python/Java lock file collectors with CLI validation commands
- Platform events rollout with scanner.report.ready@1 and scanner.scan.completed@1
- Surface-cache environment resolution with startup validation
## Gating Explainability (Quiet-by-Design Triage)
The Scanner WebService exposes gating explainability through the triage APIs to support the "Quiet-by-Design" UX pattern where noise is gated at the source and proof is surfaced with one click.
### Gating Reasons
Findings can be hidden by default based on:
| Gating Reason | Description |
|---------------|-------------|
| `unreachable` | Not reachable from any application entrypoint |
| `policy_dismissed` | Waived or tolerated by policy rules |
| `backported` | Patched via distro backport |
| `vex_not_affected` | VEX statement declares not affected with sufficient trust |
| `superseded` | Superseded by newer advisory |
| `user_muted` | Explicitly muted by user |
### Key DTOs
- `FindingTriageStatusDto` - Extended with `GatingReason`, `IsHiddenByDefault`, `SubgraphId`, `DeltasId`, `GatingExplanation`
- `TriageVexStatusDto` - Includes `TrustScore`, `PolicyTrustThreshold`, `MeetsPolicyThreshold`, `TrustBreakdown`
- `GatedBucketsSummaryDto` - Counts of hidden findings by gating reason for chip display
- `BulkTriageQueryResponseDto` - Includes `GatedBuckets` and `ActionableCount`
### VEX Trust Scoring
VEX statements are evaluated against a policy-defined trust threshold (default 0.8). The trust score is computed from:
- **Authority** (0-1): Issuer reputation and category
- **Accuracy** (0-1): Historical correctness
- **Timeliness** (0-1): Response speed
- **Verification** (0-1): Signature validity
When `TrustScore >= PolicyTrustThreshold`, the VEX not_affected claim gates the finding.
### Unified Evidence Endpoint
`GET /v1/triage/findings/{findingId}/evidence` returns all evidence tabs in one call:
- SBOM reference and component metadata
- Reachability subgraph with call paths
- VEX claims with trust scores
- Attestation summaries
- Delta comparison
- Policy evaluation results
- Manifest hashes for verification
- Replay command for deterministic reproduction
### Evidence Bundle Export
`GET /v1/triage/findings/{findingId}/evidence/export` returns a downloadable archive containing:
- `MANIFEST.json` - Bundle manifest with hashes
- `finding-status.json` - Triage status
- `proof-bundle.json` - Proof bundle
- `replay-command.json` - Replay command info
- `replay.sh` / `replay.ps1` - Replay scripts
- `README.md` - Human-readable documentation
### Replay Command Generation
The `IReplayCommandService` generates copy-ready CLI commands:
```bash
stella scan replay --artifact sha256:abc... --manifest sha256:def... --feeds sha256:ghi... --policy sha256:jkl...
```
For offline replay: `stella scan replay --offline --artifact ... --verify-inputs`
### UI Wireframes
#### Gated Buckets Summary
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Gated Findings Summary │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌────────────────────────┐ │
│ │ 12 actionable │ (96 hidden) │
│ └────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ +42 │ │ +15 │ │ +8 │ │ +23 │ │
│ │ unreachable │ │ policy │ │ backported │ │ VEX │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ +3 │ │ +5 │ │ [Show all] │ │
│ │ superseded │ │ muted │ └─────────────────┘ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
#### VEX Trust Display
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ VEX Status: not_affected │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Trust Score: ████████░░ 0.85 │
│ Threshold: ──────── 0.80 ✓ Meets policy │
│ │
│ Issuer: vendor.example │
│ Justification: vulnerable_code_not_in_execute_path │
│ │
│ ┌─ Trust Breakdown ─────────────────────────────────────────────────┐ │
│ │ Authority: ██████████░ 0.90 │ │
│ │ Accuracy: ████████░░░ 0.85 │ │
│ │ Timeliness: ████████░░░ 0.80 │ │
│ │ Verification: ████████░░░ 0.85 │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
#### Replay Command Component
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Replay Command │
│ Reproduce this verdict deterministically │
├──────────┬─────────┬─────────────────────────────────────────────────────────┤
│ [Full] │ Short │ Offline │
├──────────┴─────────┴─────────────────────────────────────────────────────────┤
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ $ stella scan replay \ │ │
│ │ --artifact sha256:a1b2c3d4e5f6... \ │ │
│ │ --manifest sha256:def456... \ │ │
│ │ --feeds sha256:feed789... \ │ │
│ │ --policy sha256:policy321... │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ ┌───────────────┐ │
│ │ 📋 Copy │ │
│ └───────────────┘ │
├─────────────────────────────────────────────────────────────────────────────┤
│ 📦 Download Evidence Bundle 12.5 KB · ZIP │
├─────────────────────────────────────────────────────────────────────────────┤
│ Expected verdict hash: sha256:verdict123... │
└─────────────────────────────────────────────────────────────────────────────┘
```
#### Gating Explainer Flow
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Finding: CVE-2024-1234 │
│ lodash@4.17.15 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Status: Hidden by default [Why hidden?] ←─┐ │
│ │ │
│ ┌───────────────┴───────────────────────────┐ │
│ │ Why is this finding hidden? │ │
│ ├───────────────────────────────────────────┤ │
│ │ │ │
│ │ This finding is gated because: │ │
│ │ │ │
│ │ ✓ VEX not_affected (trust: 0.85) │ │
│ │ Vendor issued not_affected statement │ │
│ │ with justification: │ │
│ │ "vulnerable_code_not_in_execute_path" │ │
│ │ │ │
│ │ Evidence: │ │
│ │ • VEX document: vex-vendor-2025-001 │ │
│ │ • Issued: 2025-12-15T10:00:00Z │ │
│ │ • Signature: ✓ Valid (ES256) │ │
│ │ │ │
│ │ [View Evidence] [Close] │ │
│ └───────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
#### Evidence Bundle Contents
```
evidence-f-abc123/
├── manifest.json ← Archive manifest with SHA-256 hashes
├── README.md ← Human-readable documentation
├── sbom.cdx.json ← CycloneDX SBOM slice
├── reachability.json ← Reachability analysis
├── vex/
│ ├── vendor.json ← Vendor VEX statement
│ ├── nvd.json ← NVD data
│ └── cisa-kev.json ← CISA KEV flag
├── attestations/
│ ├── sbom.dsse.json ← SBOM DSSE envelope
│ └── scan.dsse.json ← Scan DSSE envelope
├── policy/
│ └── evaluation.json ← Policy evaluation result
├── delta.json ← Delta comparison
├── replay-command.txt ← Copy-ready CLI command
├── replay.sh ← Bash replay script
└── replay.ps1 ← PowerShell replay script
```
See Sprint 9200.0001.0001-0004 for implementation details.
## Epic alignment
- **Epic 6 Vulnerability Explorer:** provide policy-aware scan outputs, explain traces, and findings ledger hooks for triage workflows.
- **Epic 10 Export Center:** generate export-ready artefacts, manifests, and DSSE metadata for bundles.