# 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: 1. **Signals** — Data sources that contribute to the risk assessment 2. **Weights** — Relative importance of each signal (0.0–1.0) 3. **Overrides** — Rules that modify severity or decisions based on signal combinations 4. **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: ```json { "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. ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```bash stella policy profiles list --format table ``` ### Show Profile Details ```bash stella policy profiles show --format json ``` ### Validate Profile ```bash stella policy profiles validate profile.json ``` ### Apply Profile ```bash stella policy profiles apply --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 ```yaml policy: riskProfiles: path: /etc/stella/risk-profiles default: stella-default-v1 validation: strict: true allowUnknownSignals: false ``` --- ## Validation Rules 1. **Schema validation** — Profile must conform to `risk-profile-schema@1.json` 2. **Signal consistency** — All signals in `weights` must be defined in `signals` 3. **Weight bounds** — All weights must be in [0.0, 1.0] range 4. **Override predicates** — `when` clauses must reference valid signal names 5. **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 - [Policy Engine Architecture](../architecture.md) - [CVSS v4.0 Integration](../cvss-v4.md) - [Policy Templates](../POLICY_TEMPLATES.md) - [Determinization Architecture](../determinization-architecture.md)