NVIDIA SkillSpector 64 Vulnerability Patterns: Complete Catalog with Severity Levels
SkillSpector defines 64 static-analysis rule IDs mapped to four severity levels (CRITICAL, HIGH, MEDIUM, LOW) based on the Severity enum in skillspector/models.py, with each pattern implemented in specific analyzer modules under src/skillspector/nodes/analyzers/.
NVIDIA's SkillSpector is an open-source security framework that uses static analysis to detect vulnerabilities in AI agent implementations and supply chain dependencies. The tool catalogs exactly 64 vulnerability patterns—each assigned a default severity—that drive risk scores in the final SARIF reports. These patterns are organized into functional categories ranging from excessive agency detection to supply chain security, with severity levels derived from the core Severity enum and verified through comprehensive unit tests.
How Severity Levels Are Defined in SkillSpector
The severity system centers on the Severity enum defined in src/skillspector/models.py. This enum provides four distinct levels: CRITICAL, HIGH, MEDIUM, and LOW. When analyzer modules detect a vulnerability, they instantiate a Finding object that includes the severity= parameter, which directly references these enum values.
For supply chain vulnerabilities detected via the OSV database (Open Source Vulnerabilities), severity is dynamically determined by CVSS scores. The logic in static_patterns_supply_chain.py maps CVSS scores to SkillSpector severities: scores ≥ 9.0 yield CRITICAL, 7.0–8.9 yield HIGH, 4.0–6.9 yield MEDIUM, and scores below 4.0 yield LOW.
Complete List of 64 Vulnerability Patterns by Category
The 64 patterns are distributed across twelve analyzer modules, each targeting specific attack vectors. The following tables list every pattern ID, its description, and its default severity.
Excessive Agency Patterns (EA1–EA4)
Implemented in static_patterns_excessive_agency.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| EA1 | Excessive tool wildcard | MEDIUM |
| EA2 | Unsafe "auto-approve" flags | MEDIUM |
| EA3 | Scope-creep wording | LOW |
| EA4 | Infinite-retry / no-rate-limit | MEDIUM |
Output Handling Patterns (OH1–OH3)
Implemented in static_patterns_output_handling.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| OH1 | Direct code execution (exec, eval, subprocess.run) |
HIGH |
| OH2 | Prompt-injection via output | HIGH |
| OH3 | Unrestricted output (no length limit) | HIGH |
System Prompt Leakage Patterns (P6–P8)
Implemented in static_patterns_system_prompt_leakage.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| P6 | Disclosing system prompt | HIGH |
| P7 | Prompt-leakage via "help" wording | HIGH |
| P8 | Prompt-leakage via external write | HIGH |
Memory Poisoning Patterns (MP1–MP3)
Implemented in static_patterns_memory_poisoning.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| MP1 | Persistent memory instructions (remember forever) | HIGH |
| MP2 | Repetitive filler / padding | MEDIUM |
| MP3 | Malicious memory poisoning (instruction override) | HIGH |
Tool Misuse Patterns (TM1–TM3)
Implemented in static_patterns_tool_misuse.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| TM1 | Tool-parameter abuse (rm -rf /, chmod 777, git push --force, curl –insecure) |
HIGH (unless whitelisted) |
| TM2 | Command-chaining abuse (&& rm -rf, ; curl … | sh) |
HIGH |
| TM3 | Unsafe defaults (e.g., verify = False, CORS = "*") |
HIGH |
Rogue Agent Patterns (RA1–RA2)
Implemented in static_patterns_rogue_agent.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| RA1 | Rogue-agent self-modifying code (open(__file__), path.write_text) |
HIGH |
| RA2 | Persistence / privilege-escalation instructions (cron, systemd, registry) | HIGH |
Supply Chain Security Patterns (SC2–SC23)
Implemented in static_patterns_supply_chain.py. This category contains 22 patterns covering script downloads, dependency vulnerabilities, and typosquatting:
| Pattern ID | Description | Default Severity |
|---|---|---|
| SC2 | Trusted-source script download (e.g., curl https://astral.sh/uv/install.sh) |
LOW |
| SC3 | Trusted-source, low-confidence download | LOW |
| SC4 | Vulnerable dependency discovered via OSV (e.g., Jinja2 XSS) | HIGH or CRITICAL |
| SC5 | Abandoned / unmaintained package (PyPI or npm) | HIGH |
| SC6 | Typosquat of a popular package name | HIGH |
| SC7 | Supply-chain safe pattern (non-malicious curl … | bash) |
LOW |
| SC8 | npm package with known CVE (via OSV) | CRITICAL |
| SC9 | PyPI package with known CVE (via OSV) | CRITICAL |
| SC10 | Dependency version out-of-date (no CVE) | MEDIUM |
| SC11 | Non-dependency file ignored (no finding) | — |
| SC12 | Unmaintained package with no CVE | HIGH |
| SC13 | Typosquat with high similarity (> 80%) | HIGH |
| SC14 | Typosquat with low similarity (ignored) | — |
| SC15 | Trusted-source script with high confidence (e.g., curl https://brew.sh/install.sh) |
LOW |
| SC16 | Untrusted domain script download | HIGH |
| SC17 | Supply-chain safe pattern for pip install (get-pip.py) |
LOW |
| SC18 | Supply-chain safe pattern for npm install (npm install) |
LOW |
| SC19 | Supply-chain safe pattern for Dockerfile apt cleanup | LOW |
| SC20 | Supply-chain safe pattern for Dockerfile user-setup | LOW |
| SC21 | Supply-chain safe pattern for Dockerfile chown | LOW |
| SC22 | Supply-chain safe pattern for non-Dockerfile rm-rf | HIGH |
| SC23 | Supply-chain safe pattern for generic script download | HIGH |
Trigger Word Patterns (TR1–TR5)
Implemented in static_patterns_supply_chain.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| TR1 | Overly-broad trigger word (e.g., "the") | LOW |
| TR2 | Shadow-builtin command trigger (e.g., "help") | LOW |
| TR3 | Keyword baiting trigger (e.g., "anything") | LOW |
| TR4 | Future-proof placeholder | LOW |
| TR5 | Future-proof placeholder | LOW |
Legacy Security Patterns (P1–P5, E1–E2, PE3)
Implemented in static_patterns.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| P1 | Deprecated "python-2" pattern (legacy) | MEDIUM |
| P2 | Insecure exec-style usage (legacy) |
HIGH |
| P3 | Hard-coded credentials (legacy) | CRITICAL |
| P4 | Insecure command construction (legacy) | HIGH |
| P5 | Unsafe file-write pattern (legacy) | MEDIUM |
| E1 | Environment-variable leakage (legacy) | HIGH |
| E2 | Exposed secret via logs (legacy) | HIGH |
| PE3 | Poor encryption usage (legacy) | CRITICAL |
Tool Poisoning Patterns (TP1–TP4)
Implemented in static_patterns_tool_poisoning.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| TP1 | Zero-width char injection (tool-poisoning) | HIGH |
| TP2 | Base64-encoded payload (tool-poisoning) | HIGH |
| TP3 | Data-URI script injection (tool-poisoning) | HIGH |
| TP4 | Mixed-confidence script injection (tool-poisoning) | MEDIUM or HIGH |
Least Privilege Patterns (LP1–LP4)
Implemented in static_patterns_least_privilege.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| LP1 | Least-privilege under-declared permission | HIGH |
| LP2 | Least-privilege safe pattern | LOW |
| LP3 | Least-privilege moderate pattern | MEDIUM |
| LP4 | Least-privilege low-risk pattern | LOW |
Model Information Patterns (ML1–ML3)
Implemented in model_info.py:
| Pattern ID | Description | Default Severity |
|---|---|---|
| ML1 | Model-info mismatch (LLM provider) | HIGH |
| ML2 | Model-info low-risk discrepancy | MEDIUM |
| ML3 | Model-info safe discrepancy | LOW |
How Severity Is Assigned in the Source Code
When analyzers detect a vulnerability, they construct a Finding object by passing the severity directly from the Severity enum. For example, in static_patterns_output_handling.py, the OH1 pattern for direct code execution is flagged with HIGH severity:
# Example from static_patterns_output_handling.py
if re.search(r'\b(exec|eval|subprocess\.run)\b', content):
findings.append(
Finding(
rule_id="OH1",
message="Potential code execution via exec/eval/subprocess.run",
severity=Severity.HIGH,
confidence=0.95,
matched_text=matched,
)
)
This pattern is repeated across all analyzer modules, with each module importing Severity from skillspector/models.py and assigning the appropriate level based on the potential impact of the vulnerability.
Verification Through Unit Tests
The severity mapping for all 64 patterns is immutable and verified through unit tests in tests/unit/test_patterns_new.py and tests/unit/test_patterns.py. These tests assert that every generated Finding matches its expected severity level, ensuring that any code modification that alters severity assignments will cause immediate test failures. This guarantees that the severity catalog remains synchronized with the source code implementation.
Summary
- SkillSpector defines 64 vulnerability patterns across twelve analyzer modules, each targeting specific security risks in AI agents and dependencies.
- Four severity levels (CRITICAL, HIGH, MEDIUM, LOW) are defined in
skillspector/models.pyand assigned based on potential impact or CVSS scores for supply chain vulnerabilities. - Supply chain patterns (SC2–SC23) constitute the largest category with 22 patterns, dynamically mapping OSV CVSS scores to SkillSpector severity levels.
- Legacy patterns (P1–P5, E1–E2, PE3) maintain backward compatibility while still enforcing critical security checks like hard-coded credentials detection.
- Unit test enforcement in
test_patterns_new.pyensures severity assignments remain immutable and accurate across versions.
Frequently Asked Questions
How does SkillSpector determine severity for OSV-based vulnerabilities?
SkillSpector queries the Open Source Vulnerabilities (OSV) database and maps the returned CVSS vector to SkillSpector severity levels. According to the logic in static_patterns_supply_chain.py, CVSS scores ≥ 9.0 map to CRITICAL, scores between 7.0–8.9 map to HIGH, 4.0–6.9 map to MEDIUM, and scores below 4.0 map to LOW.
Can the default severity levels be customized or overridden?
No, the severity mapping is immutable by design. The unit tests in tests/unit/test_patterns_new.py enforce strict assertions that each pattern ID must emit findings with specific severity levels. Any modification to these assignments would cause test failures, ensuring consistent risk scoring across all SkillSpector deployments.
Which patterns are classified as CRITICAL severity?
Only three patterns carry CRITICAL severity: P3 (Hard-coded credentials) and PE3 (Poor encryption usage) from the legacy analyzer, and SC8/SC9 (npm/PyPI packages with known CVEs) when the OSV CVSS score exceeds 9.0. These represent the most severe security risks requiring immediate remediation.
What is the difference between SC2 and SC16 supply chain patterns?
SC2 detects downloads from trusted sources (e.g., curl https://astral.sh/uv/install.sh) and receives LOW severity because the domain is verified. SC16 detects downloads from untrusted domains and receives HIGH severity due to the elevated risk of malicious script injection. Both patterns are evaluated in static_patterns_supply_chain.py using domain reputation heuristics.
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 →