Signals Weighting

This guide explains the signals that feed Stella Ops policy decisions and how each one is weighted when a verdict is computed. It is written for policy authors and reviewers who tune scoring behaviour, and for operators who need to understand why a finding scored the way it did.

For the formula and profile-level weights, see Scoring Profiles; for the YAML knobs, see Score Policy YAML; for how signals are referenced inside rules, see the Stella Policy Language (SPL) v1 reference.

What signals are

Signals are the normalised facts the Policy Engine evaluates for every finding. They are derived from SBOM inventory, advisories (Concelier), VEX claims (Excititor), reachability graphs and runtime telemetry, trust/entropy analysis, and operator metadata. Every signal is content-addressed so that a verdict can be replayed deterministically with no network access.

The normalised signals dictionary is:

SignalSPL accessorMeaning
Trust scoresignals.trust_scoreConfidence in the upstream source/provenance (0.0–1.0).
Reachability statesignals.reachability.statereachable, unreachable, or unknown.
Reachability scoresignals.reachability.scoreStrength of the reachability evidence (0.0–1.0).
Entropy penaltysignals.entropy_penaltyPenalty for noisy/low-quality inputs (0.0–1.0).
Uncertainty levelsignals.uncertainty.levelMagnitude of missing or conflicting data.
Runtime hitssignals.runtime_hitsObserved runtime executions of the affected code.

Missing fields evaluate to unknown/null. Rules must handle the unknown case explicitly rather than assuming a default — see SPL data namespaces.

How signals are weighted

Scoring profiles combine four weighted factors into a single risk score. The weights are expressed in basis points (bps), where 10000 bps = 100%, so they always sum to exactly 100% and avoid floating-point drift:

riskScore = (wB × B + wR × R + wE × E + wP × P) / 10000
FactorSignals it draws onDefault weight
Base severity (B)CVSS base score1000 bps (10%)
Reachability (R)reachability.state, reachability.score, runtime_hits4500 bps (45%)
Evidence (E)KEV/EPSS, advisory and VEX evidence, freshness3000 bps (30%)
Provenance (P)trust_score, signing/attestation level1500 bps (15%)

These are the defaults for the Simple profile. The Advanced profile adds CVSS-version adjustment, a KEV boost, an uncertainty penalty driven by uncertainty.level, and semantic-category multipliers. See Scoring Profiles for the full breakdown.

Configurable knobs

Signal behaviour is tuned through the score policy YAML. The most common knobs are:

See Score Policy YAML for the complete schema, bounds, and worked examples.

Weighting in SPL rules

Beyond the score formula, individual SPL rules can read signals directly to gate or escalate a verdict. Two representative patterns:

rule reachability_gate priority 20 {
  when signals.reachability.state == "reachable" and signals.reachability.score >= 0.6
  then status := "affected"
  because "Runtime/graph evidence shows reachable code path";
}

rule trust_entropy_penalty priority 30 {
  when signals.trust_score < 0.4 or signals.entropy_penalty > 0.2
  then severity := severity_band("critical")
  because "Low trust score or high entropy";
}

Determinism

Signal weighting is fully deterministic: