How SkillSpector Calculates Risk Scores: Algorithm and Implementation
SkillSpector calculates risk scores by summing fixed severity points (CRITICAL=50, HIGH=25, MEDIUM=10, LOW=5), applying a 1.3× multiplier if executable scripts are detected, clamping the result to 0‑100, and mapping the numeric value to severity bands and installation recommendations.
The risk assessment engine in NVIDIA/SkillSpector evaluates skill bundles for security vulnerabilities using a deterministic scoring algorithm. This calculation is performed by the private helper function _compute_risk_score within the report generation node. Understanding this scoring mechanism helps developers interpret scan results and understand why specific installation recommendations are issued.
The Scoring Algorithm in src/skillspector/nodes/report.py
The core logic resides in the _compute_risk_score function (lines 55‑102), which processes a list of findings and produces a numeric score, severity label, and human‑readable recommendation.
Base Point Values by Severity
Each finding contributes fixed points based on its severity level. The function iterates through the findings list (lines 81‑92) and accumulates points according to the v1 rules:
- CRITICAL: +50 points
- HIGH: +25 points
- MEDIUM: +10 points
- LOW: +5 points
This subtotal represents the raw risk value before any multipliers are applied.
Executable Script Multiplier
If the scanned bundle contains executable scripts (has_executable_scripts == True), the subtotal is multiplied by 1.3 (implemented at 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. This multiplier reflects the increased attack surface presented by runnable code.
Severity Band Classification
After calculating the final numeric score, the function maps the value to a severity band using the ordered list _RISK_SEVERITY_BANDS (lines 96‑100):
- ≥ 81: CRITICAL
- ≥ 51: HIGH
- ≥ 21: MEDIUM
- < 21: LOW
These thresholds determine how the numeric score is presented in reports and whether the skill bundle requires immediate attention.
Recommendation Mapping
Each severity band maps to a specific installation recommendation via the _RISK_RECOMMENDATION dictionary (lines 55‑60 and 101):
- LOW →
SAFE - MEDIUM →
CAUTION - HIGH or CRITICAL →
DO_NOT_INSTALL
The function returns a tuple (score, severity_band, recommendation), which the report node inserts into the final output under the risk_assessment section.
Practical Code Examples
You can invoke the scoring logic directly in Python or observe it through the CLI:
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
When using the command‑line interface, the same calculation runs internally:
# Using the CLI (reports the same calculation internally)
skillspector 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 Assessment Pipeline
| File | Role in Risk Score Calculation |
|---|---|
src/skillspector/nodes/report.py |
Contains _compute_risk_score, severity bands _RISK_SEVERITY_BANDS, and recommendation map _RISK_RECOMMENDATION (core logic). |
src/skillspector/models.py |
Defines the Finding model whose severity field feeds the scoring algorithm. |
src/skillspector/state.py |
Stores has_executable_scripts and computed risk_* fields for downstream nodes. |
src/skillspector/cli.py |
Invokes the report node, which calls _compute_risk_score and presents results to the user. |
Summary
- Base scoring: CRITICAL (50), HIGH (25), MEDIUM (10), LOW (5) points are summed per finding.
- Executable multiplier: A 1.3× multiplier applies when
has_executable_scriptsis True, with results clamped to 0‑100. - Band mapping: Scores ≥81 are CRITICAL, ≥51 are HIGH, ≥21 are MEDIUM, and <21 are LOW.
- Recommendations: LOW yields SAFE, MEDIUM yields CAUTION, and HIGH/CRITICAL yield DO_NOT_INSTALL.
- Entry point: The
_compute_risk_scorefunction insrc/skillspector/nodes/report.pyreturns the tuple(score, severity_band, recommendation).
Frequently Asked Questions
What is the maximum possible risk score in SkillSpector?
The maximum score is 100. Even if the calculated base points multiplied by 1.3 exceed 100, the algorithm clamps the value to the 0‑100 range (lines 93‑95 in report.py). This ensures consistent severity band mapping regardless of how many critical vulnerabilities are detected.
How does the executable script multiplier affect the final score?
When has_executable_scripts is True, the base point subtotal is multiplied by 1.3 and rounded down to the nearest integer. For example, a bundle with 60 base points (two HIGH findings) would score 78 after multiplication (60 × 1.3 = 78). This multiplier is applied before the severity band lookup and can bump a MEDIUM risk into the HIGH category.
Where is the risk score calculation implemented in the codebase?
The calculation is implemented in the private helper function _compute_risk_score located in src/skillspector/nodes/report.py (lines 55‑102). This function is called by the report generation node and is not exposed as a public API, though it can be imported for testing or custom integrations.
What recommendations does SkillSpector provide based on risk scores?
SkillSpector issues three recommendations based on the severity band: SAFE for LOW scores (0‑20), CAUTION for MEDIUM scores (21‑50), and DO_NOT_INSTALL for HIGH (51‑80) and CRITICAL (81‑100) scores. These recommendations appear in JSON, Markdown, and terminal outputs under the risk_assessment.recommendation field.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →