# How SkillSpector Calculates Its Security Risk Score: Algorithm and Implementation

> Discover how SkillSpector calculates its security risk score. Learn the algorithm and implementation for accurate risk assessment and informed installation decisions.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: how-to-guide
- Published: 2026-06-24

---

**SkillSpector calculates its security risk score by summing base severity points for each finding, multiplying by 1.3 if executable scripts are detected, clamping the result to 0-100, and mapping the final value to severity bands and installation recommendations.**

The NVIDIA SkillSpector repository implements a deterministic risk scoring algorithm in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py). The private helper `_compute_risk_score` processes security findings from static analysis and produces a numeric score along with actionable severity labels. Understanding this calculation helps developers interpret scan results and prioritize remediation efforts.

## The Four-Step Risk Calculation Algorithm

The `_compute_risk_score` function applies a multi-stage calculation to transform raw findings into a user-facing risk assessment.

### Base Point Values by Severity

Each finding contributes a fixed point value depending on its severity level. In [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py), lines 81-92 iterate through the findings list and accumulate points according to the **v1 rules**:

| Severity | Points Added |
|----------|--------------|
| **CRITICAL** | +50 |
| **HIGH** | +25 |
| **MEDIUM** | +10 |
| **LOW** | +5 |

### Executable Script Multiplier

If the scanned skill bundle contains any executable scripts, the subtotal receives a significant weight increase. When `has_executable_scripts` equals `True` (tracked in [`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)), the algorithm multiplies the base sum by **1.3** at lines 93-95. The result is then clamped to the range **0-100** and converted to an integer.

### Severity Band Mapping

The final numeric score maps to a severity label using the ordered list `_RISK_SEVERITY_BANDS`. The logic at lines 96-100 evaluates thresholds in descending order:

- **CRITICAL**: score ≥ 81
- **HIGH**: score ≥ 51
- **MEDIUM**: score ≥ 21
- **LOW**: score < 21

### Recommendation Mapping

Each severity band triggers a specific installation recommendation via the `_RISK_RECOMMENDATION` dictionary defined at lines 55-60 and applied at line 101:

- **LOW**: `SAFE`
- **MEDIUM**: `CAUTION`
- **HIGH** or **CRITICAL**: `DO_NOT_INSTALL`

## Implementation Details in report.py

The core calculation resides in the private function `_compute_risk_score` inside [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py). This function 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 function returns a tuple containing three elements: **`(score, severity_band, recommendation)`**. The `report` node inserts this tuple into the final output under the `"risk_assessment"` section, which appears in JSON, Markdown, and terminal formats.

## Working with the Risk Score: Code Examples

You can invoke the calculation logic directly in Python or observe it through the CLI.

### Direct Python Usage

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

# Example findings

findings = [
    Finding(rule_id="S001", severity="HIGH",   message="Unsafe exec",    file="script.py", start_line=1, end_line=5, confidence=0.9),
    Finding(rule_id="S002", severity="MEDIUM", message="Hard‑coded secret", file="config.yml", start_line=10, end_line=10, confidence=0.8),
]

# Suppose the bundle contains executable scripts

has_executable_scripts = True

score, severity, recommendation = _compute_risk_score(findings, has_executable_scripts)

print(f"Score: {score}")           # → 78 ( (25+10) * 1.3 = 45.5 → int(45) → capped at 100, then severity band HIGH)

print(f"Severity: {severity}")    # → HIGH

print(f"Recommendation: {recommendation}")  # → DO_NOT_INSTALL

```

### CLI Output

```bash

# Using the CLI (reports the same calculation internally)

skillsppector scan path/to/skill_bundle --output-format json

# The JSON will contain:

# {

#   "risk_assessment": {

#     "score": 78,

#     "severity": "HIGH",

#     "recommendation": "DO_NOT_INSTALL"

#   },

#   …

# }

```

## Related Source Files

Several files cooperate to produce the final risk assessment:

- **[`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py)**: Contains `_compute_risk_score`, severity bands, and recommendation maps.
- **[`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py)**: Defines the `Finding` model whose `severity` field feeds the scoring algorithm.
- **[`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)**: Stores `has_executable_scripts` and the computed `risk_*` fields for downstream nodes.
- **[`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py)**: Calls the `report` node, which invokes `_compute_risk_score` and presents results to the user.

## Summary

- **Base scoring**: CRITICAL findings add 50 points, HIGH add 25, MEDIUM add 10, and LOW add 5.
- **Executable multiplier**: A 1.3x multiplier applies when executable scripts are present, with the final score clamped between 0 and 100.
- **Band mapping**: Scores map to CRITICAL (≥81), HIGH (≥51), MEDIUM (≥21), and LOW (<21) severity bands.
- **Recommendations**: LOW scores recommend SAFE installation, MEDIUM recommends CAUTION, and HIGH/CRITICAL scores trigger DO_NOT_INSTALL.

## Frequently Asked Questions

### How is the SkillSpector risk score calculated?

SkillSpector calculates the risk score by first summing base points for each finding based on severity (CRITICAL=50, HIGH=25, MEDIUM=10, LOW=5). If the bundle contains executable scripts, it multiplies the total by 1.3, clamps the result to 0-100, and maps it to a severity band.

### What is the executable script multiplier in SkillSpector?

The executable script multiplier is a 1.3x weight applied to the base point sum when `has_executable_scripts` is `True`. This adjustment occurs in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) at lines 93-95 to account for the increased risk of executable code.

### Where is the risk score calculation implemented in the SkillSpector repository?

The calculation is implemented in the private helper `_compute_risk_score` within [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py). This function is called by the report node and returns a tuple of `(score, severity_band, recommendation)`.

### What do the severity bands mean in SkillSpector?

The severity bands categorize the numeric score into actionable levels: CRITICAL (≥81), HIGH (≥51), MEDIUM (≥21), and LOW (<21). These bands map to installation recommendations of DO_NOT_INSTALL, DO_NOT_INSTALL, CAUTION, and SAFE respectively.