# How the SkillSpector Risk Scoring Algorithm Evaluates Skill Security

> Learn how the SkillSpector risk scoring algorithm elevates security findings, applies multipliers for executable scripts, and maps results to severity bands for installation recommendations.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: deep-dive
- Published: 2026-06-14

---

**The SkillSpector risk scoring algorithm aggregates severity-weighted points from security findings, applies a 1.3× multiplier when executable scripts are detected, clamps the result to a 0–100 range, and maps it to severity bands that determine installation recommendations.**

The NVIDIA SkillSpector risk scoring algorithm transforms raw static analysis findings into actionable security metrics. Located in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py), this deterministic calculation helps security teams quickly assess whether a skill is safe to install based on quantified vulnerability data.

## Step-by-Step Algorithm Breakdown

The core logic resides in the `_compute_risk_score` function, which processes a list of `Finding` objects and returns a tuple containing the numeric score, severity band, and recommendation.

### Severity Point Mapping

Each finding contributes a fixed point value based on its severity level. According to lines 81–92 of [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py), the mapping follows this tiered structure:

- **CRITICAL** → 50 points
- **HIGH** → 25 points  
- **MEDIUM** → 10 points
- **LOW** (or missing) → 5 points

The algorithm sums these values across all findings detected during the scan.

### Executable Script Multiplier

If the scanned skill contains any executable scripts, the algorithm applies a risk multiplier. As implemented in lines 92–94, when `has_executable_scripts` is `True`, the total summed score is multiplied by **1.3** and rounded down to the nearest integer. This reflects the increased deployment risk associated with installable scripts.

### Score Clamping and Normalization

Following the multiplier application, the score is clamped to the range **0–100** (line 94). This normalization ensures that all risk scores fit within a standard percentage scale, preventing extreme values from skewing severity classifications.

### Risk Band Classification

The final numeric score maps to a severity band using explicit thresholds defined in lines 96–100:

- **≥ 81** → **CRITICAL**
- **≥ 51** → **HIGH**  
- **≥ 21** → **MEDIUM**
- **< 21** → **LOW**

These bands translate complex numerical data into intuitive risk categories.

### Recommendation Generation

Each severity band triggers a specific installation recommendation defined in lines 55–61:

- **LOW** → **SAFE**
- **MEDIUM** → **CAUTION**
- **HIGH** or **CRITICAL** → **DO_NOT_INSTALL**

The function returns these three values—score, band, and recommendation—as a tuple attached to the final report output.

## Implementation Details

The `_compute_risk_score` function in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) serves as the private implementation of this algorithm. The function signature accepts a list of `Finding` objects (defined in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py)) and a boolean flag indicating executable script presence.

The `report` node in the same file coordinates this calculation, storing results in `SkillspectorState` (defined in [`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)) for downstream formatting in JSON, Terminal, or Markdown outputs.

## Practical Usage Examples

You can interact with the algorithm directly or through the public API:

```python

# Direct computation using the private function

from skillspector.nodes.report import _compute_risk_score
from skillspector.models import Finding

findings = [
    Finding(rule_id="R1", severity="critical", file="a.py", 
            start_line=1, end_line=5, confidence=0.9, 
            message="Critical issue"),
    Finding(rule_id="R2", severity="high", file="b.py", 
            start_line=10, end_line=12, confidence=0.8, 
            message="High issue"),
    Finding(rule_id="R3", severity="medium", file="c.py", 
            start_line=20, end_line=20, confidence=0.7, 
            message="Medium issue"),
]

# Calculate without executable scripts

score, band, recommendation = _compute_risk_score(
    findings, has_executable_scripts=False
)
print(f"{score} {band} {recommendation}")

# Output: 85 CRITICAL DO_NOT_INSTALL

```

For production use, invoke the public `report` node as the CLI does:

```python
from skillspector.state import SkillspectorState
from skillspector.nodes.report import report

state = SkillspectorState(
    findings=findings,
    component_metadata=[{
        "path": "a.py", 
        "type": "python", 
        "lines": 42, 
        "executable": False
    }],
    has_executable_scripts=False,
    output_format="json",
)

result = report(state)
print(result["risk_score"])          # 85

print(result["risk_severity"])       # CRITICAL

print(result["risk_recommendation"])  # DO_NOT_INSTALL

```

## Summary

- The **SkillSpector risk scoring algorithm** converts finding severities into weighted points (CRITICAL=50, HIGH=25, MEDIUM=10, LOW=5).
- **Executable scripts trigger a 1.3× multiplier**, increasing the calculated risk to reflect deployment dangers.
- Scores are **clamped to 0–100** and mapped to four severity bands that determine installation recommendations.
- The implementation lives in **[`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py)** within the `_compute_risk_score` function, returning a tuple of (score, band, recommendation) used throughout the analysis pipeline.

## Frequently Asked Questions

### How does the executable script multiplier affect the final risk score?

When `has_executable_scripts` is `True`, the algorithm multiplies the summed severity points by 1.3 and rounds down to the nearest integer. For example, a raw score of 50 becomes 65 after multiplication, potentially pushing the skill into a higher risk band.

### What is the maximum possible risk score in SkillSpector?

The algorithm clamps all scores to a maximum of **100** regardless of how many findings are detected or whether the executable multiplier is applied. This 0–100 scale ensures consistent severity classification across all analyzed skills.

### How does the algorithm handle findings with missing severity levels?

According to the implementation in lines 81–92, findings with missing or unrecognized severity values default to **LOW** severity, contributing 5 points to the total score. This conservative approach ensures unspecified issues still add measurable risk.

### Where is the risk score calculation implemented in the codebase?

The core calculation resides in the `_compute_risk_score` function within **[`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py)** (lines 81–100). Supporting data structures are defined in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py) (Finding class) and [`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py) (SkillspectorState), with comprehensive unit tests available in [`tests/nodes/test_report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/tests/nodes/test_report.py).