SkillSpector
CLI ToolNVIDIA/SkillSpector
Security scanner to detect vulnerabilities and malicious patterns in AI agent skills.
Overview
SkillSpector analyzes AI agent skills for vulnerabilities, malicious patterns, and security risks. It supports multiple input formats (Git repos, URLs, files) and provides risk scoring with detailed reports in various formats. It also offers optional LLM-based semantic analysis for enhanced detection.
README Preview
# SkillSpector\n\n**Security scanner for AI agent skills.** Detect vulnerabilities, malicious patterns, and security risks before installing agent skills.\n\n[](https://www.python.org/downloads/)\n[](https://www.apache.org/licenses/LICENSE-2.0)\n\n## Overview\n\nAI agent skills (used by Claude Code, Codex CLI, Gemini CLI, etc.) execute with implicit trust and minimal vetting. Research shows that **26.1% of skills contain vulnerabilities** and **5.2% show likely malicious intent**.\n\nSkillSpector helps you answer: **"Is this skill safe to install?"**\n\n## Documentation\n\n- **[Development guide](docs/DEVELOPMENT.md)** — Architecture, package layout, and how to extend the analyzer pipeline.\n\n## Features\n\n- **Multi-format input**: Scan Git repos, URLs, zip files, directories, or single files\n- **64 vulnerability patterns** across 16 categories: prompt injection, data exfiltration, privilege escalation, supply chain, excessive agency, output handling, system prompt leakage, memory poisoning, tool misuse, rogue agent, trigger abuse, dangerous code (AST), taint tracking, YARA signatures, MCP least privilege, and MCP tool poisoning\n- **Two-stage analysis**: Fast static analysis + optional LLM semantic evaluation\n- **Live vulnerability lookups**: SC4 queries [OSV.dev](https://osv.dev) for real-time CVE data with automatic offline fallback\n- **Multiple output formats**: Terminal, JSON, Markdown, and SARIF reports\n- **Risk scoring**: 0-100 score with severity labels and clear recommendations\n\n## Quick Start\n\n### Installation\n\nCreate and activate a virtual environment first (all `make` targets assume the venv is active). Use **uv** or **pip**; the Makefile uses `uv` if available, otherwise `pip`.\n\n```bash\n# Clone the repository\ngit clone https://github.com/NVIDIA/skillspector.git\ncd skillspector\n\n# Create and activate virtual environment\nuv venv .venv && source .venv/bin/activate\n# or: python3 -m venv .venv && source .venv/bin/activate\n\n# Install fo
FAQ (5)
TroubleshootingHow do I fix SkillSpector TP4 (`mcp_tool_poisoning`) LLM batches running serially and causing scan timeouts?
Upgrade to a SkillSpector build containing PR #731, merged to main on 2026-10-06. The fix changes _check_tp4 in src/skillspector/nodes/analyzers/mcp_tool_poisoning.py from:
batch_outcome = analyzer.run_batches_detailed(batches)
to:
batch_outcome = run_async(analyzer.arun_batches_detailed(batches))
This uses the same shared concurrent runner as the semantic analyzers and meta-review. Set the concurrency limit, for example:
export SKILLSPECTOR_MAX_LLM_CONCURRENCY=4
A value of 1 still forces serial execution. Results remain in batch order, so TP4_MAX_FINDINGS and ledger projection behave unchanged. In testing, TP4 dropped from about 270s to 75s and the full scan from 320s to 206s. If you cannot upgrade immediately, increase SKILLSPECTOR_MAX_WORKFLOW_SECONDS or reduce the number of code chunks as a temporary workaround.
TroubleshootingHow do I make SkillSpector fail when a custom YARA rule fails to compile instead of returning SAFE?
This affects SkillSpector 2.11.2 at commit 9749372. It is fixed by PR #557, so upgrade to a main build or release containing that PR.
After the upgrade, an invalid .yar file produces a WARNING with its path and reason, static_yara is reported as degraded/partial, and --fail-on-incomplete exits non-zero instead of returning SAFE.
If you cannot upgrade immediately, validate every custom rule before scanning:
for f in rules/*.yar; do
python -c "import sys,pathlib,yara; p=pathlib.Path(sys.argv[1]); p.read_text(encoding='utf-8'); yara.compile(filepath=str(p))" "$f" || exit 1
done
This checks both UTF-8 decoding and YARA compilation. Remove a UTF-8 BOM with:
sed -i '1s/^\xEF\xBB\xBF//' rules/acme.yar
Convert a Windows-1252 rule to UTF-8 with:
iconv -f WINDOWS-1252 -t UTF-8 rules/acme.yar -o rules/acme.yar.utf8 \
&& mv rules/acme.yar.utf8 rules/acme.yar
On affected versions, run with SKILLSPECTOR_LOG_LEVEL=DEBUG to see skipped-rule messages, but do not rely on the exit code because the scan still completes successfully.
TroubleshootingHow do I fix a SkillSpector ransomware_behavior false positive on Bitcoin funding documentation containing “Send BTC”?
The false positive occurred because the ransomware_behavior YARA rule matched generic payment prose with its nocase send\s+.*btc ransom-note pattern and used any of them, so no encryption or ransom demand was required. It was fixed in PR #608 (commit a0d489e6, merged 2026-10-08, Jira SKILLSPECT-232): the rule now requires ransom-specific context around Bitcoin payment wording and filters clause-opening payment advice while retaining encryption, rename, overwrite, and threat indicators. Update SkillSpector to a release containing commit a0d489e6, then rerun the ClawHub/SkillSpector audit. If you cannot update immediately, temporarily reword funding instructions to avoid the generic send ... BTC pattern, for example “Fund the account using Bitcoin,” and rescan.
TroubleshootingWhy does `skillspector --help` show missing API key warnings and run slowly?
This happens when skillspector.graph executes graph = create_graph() at module import time, causing the CLI to build and initialize all analyzers even for --help or --version. Upgrade to a release containing PR #436, which replaces eager graph construction with a lazy, thread-safe graph proxy. The graph is compiled only on the first real graph.invoke() or graph.ainvoke() call, while the existing API remains unchanged. After upgrading, clear the provider credentials and verify with time skillspector --help: help should render immediately without missing-key warnings. Missing-credential warnings will still appear when an actual scan initializes unavailable analyzers.
TroubleshootingHow do I fix SkillSpector treating .ZIP or .ZiP archives as ordinary files instead of extracting them?
This happens because InputHandler.resolve(), _download_file(), and _download_transitive_file() use case-sensitive .endswith(".zip") checks. Update SkillSpector to a build containing merged PR #727, which recognizes ZIP extensions case-insensitively. If updating is not possible, rename the archive to use a lowercase extension:
mv skill.ZIP skill.zip
mv skill.ZiP skill.zip
For downloaded files served with application/octet-stream, ensure the URL or saved filename ends in lowercase .zip. A source-level workaround is to change the checks to filename.lower().endswith(".zip") in all three methods.