216 lines
9.9 KiB
Markdown
216 lines
9.9 KiB
Markdown
# Signals Module Architecture
|
|
|
|
## Overview
|
|
|
|
The **Signals** module provides a unified evidence-weighted scoring system for vulnerability findings. It aggregates evidence from multiple sources (reachability analysis, runtime observations, backport detection, exploit intelligence, source trust, and mitigations) into a single 0-100 score that enables rapid triage.
|
|
|
|
## Module Purpose
|
|
|
|
- **Unify Scoring:** Combine disparate evidence signals into one actionable score
|
|
- **Enable Triage:** Support sorting, filtering, and prioritization by evidence strength
|
|
- **Maintain Determinism:** Same inputs + policy = same score, always
|
|
- **Provide Transparency:** Decomposable scores with explanations
|
|
|
|
## Location
|
|
|
|
```
|
|
src/Signals/
|
|
├── StellaOps.Signals/
|
|
│ └── EvidenceWeightedScore/
|
|
│ ├── EvidenceWeightedScoreCalculator.cs
|
|
│ ├── EvidenceWeightedScoreInput.cs
|
|
│ ├── EvidenceWeightedScoreResult.cs
|
|
│ ├── Normalizers/
|
|
│ │ ├── BackportEvidenceNormalizer.cs
|
|
│ │ ├── ExploitLikelihoodNormalizer.cs
|
|
│ │ ├── MitigationNormalizer.cs
|
|
│ │ ├── ReachabilityNormalizer.cs
|
|
│ │ ├── RuntimeSignalNormalizer.cs
|
|
│ │ └── SourceTrustNormalizer.cs
|
|
│ ├── Guardrails/
|
|
│ │ └── ScoreGuardrails.cs
|
|
│ └── Policy/
|
|
│ ├── EvidenceWeightPolicy.cs
|
|
│ └── EvidenceWeightPolicyProvider.cs
|
|
└── __Tests/
|
|
└── StellaOps.Signals.Tests/
|
|
└── EvidenceWeightedScore/
|
|
```
|
|
|
|
## Core Concepts
|
|
|
|
### Evidence Dimensions
|
|
|
|
| Dimension | Symbol | Description | Source Module |
|
|
|-----------|--------|-------------|---------------|
|
|
| Reachability | RCH | Code path reachability to vulnerable sink | Policy |
|
|
| Runtime | RTS | Live observation strength (eBPF/dyld/ETW) | Policy |
|
|
| Backport | BKP | Patch evidence from distro/changelog/binary | Concelier |
|
|
| Exploit | XPL | Exploit probability (EPSS + KEV) | Scanner, Concelier |
|
|
| Source Trust | SRC | VEX source trustworthiness | Excititor |
|
|
| Mitigations | MIT | Active protective controls | Policy |
|
|
|
|
### Scoring Formula
|
|
|
|
```
|
|
Score = clamp01(W_rch*RCH + W_rts*RTS + W_bkp*BKP + W_xpl*XPL + W_src*SRC - W_mit*MIT) * 100
|
|
```
|
|
|
|
Note: MIT is **subtractive** — mitigations reduce risk.
|
|
|
|
### Guardrails
|
|
|
|
Hard caps and floors based on evidence conditions:
|
|
|
|
1. **Not-Affected Cap:** If vendor says not-affected (BKP=1) and no runtime contradiction (RTS<0.6), cap at 15
|
|
2. **Runtime Floor:** If strong live signal (RTS>=0.8), floor at 60
|
|
3. **Speculative Cap:** If no reachability and no runtime (RCH=0, RTS=0), cap at 45
|
|
|
|
### Score Buckets
|
|
|
|
| Bucket | Range | Meaning |
|
|
|--------|-------|---------|
|
|
| ActNow | 90-100 | Strong evidence of exploitable risk; immediate action |
|
|
| ScheduleNext | 70-89 | Likely real; schedule for next sprint |
|
|
| Investigate | 40-69 | Moderate evidence; investigate when touching component |
|
|
| Watchlist | 0-39 | Low/insufficient evidence; monitor |
|
|
|
|
## Architecture
|
|
|
|
### Component Diagram
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Signals Module │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────────┐ ┌──────────────────────────────────┐ │
|
|
│ │ NormalizerAggr. │───▶│ EvidenceWeightedScoreCalculator │ │
|
|
│ └────────┬────────┘ └──────────────┬───────────────────┘ │
|
|
│ │ │ │
|
|
│ ▼ ▼ │
|
|
│ ┌─────────────────┐ ┌──────────────────────────────────┐ │
|
|
│ │ Normalizers │ │ ScoreGuardrails │ │
|
|
│ │ ┌─────┐ ┌─────┐ │ └──────────────────────────────────┘ │
|
|
│ │ │ BKP │ │ XPL │ │ │
|
|
│ │ └─────┘ └─────┘ │ ┌──────────────────────────────────┐ │
|
|
│ │ ┌─────┐ ┌─────┐ │ │ EvidenceWeightPolicyProvider │ │
|
|
│ │ │ MIT │ │ RCH │ │ └──────────────────────────────────┘ │
|
|
│ │ └─────┘ └─────┘ │ │
|
|
│ │ ┌─────┐ ┌─────┐ │ │
|
|
│ │ │ RTS │ │ SRC │ │ │
|
|
│ │ └─────┘ └─────┘ │ │
|
|
│ └─────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────────────┐ ┌───────────────────────────────────────┐
|
|
│ External Modules │ │ Consumers │
|
|
│ │ │ │
|
|
│ • Policy (RCH, RTS) │ │ • Policy Engine (verdict enrichment) │
|
|
│ • Concelier (BKP) │ │ • Findings API (score endpoints) │
|
|
│ • Scanner (XPL) │ │ • Web UI (score components) │
|
|
│ • Excititor (SRC) │ │ │
|
|
└─────────────────────┘ └───────────────────────────────────────┘
|
|
```
|
|
|
|
### Data Flow
|
|
|
|
1. **Finding arrives** for scoring
|
|
2. **NormalizerAggregator** collects evidence from source modules
|
|
3. **Individual normalizers** convert raw evidence to 0-1 values
|
|
4. **EvidenceWeightedScoreCalculator** applies formula
|
|
5. **ScoreGuardrails** apply caps/floors
|
|
6. **Result** returned with score, bucket, breakdown, explanations
|
|
|
|
### Policy Configuration
|
|
|
|
Weight policies are loaded from YAML and can vary by:
|
|
- **Tenant:** Different organizations may prioritize differently
|
|
- **Environment:** Production may weight runtime higher than dev
|
|
- **Policy version:** Changes are versioned for reproducibility
|
|
|
|
```yaml
|
|
version: "ews.v1"
|
|
profile: production
|
|
|
|
weights:
|
|
rch: 0.30
|
|
rts: 0.25
|
|
bkp: 0.15
|
|
xpl: 0.15
|
|
src: 0.10
|
|
mit: 0.10
|
|
|
|
guardrails:
|
|
not_affected_cap:
|
|
enabled: true
|
|
max_score: 15
|
|
runtime_floor:
|
|
enabled: true
|
|
min_score: 60
|
|
speculative_cap:
|
|
enabled: true
|
|
max_score: 45
|
|
```
|
|
|
|
## Integration Points
|
|
|
|
### Inbound (Evidence Sources)
|
|
|
|
| Source | Data | Interface |
|
|
|--------|------|-----------|
|
|
| Policy/ConfidenceCalculator | ReachabilityEvidence, RuntimeEvidence | Direct type reference |
|
|
| Concelier/BackportProofService | ProofBlob | Direct type reference |
|
|
| Scanner/EpssPriorityCalculator | EPSS score, percentile | Direct type reference |
|
|
| Concelier/VendorRiskSignalExtractor | KEV status | Direct type reference |
|
|
| Excititor/TrustVector | Trust vector components | Direct type reference |
|
|
| Policy/GateMultipliers | Active mitigations | Direct type reference |
|
|
|
|
### Outbound (Consumers)
|
|
|
|
| Consumer | Usage |
|
|
|----------|-------|
|
|
| Policy Engine | Verdict enrichment, score-based rules |
|
|
| Findings API | Score endpoints (calculate, get, history) |
|
|
| Web UI | Score display components |
|
|
| Webhooks | Score change notifications |
|
|
| Attestor | Scoring proofs in attestations |
|
|
|
|
## Determinism
|
|
|
|
The Signals module maintains strict determinism:
|
|
|
|
1. **Same inputs + same policy = same score:** No randomness, no time-dependent factors in formula
|
|
2. **Policy versioning:** Every policy has a digest; scores include policy digest
|
|
3. **Reproducible proofs:** Scoring proofs can be verified by recalculation
|
|
4. **Stable ordering:** Input order doesn't affect result
|
|
|
|
## Performance
|
|
|
|
| Metric | Target |
|
|
|--------|--------|
|
|
| Single score calculation | <10ms |
|
|
| Batch (100 findings) | <1s |
|
|
| Policy load | <100ms |
|
|
| Cache hit ratio | >80% |
|
|
|
|
## Testing Strategy
|
|
|
|
| Level | Focus | Location |
|
|
|-------|-------|----------|
|
|
| L0 Unit | Calculator, normalizers, guardrails | `*.Tests` |
|
|
| L0 Property | Monotonicity, bounds, determinism | `*.Tests/Properties` |
|
|
| S1 Integration | Cross-module evidence flow | `*.Tests/Integration` |
|
|
| S1 Snapshot | Result JSON structure | `*.Tests/Snapshots` |
|
|
|
|
## Related Documentation
|
|
|
|
- Product Advisory: `docs/product-advisories/24-Dec-2025 - Evidence-Weighted Score Model.md`
|
|
- Sprint Plans: `docs/implplan/SPRINT_8200_0012_*.md`
|
|
- Policy Confidence (deprecated): `docs/modules/policy/confidence-scoring.md`
|
|
- Backport Detection: `docs/modules/concelier/backport-detection.md`
|
|
- EPSS Enrichment: `docs/modules/scanner/epss-enrichment.md`
|
|
- Trust Vector: `docs/modules/excititor/trust-vector.md`
|