7.4 KiB
Risk Provider Configuration Guide
Module: Policy Engine / RiskProfile
Sprint: SPRINT_20260117_010_CLI_policy_engine (PEN-004)
Last Updated: 2026-01-16
This guide documents the configuration of risk providers within the Stella Ops Policy Engine. Risk providers supply 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 |