How SkillSpector's Risk Scoring Algorithm Calculates Severity
SkillSpector calculates severity by assigning fixed point values to each finding based on its severity level (CRITICAL=50, HIGH=25, MEDIUM=10, LOW=5), applying a 1.3x multiplier if the skill contains executable scripts, clamping the result to 0-100, and mapping it against defined thresholds to determine the final risk band and recommendation.
The NVIDIA/SkillSpector repository implements a deterministic risk assessment pipeline that transforms raw security findings into actionable severity scores. At the heart of this system lies the _compute_risk_score function in the Report node, which aggregates individual finding severities into a normalized 0-100 risk score. This score drives the entire reporting workflow, from SARIF outputs to terminal displays.
The Five-Step Calculation Process
The algorithm processes findings through a sequential pipeline that combines additive scoring with conditional multipliers and threshold-based mapping.
Step 1: Assign Base Points by Severity
Each finding contributes a fixed number of points based on its severity annotation. As implemented in src/skillspector/nodes/report.py (lines 82-92), the scoring system uses the following weights:
- CRITICAL → 50 points
- HIGH → 25 points
- MEDIUM → 10 points
- LOW → 5 points
The function iterates through the findings list and accumulates these base values into a running subtotal.
Step 2: Apply the Executable Script Multiplier
If the skill contains any executable scripts (indicated by the boolean flag has_executable_scripts), the subtotal from Step 1 is multiplied by 1.3 and rounded down to the nearest integer. This logic resides in lines 92-94 of src/skillspector/nodes/report.py, reflecting the increased risk profile of skills that can execute arbitrary code.
Step 3: Clamp to Valid Range
Following the multiplier application, the algorithm constrains the result to the interval [0, 100] (lines 94-95). This ensures that even configurations with numerous critical findings or executable scripts cannot exceed the defined maximum score.
Step 4: Map to Risk Severity Bands
The clamped score is compared against ordered thresholds defined in the _RISK_SEVERITY_BANDS constant (lines 54-56). The algorithm selects the first band whose threshold is less than or equal to the calculated score:
- 81+ → CRITICAL
- 51-80 → HIGH
- 21-50 → MEDIUM
- 0-20 → LOW
Step 5: Generate Human-Readable Recommendations
Finally, the severity band maps to a specific action via the _RISK_RECOMMENDATION dictionary (lines 56-60). This translates abstract severity levels into concrete guidance such as "SAFE", "CAUTION", or "DO_NOT_INSTALL".
Implementation in the Codebase
The core logic resides in src/skillspector/nodes/report.py within the _compute_risk_score function. This helper returns a tuple of (score, severity_band, recommendation), which the public report(state) function (lines 63-66) consumes to assemble the final analysis document.
The Finding model defined in src/skillspector/models.py provides the severity field that drives the initial point calculation, ensuring type-safe severity annotations throughout the pipeline.
Practical Example
The following example demonstrates how multiple findings combine into a final risk assessment:
from skillspector.nodes.report import _compute_risk_score
from skillspector.models import Finding
# Example findings with varying severities
findings = [
Finding(rule_id="R1", severity="HIGH"), # +25 points
Finding(rule_id="R2", severity="LOW"), # +5 points
Finding(rule_id="R3", severity="CRITICAL"), # +50 points
]
# Skill contains executable payload
has_executable_scripts = True
score, severity, recommendation = _compute_risk_score(
findings,
has_executable_scripts
)
print(f"Score: {score}") # Output: 100 (104 clamped to 100)
print(f"Severity band: {severity}") # Output: CRITICAL
print(f"Recommendation: {recommendation}") # Output: DO_NOT_INSTALL
In this scenario, the base calculation yields 80 points (25+5+50), which becomes 104 after the 1.3x multiplier (80 × 1.3 = 104). The clamping logic caps this at 100, triggering the CRITICAL severity band (≥81) and corresponding "DO_NOT_INSTALL" recommendation.
Integration with the Reporting Pipeline
The _compute_risk_score function serves as the computational backend for SkillSpector's reporting infrastructure. The public report(state) helper invokes this calculation to populate SARIF output files, JSON/Markdown reports, and terminal color coding. By centralizing severity calculation in a single function, the codebase ensures consistent risk interpretation across all output formats.
Summary
- Base scoring: Fixed points per severity (CRITICAL=50, HIGH=25, MEDIUM=10, LOW=5) in
src/skillspector/nodes/report.pylines 82-92. - Risk multiplier: 1.3x boost for skills with executable scripts, applied at lines 92-94.
- Range enforcement: Scores clamped to [0, 100] regardless of input volume.
- Threshold mapping: Bands defined at 81 (CRITICAL), 51 (HIGH), 21 (MEDIUM), and 0 (LOW).
- Output: Returns a tuple of
(score, severity_band, recommendation)consumed by the reporting pipeline.
Frequently Asked Questions
What is the maximum possible risk score in SkillSpector?
The maximum risk score is 100. Even if the base points plus executable script multiplier calculate to a higher value (e.g., 104), the algorithm clamps the result to the 0-100 range at lines 94-95 of src/skillspector/nodes/report.py.
How does the executable script multiplier affect the final severity?
The multiplier increases the base subtotal by 30% (multiplied by 1.3 and rounded down). This can bump a skill from HIGH to CRITICAL severity if the multiplied score crosses the 81-point threshold. For example, a base score of 70 becomes 91 after multiplication, triggering the CRITICAL band.
Where are the severity thresholds defined?
Thresholds are defined in the _RISK_SEVERITY_BANDS constant at lines 54-56 of src/skillspector/nodes/report.py. The ordered dictionary maps integer thresholds to severity strings: 81→CRITICAL, 51→HIGH, 21→MEDIUM, and 0→LOW.
What recommendation is assigned to a CRITICAL severity rating?
According to the _RISK_RECOMMENDATION mapping at lines 56-60, a CRITICAL severity typically maps to "DO_NOT_INSTALL" or equivalent high-risk warnings. The exact string depends on the static configuration defined in the Report node, but consistently indicates that the skill poses severe security risks.
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 →