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:

  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:

Required Properties

PropertyTypeDescription
idstringStable identifier (slug or URN)
versionstringSemVer version (e.g., 1.0.0)
signalsarraySignal definitions (min 1)
weightsobjectWeight per signal name
overridesobjectSeverity 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

PropertyRequiredTypeDescription
namestringLogical signal key (e.g., reachability, kev, exploit_chain)
sourcestringUpstream provider or calculation origin
typeenumboolean, numeric, or categorical
pathstringJSON Pointer to the signal in the evidence document
transformstringTransform applied before weighting (e.g., log, normalize)
unitstringUnit for numeric signals

Built-in Signal Sources

SourceSignal NamesTypeDescription
cvssbase_score, temporal_score, environmental_scorenumericCVSS v4.0 scores
epssprobability, percentilenumericEPSS v4 exploit prediction
cisakevbooleanKnown Exploited Vulnerabilities
reachabilityreachable, confidence, depthmixedReachability analysis results
vexstatus, justificationcategoricalVEX consensus status
patchavailable, verifiedbooleanPatch availability evidence
runtimeobserved, observation_countmixedRuntime 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:


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:

appsettings.yaml Example

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 predicateswhen clauses must reference valid signal names
  5. Version format — Must be valid SemVer

Validation Errors

CodeDescription
RISK_PROFILE_001Missing required property
RISK_PROFILE_002Invalid weight value
RISK_PROFILE_003Unknown signal in weights
RISK_PROFILE_004Invalid override predicate
RISK_PROFILE_005Version format invalid