Agent skills run with implicit trust. Claude Code, Codex CLI, and MCP tools execute arbitrary Python, shell commands, and API calls with the same privileges as the host process. NVIDIA scanned 31,132 skills and found 26.1% contain vulnerabilities and 5.2% show likely malicious intent. SkillSpector is the security scanner they built to catch these issues before installation.
The tool is part of NVIDIA’s Verified Skills pipeline, which scans, evaluates, and signs agent skills before publication to their catalog. It runs a two-stage analysis: fast static checks followed by optional LLM semantic evaluation. The scanner detects 71 vulnerability patterns across 17 categories, queries live CVE databases, and enforces fail-closed resource bounds to prevent analysis-time attacks.
The Supply Chain Problem
Agent skills are distributed as Git repos, zip bundles, or single files. Developers install them with minimal vetting. The trust model assumes skills are safe because they come from a GitHub repo or a catalog listing. This is the same supply chain risk that hit npm, PyPI, and Docker Hub, but agent skills have broader execution scope.
A malicious skill can:
- Exfiltrate environment variables, API keys, or file contents
- Inject prompts that override system instructions
- Escalate privileges by calling shell commands
- Poison agent memory to influence future decisions
- Abuse tool permissions (MCP least privilege violations)
- Trigger on specific inputs (time bombs, keyword triggers)
SkillSpector scans for these patterns before the skill touches your runtime.
Two-Stage Analysis Pipeline
The scanner runs static analysis first, then optionally invokes an LLM for semantic evaluation. This balances speed against depth.
Stage 1: Static Analysis
Fast checks that run without network calls or LLM inference:
- AST parsing: Detects dangerous code patterns (eval, exec, subprocess, file writes)
- YARA signatures: Matches known malicious patterns in code and config files
- Taint tracking: Follows user input through the skill to identify injection points
- MCP least privilege: Checks if the skill requests more tool permissions than it uses
- Supply chain (SC4): Queries OSV.dev for CVEs in dependencies, with automatic offline fallback
The static stage produces findings in under 5 seconds for most skills. If the skill is clean or the findings are low-severity, you can stop here.
Stage 2: LLM Semantic Evaluation
Optional deep analysis that requires an LLM API key:
- Prompt injection: Detects attempts to override system instructions or leak prompts
- Data exfiltration: Identifies obfuscated network calls or encoding tricks
- Excessive agency: Flags skills that request permissions beyond their stated purpose
- Memory poisoning: Catches attempts to corrupt agent state or conversation history
- Anti-refusal: Detects jailbreak patterns or refusal suppression
- Rogue agent: Identifies skills that spawn subagents or delegate tasks without disclosure
The LLM stage adds 10-30 seconds depending on skill size and model latency. It catches semantic issues that static analysis misses, like a skill that claims to “format JSON” but also sends data to a remote endpoint.
Fail-Closed Resource Bounds
SkillSpector enforces hard limits to prevent analysis-time attacks. A malicious skill could try to crash the scanner, exhaust memory, or trigger infinite loops. The bounds are:
| Resource | Limit | Behavior on Violation |
|---|---|---|
| Bundle size | 100 MB | Reject before extraction |
| Parser depth | 1000 AST nodes | Truncate and flag |
| Nested artifacts | 10 levels | Stop recursion, flag |
| Finding count | 500 findings | Stop analysis, report overflow |
| Analysis timeout | 5 minutes | Kill process, mark unsafe |
These limits are documented in docs/ANALYSIS_RESOURCE_BOUNDS.md. The scanner fails closed: if a skill exceeds any bound, the scan aborts and the skill is marked unsafe. This prevents zip bombs, parser exploits, and resource exhaustion.
Vulnerability Taxonomy: 71 Patterns Across 17 Categories
The scanner checks for 71 specific patterns grouped into 17 categories. Here are the high-impact categories:
Prompt Injection: Detects skills that try to override system instructions, leak the system prompt, or inject hidden instructions into user messages.
Data Exfiltration: Catches network calls to non-declared endpoints, base64 encoding of sensitive data, and file reads followed by external writes.
Privilege Escalation: Flags shell command execution, file system writes outside the skill directory, and environment variable access.
Supply Chain (SC4): Queries OSV.dev for known CVEs in dependencies. If the network is unavailable, it falls back to a local CVE database snapshot.
MCP Least Privilege: Compares the tool permissions a skill requests against the tools it actually calls. A skill that requests file system access but never uses it gets flagged.
MCP Tool Poisoning: Detects skills that redefine or override existing MCP tools to intercept calls or modify behavior.
Memory Poisoning: Identifies attempts to corrupt agent memory, conversation history, or state files.
Dangerous Code (AST): Static analysis of Python AST for eval, exec, compile, import, subprocess, os.system, and other risky calls.
Taint Tracking: Follows user input through the skill to identify injection points. If user input reaches eval or subprocess without sanitization, it gets flagged.
The full list is in the repository under docs/VULNERABILITY_PATTERNS.md.
Live CVE Lookups with Offline Fallback
The SC4 (supply chain) analyzer queries OSV.dev for real-time CVE data. When you scan a skill, SkillSpector extracts dependency declarations (requirements.txt, package.json, go.mod) and sends them to OSV.dev. The response includes CVE IDs, severity scores, and patched versions.
If the network is unavailable or OSV.dev is down, the scanner falls back to a local CVE database snapshot. The snapshot is updated weekly via GitHub Actions and bundled with the release. This ensures the scanner works in air-gapped environments or CI pipelines without internet access.
The fallback is automatic. You do not configure it. The scanner tries OSV.dev first, then switches to local data if the request times out or fails.
Output Formats and Integration Points
SkillSpector produces four output formats:
- Terminal: Human-readable summary with color-coded severity levels
- JSON: Machine-readable findings for CI/CD pipelines
- Markdown: Report suitable for pull request comments or documentation
- SARIF: Static Analysis Results Interchange Format for GitHub Code Scanning and other SAST tools
The JSON output is the integration point for CI/CD. You can gate skill installation by checking the exit code or parsing the findings array.
import subprocess
import json
result = subprocess.run(
["skillspector", "scan", "skill.zip", "--format", "json"],
capture_output=True,
text=True
)
findings = json.loads(result.stdout)
critical = [f for f in findings if f["severity"] == "critical"]
if critical:
print(f"Blocked: {len(critical)} critical findings")
exit(1)
The SARIF output integrates with GitHub Code Scanning. Upload the SARIF file as a workflow artifact and GitHub will annotate pull requests with findings.
Gating Skill Installation in Production
You have three integration points:
Pre-commit hooks: Scan skills before they enter version control. This catches issues before they reach CI/CD.
CI/CD pipelines: Run SkillSpector as a build step. Fail the build if critical findings are detected.
Runtime interception: Wrap the skill installation command with a scanner check. This is the last line of defense.
NVIDIA uses all three. The Verified Skills pipeline scans every skill submission, signs passing skills with a GPG key, and publishes them to the catalog. Users can verify signatures before installation.
For self-hosted catalogs, you can run SkillSpector as a pre-receive hook in your Git server or as a Lambda function that scans uploaded bundles.
Pi and OpenCode Extensions
SkillSpector ships with extensions for Pi and OpenCode, two agent frameworks. These extensions let you scan skills from inside an agent session.
Pi extension: Install SkillSpector as a Pi tool. The agent can call skillspector.scan(url) to check a skill before installing it.
OpenCode extension: Install SkillSpector as an OpenCode tool. Type /skillspector scan <url> in the chat to trigger a scan.
Both extensions run the full two-stage pipeline and return findings in the chat. This is useful when an agent discovers a new skill and wants to vet it before installation.
The extensions are documented in docs/PI_EXTENSION.md and docs/OPENCODE_EXTENSION.md.
Architecture: Analyzer Registry and Finding Ledger
SkillSpector uses an analyzer registry pattern. Each vulnerability category is implemented as a separate analyzer class. The scanner loads all analyzers at startup and runs them in parallel.
Analyzers produce findings. Each finding has:
- Pattern ID: Unique identifier for the vulnerability pattern
- Severity: Critical, high, medium, low, info
- Location: File path, line number, code snippet
- Description: Human-readable explanation
- Remediation: Suggested fix
Findings are stored in a ledger. The ledger enforces the 500-finding limit. If an analyzer produces more than 500 findings, the ledger stops accepting new findings and flags the overflow.
The ledger is thread-safe. Analyzers run in parallel and write findings concurrently. The ledger uses a lock to prevent race conditions.
When to Use SkillSpector
Use it when:
- You install agent skills from public catalogs or GitHub repos
- You run agents in production with access to sensitive data or APIs
- You maintain a catalog of approved skills for your organization
- You need SARIF output for GitHub Code Scanning or other SAST tools
- You want to enforce least privilege for MCP tools
Avoid it when:
- You only run skills you wrote yourself (but still consider it for supply chain checks)
- You need real-time scanning during skill execution (this is a pre-installation scanner)
- You require formal verification or proof of correctness (this is heuristic-based detection)
The scanner catches known patterns and common mistakes. It does not prove a skill is safe. It reduces risk by filtering out obvious vulnerabilities and malicious code before installation.
Technical Verdict
SkillSpector is a practical tool for a real supply chain problem. The two-stage pipeline balances speed and depth. The fail-closed resource bounds prevent analysis-time attacks. The 71-pattern taxonomy covers the high-impact vulnerability classes. The live CVE lookups with offline fallback make it usable in air-gapped environments.
The scanner is most useful as a CI/CD gate or pre-commit hook. It catches issues before they reach production. The JSON and SARIF outputs integrate cleanly with existing workflows.
The LLM semantic stage is optional but recommended. It catches obfuscated attacks and semantic issues that static analysis misses. Budget 10-30 seconds per skill for the LLM stage.
If you run agents in production or maintain a skill catalog, add SkillSpector to your pipeline. It will not catch every attack, but it will stop the obvious ones.