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

> Discover how SkillSpector calculates its security risk score using severity weighted points and an executable script multiplier. Learn the algorithm and implementation behind assessing skill bundle safety.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: internals
- Published: 2026-06-16

---

**SkillSpector computes security risk scores by aggregating severity-weighted points from findings, applying a 1.3× multiplier when executable scripts are detected, and mapping the result to a 0-100 scale that determines whether a skill bundle is safe to install.**

NVIDIA's SkillSpector analyzes AI skill bundles for security vulnerabilities and generates a quantitative risk assessment to guide installation decisions. Understanding how SkillSpector calculates its risk score helps developers interpret scan results and prioritize remediation efforts. The scoring logic resides 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).

## The Core Scoring Algorithm in `_compute_risk_score`

The risk calculation follows a four-stage pipeline implemented in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py). Each stage transforms the raw findings into actionable security guidance.

### Base Point Allocation by Severity

Every finding contributes fixed points based on its severity level. The algorithm iterates through the findings list (lines 81-92) and accumulates:

- **CRITICAL**: +50 points
- **HIGH**: +25 points  
- **MEDIUM**: +10 points
- **LOW**: +5 points

### Executable Script Multiplier

If the scanned bundle contains executable scripts (`has_executable_scripts == True`), the subtotal receives a **1.3× multiplier** (lines 93-95). The result is rounded down to the nearest integer and clamped to the range **0-100** to ensure the score remains within bounds.

### Severity Band Classification

The numeric score maps to a severity label using the ordered list `_RISK_SEVERITY_BANDS` (lines 96-100):

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

### Recommendation Mapping

Each severity band translates to a human-readable recommendation via `_RISK_RECOMMENDATION` (lines 55-60 and 101):

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

The function returns a tuple `(score, severity_band, recommendation)` that the report node injects into the final output.

## Practical Implementation Examples

You can interact with the scoring system programmatically or via the CLI.

### Programmatic Usage

Import `_compute_risk_score` directly to calculate risk for custom finding sets:

```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 Usage

The command-line interface performs the same calculation internally when scanning skill bundles:

```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"

#   },

#   …

# }

```

## Key Files in the Risk Calculation Pipeline

Several modules collaborate 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`, the severity bands list, and the recommendation mapping dictionary.
- **[`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py)**: Defines the `Finding` dataclass whose `severity` field feeds the scoring algorithm.
- **[`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py)**: Stores the `has_executable_scripts` boolean and the computed risk fields for downstream processing.
- **[`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py)**: Invokes the report node, which calls `_compute_risk_score` and renders results to JSON, Markdown, or terminal output.

## Summary

- **SkillSpector risk score calculation** begins with fixed point values: 50 for CRITICAL, 25 for HIGH, 10 for MEDIUM, and 5 for LOW severity findings.
- An **executable script multiplier of 1.3×** increases the risk when bundled code can execute directly, with results clamped to a 0-100 range.
- The final score maps to severity bands (CRITICAL ≥81, HIGH ≥51, MEDIUM ≥21, LOW <21) that trigger specific installation recommendations.
- The `_compute_risk_score` helper in [`src/skillspector/nodes/report.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/nodes/report.py) returns a tuple containing the numeric score, severity label, and action recommendation.

## Frequently Asked Questions

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

The risk score is explicitly clamped to a maximum of **100** regardless of how many findings are present or whether the executable script multiplier is applied. This normalization ensures consistent severity band mapping across all scanned bundles.

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

When `has_executable_scripts` is `True`, the base point total is multiplied by **1.3** and rounded down to the nearest integer. For example, a subtotal of 45 points becomes 58 points after multiplication, potentially pushing the bundle into a higher severity band.

### Where does SkillSpector store the calculated risk assessment?

The computed values persist in the application state managed by [`src/skillspector/state.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/state.py), which tracks `has_executable_scripts` and the resulting `risk_*` fields. The report node later retrieves these values to generate the final "risk_assessment" section in JSON or Markdown outputs.

### What recommendation does SkillSpector give for CRITICAL severity findings?

Any bundle scoring **81 or higher** (CRITICAL band) receives the `DO_NOT_INSTALL` recommendation, as do HIGH severity bundles (scores 51-80). Only LOW severity bundles (<21 points) receive the `SAFE` recommendation, while MEDIUM bundles (21-50) trigger `CAUTION`.