How SkillSpector Calculates Its Risk Scoring Algorithm: A Deep Dive into NVIDIA’s Security Scanner
SkillSpector's risk scoring algorithm aggregates security findings by severity, applies a multiplier for executable scripts, and maps the result to a severity band and installation recommendation.
SkillSpector is NVIDIA’s open-source security scanner for AI skill bundles. At the heart of its reporting module lies a deterministic risk scoring algorithm that quantifies security threats into a single 0–100 score. This calculation, implemented in the private helper _compute_risk_score within src/skillspector/nodes/report.py, transforms raw vulnerability findings into actionable installation guidance.
Base Point Values and Severity Weights
The algorithm begins with a simple additive model where each finding contributes fixed points based on its severity level. This "v1 rules" approach ensures consistent scoring regardless of the total number of files scanned.
In src/skillspector/nodes/report.py (lines 81–92), the function iterates over the findings list and accumulates points according to the following scale:
- CRITICAL findings add 50 points
- HIGH severity findings add 25 points
- MEDIUM severity findings add 10 points
- LOW severity findings add 5 points
The Executable Script Multiplier
After calculating the base subtotal, the algorithm checks for executable scripts within the scanned bundle. If the state flag has_executable_scripts evaluates to True, the current subtotal is multiplied by 1.3 and rounded down to the nearest integer.
This multiplier is applied between lines 93–95 in src/skillspector/nodes/report.py. The final result is then clamped to the range 0–100 to ensure the score remains within bounds.
Severity Band Mapping and Installation Recommendations
Mapping Numeric Scores to Labels
The numeric score maps to a human-readable severity band through the ordered list _RISK_SEVERITY_BANDS. The logic at lines 96–100 implements the following thresholds:
- ≥ 81 → CRITICAL
- ≥ 51 → HIGH
- ≥ 21 → MEDIUM
- < 21 → LOW
Installation Recommendations
Each severity band maps to a specific recommendation via the _RISK_RECOMMENDATION dictionary (defined at lines 55–60 and applied at line 101):
- LOW → SAFE
- MEDIUM → CAUTION
- HIGH and CRITICAL → DO_NOT_INSTALL
Source Code Implementation and Usage
The core logic resides in the private function _compute_risk_score inside src/skillspector/nodes/report.py. This helper accepts a list of Finding objects (defined in src/skillspector/models.py) and a boolean flag indicating executable presence.
The function returns a tuple of (score, severity_band, recommendation), which the report node injects into the final output under the risk_assessment section.
Here is a practical example demonstrating the calculation:
from skillspector.nodes.report import _compute_risk_score
from skillspector.models import Finding
# Example findings: one CRITICAL and one MEDIUM
findings = [
Finding(rule_id="S001", severity="CRITICAL", message="Arbitrary code execution",
file="main.py", start_line=1, end_line=5, confidence=0.95),
Finding(rule_id="S002", severity="MEDIUM", message="Hard-coded secret",
file="config.yml", start_line=10, end_line=10, confidence=0.8),
]
# Bundle contains executable scripts, triggering the 1.3x multiplier
has_executable_scripts = True
score, severity, recommendation = _compute_risk_score(findings, has_executable_scripts)
print(f"Score: {score}") # Output: 78 ((50+10)*1.3=78)
print(f"Severity: {severity}") # Output: HIGH
print(f"Recommendation: {recommendation}") # Output: DO_NOT_INSTALL
You can also observe this calculation via the command line interface:
# Using the CLI (performs the same calculation internally)
skillspector scan path/to/skill_bundle --output-format json
# The JSON output includes:
# {
# "risk_assessment": {
# "score": 78,
# "severity": "HIGH",
# "recommendation": "DO_NOT_INSTALL"
# }
# }
Summary
- Base scoring: Fixed points per severity (50/25/10/5) summed in
src/skillspector/nodes/report.pylines 81–92. - Executable multiplier: 1.3x boost when
has_executable_scriptsis True, applied at lines 93–95 with clamping to 0–100. - Severity mapping: Numeric scores translate to CRITICAL (≥81), HIGH (≥51), MEDIUM (≥21), or LOW (<21) bands at lines 96–100.
- Final recommendation: Maps to SAFE, CAUTION, or DO_NOT_INSTALL based on the severity band.
Frequently Asked Questions
What is the maximum possible risk score in SkillSpector?
The algorithm clamps the final score to a maximum of 100. Even if the base points multiplied by 1.3 exceed 100, the result is capped at this ceiling before severity band mapping occurs.
How does the executable script multiplier affect the final recommendation?
The 1.3 multiplier can push a MEDIUM score into HIGH territory, changing the recommendation from CAUTION to DO_NOT_INSTALL. This reflects the increased danger of executable code combined with security findings.
Where does SkillSpector store the risk score during execution?
The computed score, severity band, and recommendation are stored in the application state (defined in src/skillspector/state.py) under the risk_assessment section, making them available to downstream nodes and the final report formatter.
Can I customize the point values or severity thresholds?
Currently, the point values (50/25/10/5) and band thresholds (81/51/21) are hardcoded as v1 rules in src/skillspector/nodes/report.py. To modify them, you would need to edit the source code and adjust the _RISK_SEVERITY_BANDS list and the scoring logic in _compute_risk_score.
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 →