Risk Provider Configuration Guide
Audience: Policy authors and platform engineers configuring how vulnerability findings are scored and prioritised. Scope: Risk profiles in the Stella Ops Policy Engine — signals, weights, overrides, the profile schema, CLI commands, configuration files, and validation rules.
This guide documents how to configure risk providers in the Stella Ops Policy Engine. Risk providers supply the signals (data points) used in risk-scoring calculations.
Overview
Risk profiles define how vulnerability findings are scored and prioritized. Each profile consists of:
- Signals — Data sources that contribute to the risk assessment
- Weights — Relative importance of each signal (0.0–1.0)
- Overrides — Rules that modify severity or decisions based on signal combinations
- Metadata — Optional profile metadata
Risk Profile Schema
Risk profiles follow the risk-profile-schema@1.json schema. The canonical schema is available at:
- Schema URI:
https://stellaops.dev/schemas/risk-profile-schema@1.json - Source:
src/Policy/StellaOps.Policy.RiskProfile/Schemas/risk-profile-schema@1.json
Required Properties
| Property | Type | Description |
|---|---|---|
id | string | Stable identifier (slug or URN) |
version | string | SemVer version (e.g., 1.0.0) |
signals | array | Signal definitions (min 1) |
weights | object | Weight per signal name |
overrides | object | Severity and decision overrides |
Signal Configuration
Each signal definition requires:
{
"name": "kev",
"source": "cisa",
"type": "boolean",
"path": "/evidence/kev/known",
"transform": null,
"unit": null
}
Signal Properties
| Property | Required | Type | Description |
|---|---|---|---|
name | ✅ | string | Logical signal key (e.g., reachability, kev, exploit_chain) |
source | ✅ | string | Upstream provider or calculation origin |
type | ✅ | enum | boolean, numeric, or categorical |
path | string | JSON Pointer to the signal in the evidence document | |
transform | string | Transform applied before weighting (e.g., log, normalize) | |
unit | string | Unit for numeric signals |
Built-in Signal Sources
| Source | Signal Names | Type | Description |
|---|---|---|---|
cvss | base_score, temporal_score, environmental_score | numeric | CVSS v4.0 scores |
epss | probability, percentile | numeric | EPSS v4 exploit prediction |
cisa | kev | boolean | Known Exploited Vulnerabilities |
reachability | reachable, confidence, depth | mixed | Reachability analysis results |
vex | status, justification | categorical | VEX consensus status |
patch | available, verified | boolean | Patch availability evidence |
runtime | observed, observation_count | mixed | Runtime signal correlation |
Weight Configuration
Weights determine the relative importance of each signal in the final risk score. Weights are normalized by the scoring engine.
{
"weights": {
"base_score": 0.3,
"kev": 0.25,
"reachability": 0.25,
"epss_probability": 0.15,
"patch_available": 0.05
}
}
Weight Rules:
- Values must be between 0.0 and 1.0
- Weights are normalized (sum to 1.0) at runtime
- Missing signals receive zero contribution
Override Configuration
Overrides allow conditional severity adjustments and decision actions.
Severity Overrides
{
"overrides": {
"severity": [
{
"when": { "kev": true, "reachable": true },
"set": "critical"
},
{
"when": { "patch_available": true, "reachable": false },
"set": "low"
}
]
}
}
Severity Levels: critical, high, medium, low, informational
Decision Overrides
{
"overrides": {
"decisions": [
{
"when": { "kev": true },
"action": "deny",
"reason": "Active exploitation detected via CISA KEV"
},
{
"when": { "reachable": false, "vex_status": "not_affected" },
"action": "allow",
"reason": "Unreachable and verified not affected"
}
]
}
}
Decision Actions: allow, review, deny
Example Risk Profile
{
"id": "stella-default-v1",
"version": "1.0.0",
"description": "Default risk profile for container vulnerability assessment",
"signals": [
{ "name": "base_score", "source": "cvss", "type": "numeric", "path": "/cvss/baseScore" },
{ "name": "kev", "source": "cisa", "type": "boolean", "path": "/evidence/kev/known" },
{ "name": "epss_probability", "source": "epss", "type": "numeric", "path": "/epss/probability" },
{ "name": "reachable", "source": "reachability", "type": "boolean", "path": "/reachability/reachable" },
{ "name": "reachability_confidence", "source": "reachability", "type": "numeric", "path": "/reachability/confidence" },
{ "name": "patch_available", "source": "patch", "type": "boolean", "path": "/patch/available" },
{ "name": "vex_status", "source": "vex", "type": "categorical", "path": "/vex/status" }
],
"weights": {
"base_score": 0.25,
"kev": 0.20,
"epss_probability": 0.15,
"reachable": 0.20,
"reachability_confidence": 0.10,
"patch_available": 0.05,
"vex_status": 0.05
},
"overrides": {
"severity": [
{ "when": { "kev": true, "reachable": true }, "set": "critical" },
{ "when": { "reachable": false }, "set": "low" }
],
"decisions": [
{ "when": { "kev": true, "reachable": true }, "action": "deny", "reason": "Active exploitation in reachable code" },
{ "when": { "vex_status": "not_affected" }, "action": "allow", "reason": "VEX confirms not affected" }
]
},
"metadata": {
"author": "platform-team",
"compliance": ["SOC2", "ISO27001"]
}
}
CLI Commands
List Risk Profiles
stella policy profiles list --format table
Show Profile Details
stella policy profiles show <profile-id> --format json
Validate Profile
stella policy profiles validate profile.json
Apply Profile
stella policy profiles apply <profile-id> --scope tenant:default
Configuration Files
Risk profiles can be stored as YAML or JSON:
- Default location:
etc/risk-profiles/ - Environment variable:
STELLA_RISK_PROFILES_PATH - Configuration key:
policy:riskProfiles:path
appsettings.yaml Example
policy:
riskProfiles:
path: /etc/stella/risk-profiles
default: stella-default-v1
validation:
strict: true
allowUnknownSignals: false
Validation Rules
- Schema validation — Profile must conform to
risk-profile-schema@1.json - Signal consistency — All signals in
weightsmust be defined insignals - Weight bounds — All weights must be in [0.0, 1.0] range
- Override predicates —
whenclauses must reference valid signal names - Version format — Must be valid SemVer
Validation Errors
| Code | Description |
|---|---|
RISK_PROFILE_001 | Missing required property |
RISK_PROFILE_002 | Invalid weight value |
RISK_PROFILE_003 | Unknown signal in weights |
RISK_PROFILE_004 | Invalid override predicate |
RISK_PROFILE_005 | Version format invalid |
Related Documentation
- Signals Weighting — the signals that feed policy decisions and how each is weighted.
- Scoring Profiles — the built-in profiles and when to use each.
- Effective Severity Selection — how overrides resolve into a final severity.
- CVSS v4.0 Integration — CVSS scoring inputs.
- Policy Engine Architecture — engine internals.
- Policy Templates — starter profiles and packs.
- Determinization Architecture — deterministic scoring guarantees.
