up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
This commit is contained in:
56
docs/policy/effective-severity.md
Normal file
56
docs/policy/effective-severity.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Effective Severity Selection
|
||||
|
||||
Last updated: 2025-11-25 (Docs Tasks Md.V)
|
||||
|
||||
## Goal
|
||||
Provide a deterministic, explainable way to pick the *effective* severity for a vulnerability or VEX observation when multiple signals exist (CVSS, KEV, exploit intel, VEX status, asset criticality, policy overrides).
|
||||
|
||||
## Inputs
|
||||
- **Base scores**: CVSS v3/v4 (base + temporal) and ecosystem-native severities (npm/yarn, PyPI, Maven). Missing scores are treated as `null`.
|
||||
- **Exploitability**: KEV flag, EPSS probability, in-the-wild sightings, vendor exploit flags.
|
||||
- **VEX status**: `not_affected`, `affected`, `fixed`, `under_investigation`, `unknown` (per OpenVEX/CSAF/CycloneDX-VEX).
|
||||
- **Context signals**: asset criticality, exposure surface (`internet`, `intranet`, `airgap`), runtime enablement flag, workload type.
|
||||
- **Policy overrides**: tenant/org rules (allow lists, waiver ids, force-upgrade requirements, SLA class).
|
||||
|
||||
## Algorithm (deterministic)
|
||||
1) **Normalize** all scores to a 0–10 float with 3-decimal rounding; store provenance for each signal.
|
||||
2) **VEX gate**
|
||||
- `not_affected` → effective severity `None` (score 0). Short-circuit unless override `force_evaluate=true`.
|
||||
- `fixed` → keep score but add mitigation note.
|
||||
3) **Exploit boost**: if `KEV=true` or `EPSS >= 0.7`, set `exploit_boost = +1.0` (cap at 10). Record reason.
|
||||
4) **Exposure clamp**
|
||||
- `airgap` → max score 7.0 unless override `allow_airgap_breakglass`.
|
||||
- `intranet` → no cap; `internet` → no cap.
|
||||
5) **Criticality weight**: multiply by asset criticality weight (default 1.0; high=1.2, medium=1.0, low=0.8). Clamp 0–10.
|
||||
6) **Policy override**: apply explicit tenant rules (force severity, waive to `None`, or constrain max). Overrides always log the applied rule id.
|
||||
7) **Bucket** into severity bands (stable mapping):
|
||||
|
||||
| Score range (inclusive) | Band |
|
||||
| --- | --- |
|
||||
| 9.0–10.0 | Critical |
|
||||
| 7.0–8.9 | High |
|
||||
| 4.0–6.9 | Medium |
|
||||
| 0.1–3.9 | Low |
|
||||
| 0 | None |
|
||||
|
||||
All arithmetic uses `decimal` and rounds only when persisted or returned (3 decimals) to stay replayable.
|
||||
|
||||
## Examples
|
||||
- CVSS 7.5 + KEV + internet + high criticality → base 7.5 → +1.0 exploit → *before clamp* 8.5 → ×1.2 = 10.2 → clamp 10.0 → **Critical**.
|
||||
- CVSS 5.0, `not_affected` VEX → short-circuit to **None** (score 0) with rationale `vex:not_affected`.
|
||||
- No CVSS, EPSS 0.2, exposure `airgap` → default score 0, band **None**; remains deterministic.
|
||||
|
||||
## Observability
|
||||
- Emit `stellaops.policy.effective_severity` histogram (0–10) with tags `tenant`, `source`, `vex_status`, `kev`, `epss_bucket`, `criticality`, `override_id`.
|
||||
- Log structured event `severity.selected` containing input signals, applied steps, final score/band.
|
||||
- Traces: span attribute `severity.score` and `severity.band`; link to upstream ingest span (`traceparent` propagated).
|
||||
|
||||
## Determinism & Offline posture
|
||||
- No live network lookups during evaluation; KEV/EPSS/VEX feeds must be preloaded from frozen bundles.
|
||||
- Sorting of tied severities: break ties by subject id (lexicographic) then source priority (`vex` > `kev` > `cvss` > `ecosystem`).
|
||||
- All timestamps are UTC ISO-8601; caches keyed by `(tenant, subject, advisory)`.
|
||||
|
||||
## Contract for consumers
|
||||
- API and CLI MUST return both the raw inputs and the chosen band/score so auditors can replay decisions.
|
||||
- Downstream UIs should surface the rationale chain (steps 2–6) and any overrides applied.
|
||||
- Waivers must reference the override id that changed the severity.
|
||||
Reference in New Issue
Block a user