Score Policy YAML Format

This reference describes the YAML format Stella Ops uses to configure deterministic vulnerability scoring. It is written for policy authors and operators who tune how findings are scored. The score policy defines how each factor contributes to the final vulnerability score, ensuring reproducible and auditable results.

For the higher-level model of profiles and signals, see Scoring Profiles and Signals Weighting.

Overview

Scores are computed from a small set of weighted factors. Weights and tuning knobs live in a single YAML document so that scoring is transparent, version-controlled, and replayable.

Schema Version

Current version: score.v1

File Location

By default, score policies are loaded from:

Override via environment variable: STELLAOPS_SCORE_POLICY_PATH

Basic Structure

# Required fields
policyVersion: score.v1
policyId: unique-policy-identifier

# Optional metadata
policyName: "My Organization's Scoring Policy"
description: "Custom scoring weights for our security posture"

# Weight distribution (must sum to 10000 basis points = 100%)
weightsBps:
  baseSeverity: 2500    # 25% - CVSS base score contribution
  reachability: 2500    # 25% - Code reachability analysis
  evidence: 2500        # 25% - KEV, EPSS, exploit evidence
  provenance: 2500      # 25% - Supply chain trust signals

Weight Configuration

Weights are specified in basis points (bps) where 10000 bps = 100%. This avoids floating-point precision issues and ensures weights always sum to exactly 100%.

Example: Reachability-Heavy Profile

policyVersion: score.v1
policyId: reachability-focused

weightsBps:
  baseSeverity: 2000    # 20%
  reachability: 4000    # 40% - Heavy emphasis on reachability
  evidence: 2000        # 20%
  provenance: 2000      # 20%

Example: Evidence-Heavy Profile

policyVersion: score.v1
policyId: evidence-focused

weightsBps:
  baseSeverity: 2000    # 20%
  reachability: 2000    # 20%
  evidence: 4000        # 40% - Heavy emphasis on KEV/EPSS
  provenance: 2000      # 20%

Reachability Configuration

Fine-tune how reachability analysis affects scores:

reachabilityConfig:
  reachableMultiplier: 1.5      # Boost for reachable code paths
  unreachableMultiplier: 0.3    # Reduction for unreachable code
  unknownMultiplier: 1.0        # Default when analysis unavailable

Multiplier Bounds

Evidence Configuration

Configure how exploit evidence affects scoring:

evidenceConfig:
  kevWeight: 1.5          # Boost for KEV-listed vulnerabilities
  epssThreshold: 0.5      # EPSS score threshold for high-risk
  epssWeight: 1.2         # Weight multiplier for high EPSS

KEV Integration

Known Exploited Vulnerabilities (KEV) from CISA are automatically boosted:

EPSS Integration

Exploit Prediction Scoring System (EPSS) provides probability-based risk:

Provenance Configuration

Configure how supply chain trust signals affect scoring:

provenanceConfig:
  signedBonus: 0.1            # 10% reduction for signed artifacts
  rekorVerifiedBonus: 0.2     # 20% reduction for Rekor-verified
  unsignedPenalty: -0.1       # 10% increase for unsigned artifacts

Trust Signals

SignalEffectUse Case
signedBonusScore reductionArtifact has valid signature
rekorVerifiedBonusScore reductionSignature in transparency log
unsignedPenaltyScore increaseNo signature present

Score Overrides

Override scoring for specific CVEs or patterns:

overrides:
  # Exact CVE match
  - id: log4shell-critical
    match:
      cvePattern: "CVE-2021-44228"
    action:
      setScore: 10.0
    reason: "Known critical RCE in production"

  # Pattern match
  - id: log4j-family
    match:
      cvePattern: "CVE-2021-442.*"
    action:
      multiplyScore: 1.2
    reason: "Log4j family vulnerabilities"

  # Severity-based
  - id: low-severity-suppress
    match:
      severityEquals: "LOW"
    action:
      multiplyScore: 0.5
    reason: "Reduce noise from low-severity findings"

  # Combined conditions
  - id: unreachable-medium
    match:
      severityEquals: "MEDIUM"
      reachabilityEquals: "UNREACHABLE"
    action:
      multiplyScore: 0.3
    reason: "Medium + unreachable = low priority"

Override Actions

ActionDescriptionExample
setScoreForce specific scoresetScore: 10.0
multiplyScoreApply multipliermultiplyScore: 0.5
addScoreAdd/subtract valueaddScore: -2.0

Match Conditions

ConditionDescriptionExample
cvePatternRegex match on CVE ID"CVE-2021-.*"
severityEqualsExact severity match"HIGH", "CRITICAL"
reachabilityEqualsReachability state"REACHABLE", "UNREACHABLE", "UNKNOWN"
packagePatternPackage name regex"log4j.*"

Complete Example

policyVersion: score.v1
policyId: production-v2024.12
policyName: "Production Security Policy"
description: |
  Balanced scoring policy with emphasis on exploitability
  and reachability for production workloads.

weightsBps:
  baseSeverity: 2000
  reachability: 3000
  evidence: 3000
  provenance: 2000

reachabilityConfig:
  reachableMultiplier: 1.5
  unreachableMultiplier: 0.4
  unknownMultiplier: 1.0

evidenceConfig:
  kevWeight: 1.5
  epssThreshold: 0.3
  epssWeight: 1.3

provenanceConfig:
  signedBonus: 0.1
  rekorVerifiedBonus: 0.15
  unsignedPenalty: -0.05

overrides:
  - id: critical-rce
    match:
      cvePattern: "CVE-2021-44228|CVE-2022-22965"
    action:
      setScore: 10.0
    reason: "Known critical RCE vulnerabilities"

  - id: unreachable-low
    match:
      severityEquals: "LOW"
      reachabilityEquals: "UNREACHABLE"
    action:
      multiplyScore: 0.2
    reason: "Minimal risk: low severity + unreachable"

Validation

Policies are validated against JSON Schema on load:

  1. Schema validation: Structure and types
  2. Weight sum check: weightsBps must sum to 10000
  3. Range checks: Multipliers within bounds
  4. Override validation: Valid patterns and actions

Programmatic Validation

var validator = new ScorePolicyValidator();
var result = validator.Validate(policy);
if (!result.IsValid)
{
    foreach (var error in result.Errors)
    {
        Console.WriteLine(error);
    }
}

Determinism

For reproducible scoring:

  1. Policy Digest: Each policy has a content-addressed digest
  2. Replay Manifest: Digest is recorded in scan manifests
  3. Audit Trail: Policy version tracked with every scan

Digest Format

sha256:abc123def456...

The digest is computed from canonical JSON serialization of the policy, ensuring identical policies always produce identical digests.

Migration

From Hardcoded Weights

  1. Export current weights to YAML format
  2. Validate with stellaops policy validate score.yaml
  3. Deploy to etc/score-policy.yaml
  4. Restart services to load new policy

Version Upgrades

Future schema versions (e.g., score.v2) will include migration guides and backward compatibility notes.