AI DevelopmentOpen Source

SkillSpector: Scan AI Agent Skills for Threats Before You Install Them

October 14, 2026
10 min read
Magnifying glass inspecting a stack of sealed packages on a workbench
Share:

Installing an agent skill feels like installing a note. It is closer to installing a package: a SKILL.md that steers your agent, plus scripts that can run on your machine with your credentials. NVIDIA’s SkillSpector, now past 20,000 GitHub stars, is a static scanner built to look inside a skill before you let it in.

This guide covers what it is, its four-step pipeline, the commands as documented, a CI gate and, just as important, where it stops. The one-line version: skillspector scan ./my-skill/. A scan is a filter, not a verdict.

1. What Is SkillSpector?

SkillSpector is a security scanner for AI agent skills: the folders of instructions and scripts that tools like Claude Code, Codex CLI or Gemini CLI load on demand. You point it at a skill (a directory, a single SKILL.md, a zip or a Git URL) and it reports vulnerabilities, malicious patterns and a 0–100 risk score with an install recommendation. The project is published by NVIDIA under Apache-2.0 and written in Python.

⭐

~20.2k

Stars

GitHub API, Oct 14, 2026

📜

Apache-2.0

License

Open source

🏷️

v2.12.0

Latest release

Sep 23, 2026

🐍

Python 3.12+

Stack

CLI + optional MCP server

Read from the GitHub API and the README on 2026-10-14. Stars move daily; the repo was created in March 2026.

The README says it is part of NVIDIA’s Verified Skills pipeline, which scans, evaluates and signs agent skills before publication. That context matters: it was designed as a gate for a publisher’s catalog, and it doubles as a pre-install check for anyone consuming skills.

Why scan skills at all?

The README cites an academic study, “Agent Skills in the Wild” (Liu et al., 2026, arXiv 2601.10338). The researchers collected 42,447 skills, analyzed 31,132 and used their own scanner, not SkillSpector, for the numbers below. Read them as a signal about the ecosystem, not as a measurement of this tool.

26.1%

of analyzed skills had at least one vulnerability

5.2%

showed high-severity patterns pointing to likely malicious intent

2.12x

more likely to be vulnerable when the skill bundles executable scripts

2. How It Works: Four Steps From Input to Verdict

The README describes a two-stage detection pipeline wrapped by an intake step and a scoring step. Nothing in it executes the skill: the trust model states plainly that it never runs what it scans.

📥

1. Intake and inventory

You hand it a directory, a single file, a zip or a Git URL. SkillSpector builds an inventory of the files it can analyze (instructions, scripts, manifests, dependency files). Since v2.12.0 it also accepts selected GitHub subdirectory links and GitHub or GitLab file links.

🔬

2. Stage 1: deterministic static analysis

Fast pattern matching across 11 static analyzers, plus Python AST checks, YARA signatures and taint tracking from sources such as credentials to sinks such as network output. Repeatable, no API key needed. Dependency names and versions are checked against OSV.dev.

🧠

3. Stage 2: optional LLM semantic review

A model compares what a skill claims with what its code does, which helps with description-behavior mismatches and vague triggers. Every deterministic finding stays in the report whether the model confirms it, disputes it or ignores it; confirmed findings can gain an explanation and higher confidence, never lower.

📊

4. Score, verdict and report

Findings are weighted (CRITICAL 50, HIGH 25, MEDIUM 10, LOW 5 points, with a 1.3x multiplier for executable scripts) into a 0–100 score, a severity and an install recommendation. Reports come as terminal, JSON, Markdown or SARIF 2.1.0.

Score-to-verdict mapping (README)

0–20

LOW

SAFE

21–50

MEDIUM

CAUTION

51–80

HIGH

DO_NOT_INSTALL

81–100

CRITICAL

DO_NOT_INSTALL

Mind the wording: SAFE means nothing scored high enough, not that the skill is proven safe. Section 8 comes back to this.

3. What It Checks: 17 Categories of Skill Risk

This is the README’s own taxonomy. Each category has numbered rule IDs (P1, E2, SC4, AST1, TT3…) that show up in reports and baselines, so you can talk about a finding precisely.

Prompt Injection

P1–P5, P9

Instruction override, hidden instructions, exfiltration commands, behavior manipulation, harmful content, whitespace padding.

Anti-Refusal

AR1–AR3

Text that tells the agent to stop refusing, drop disclaimers or treat safety policy as void.

Data Exfiltration

E1–E4

External transmission, environment-variable harvesting, file-system enumeration, context leakage.

Privilege Escalation

PE1–PE3

Excessive permissions, sudo or root execution, credential access.

Supply Chain

SC1–SC10

Unpinned or known-vulnerable dependencies, remote script fetching, obfuscated code, typosquatting, shipped bytecode, concealed executables, dependency source redirection.

Excessive Agency

EA1–EA5

Unrestricted tool access, autonomous decisions, scope creep, unbounded resources, external model or provider selection.

Output Handling

OH1–OH3

Unvalidated output injection, cross-context output, unbounded output.

System Prompt Leakage

P6–P8

Direct leakage, indirect extraction and tool-based exfiltration of system prompts.

Memory Poisoning

MP1–MP3

Persistent context injection, context-window stuffing, memory manipulation.

Tool Misuse

TM1–TM3

Parameter abuse, chaining abuse and unsafe defaults such as disabled TLS verification.

Rogue Agent

RA1–RA2

Self-modification at runtime and session persistence such as cron jobs or startup hooks.

Trigger Abuse

TR1–TR3

Overly broad triggers, shadowing built-in commands or other skills, keyword baiting.

Behavioral AST

AST1–AST9

Dangerous Python calls found by syntax-tree analysis: exec, eval, dynamic import, subprocess, os.system, compile, getattr sinks.

Taint Tracking

TT1–TT5

Data flowing from credentials, files or external input into network output or code execution.

YARA Signatures

YR1–YR4

Malware, webshell, cryptominer and exploit-tool signatures.

MCP Least Privilege

LP1–LP4

Declared permissions that do not match real capabilities: under-declared, wildcard, missing or over-declared.

MCP Tool Poisoning

TP1–TP4

Hidden instructions, Unicode deception, parameter-description injection and description-behavior mismatch.

Pattern-count caveat: the README headline says 71 patterns while NVIDIA’s docs page says 68. The number differs between sources and releases, so read it as roughly 70 rules in 17 categories. The rule IDs in your own report are what matter.

4. Quickstart: Verified Against the README on 2026-10-14

Every command below is copied from the project README as of today (Python 3.12+ per its badge). I am documenting them here, not running them for you: read what an installer does before you execute it, which is the whole point of this article.

Install (uv tool)

uv tool install git+https://github.com/NVIDIA/skillspector.git

Scan a skill

# Scan a local skill directory
skillspector scan ./my-skill/

# Scan a single SKILL.md file
skillspector scan ./SKILL.md

# Scan a Git repository
skillspector scan https://github.com/user/my-skill

# Scan a zip file
skillspector scan ./my-skill.zip

Output formats

# JSON output - machine readable
skillspector scan ./my-skill/ --format json --output report.json

# Markdown output - for documentation
skillspector scan ./my-skill/ --format markdown --output report.md

# SARIF output - for CI/CD integration and IDE tooling
skillspector scan ./my-skill/ --format sarif --output report.sarif

Docker, static-only (build from a checkout of the repo)

docker build -t skillspector .
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm

Read this before you scan private skills

With LLM analysis on, analyzer-eligible file contents are sent to the configured provider, and per the README the default provider is nv_build (NVIDIA’s hosted endpoint). Pass --no-llm to keep contents local. Even with --no-llm, the supply-chain check SC4 sends dependency names and versions (not file contents) to OSV.dev. To switch provider, set SKILLSPECTOR_PROVIDER (documented values include openai, anthropic, bedrock, gemini, ollama, azure_openai and openai_compatible) together with that provider’s API-key variable.

5. Wire It Into CI Before Third-Party Skills Reach Your Agent

The README calls the exit code and the JSON output a stable contract for CI pipelines, install gates and editor integrations. It does not ship a GitHub Actions snippet, so the script below is my own composition of documented flags. I have not run it: test it on a throwaway repository first.

Exit codes of skillspector scan (README)

  • 0Scan completed, risk score ≤ 50 (SAFE or CAUTION) and no enabled strict gate fired.
  • 1Risk score above 50, or a strict gate fired: --fail-on-findings, --fail-on-incomplete or --min-coverage.
  • 2Error: bad input, unreadable source or internal failure.

By default SAFE and CAUTION both exit 0, so a green build does not mean no findings. Gate more strictly with --fail-on-findings (any active finding) and --fail-on-incomplete (partial coverage), or read the recommendation from the JSON report and apply your own policy. The opt-in --fail-on-findings flag arrived in v2.12.0, so check the version you install.

The pre-install workflow I would use

  1. Step 1 — Quarantine: Never drop a third-party skill straight into ~/.claude/skills/. Pull it into a scratch directory or let SkillSpector fetch the Git URL itself.
  2. Step 2 — Scan static-first: Run with --no-llm so nothing leaves your machine. Add the LLM stage only for skills you are allowed to share with a provider.
  3. Step 3 — Read verdict and coverage: Check risk_assessment.recommendation and analysis_completeness.is_complete in the JSON. NVIDIA’s docs say an incomplete scan is not safe to install, whatever the score.
  4. Step 4 — Human review, then project scope: A person reads SKILL.md and every flagged script, then the skill goes into the repo, where later changes show up in a pull request.

Illustrative CI gate (composed from documented flags, not copied from the README)

#!/usr/bin/env bash
# ci/scan-skills.sh - fail the build if a vendored skill is risky or unreadable
set -u

# Pin a release tag so scores do not drift between runs (uv accepts git refs after @)
uv tool install git+https://github.com/NVIDIA/skillspector.git@v2.12.0

mkdir -p reports
status=0
for d in .claude/skills/*/; do
  skillspector scan "$d" --no-llm \
    --fail-on-findings --fail-on-incomplete \
    --format sarif --output "reports/$(basename "$d").sarif" || status=1
done
exit $status

Accept known findings with a baseline

Triaged findings can be suppressed so the score reflects only new issues. The baseline is a YAML file you commit, and every entry needs a reason. Fingerprints stop matching after a scanner upgrade or a content change, broad rules can hide newly malicious content, and the v2.12.0 notes warn that scores and recommendations may shift between versions, so review baselines after upgrading.

skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml

6. Use Cases That Earn Their Keep

Four places where a static skill scanner is worth the setup time.

🧪

Vetting a skill before you install it

Someone shares a skill in a thread or a marketplace listing. Scan the folder or its Git URL, read the report, and only then decide. This is the core job.

🚦

A PR gate for repos that vendor skills

Teams that commit their skills folder get a check on every change: SARIF output for the code-scanning view of your CI, and an exit code that blocks the merge.

📦

Pre-publication checks for skill authors

NVIDIA runs it as the security tier before publishing to its catalog. If you ship skills to other people, run the same scan on your own work before you tag a release.

🤖

Let the agent ask first (MCP)

With the optional MCP extra, an agent can call the scanner as a tool before installing something. The HTTP transport has no authentication, so bind it to loopback only.

MCP extra (verified commands, README 2026-10-14)

uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
claude mcp add skillspector -- skillspector mcp

7. Where It Fits: Scanner Before, Sandbox During

The README is explicit that SkillSpector is defense-in-depth, not a sandbox: it never executes the skill, and it does not contain a skill you install anyway. Those are two different controls answering two different questions.

Static scanner (SkillSpector)

  • • Question: what is inside this skill?
  • • When: before install and on every change
  • • Strength: cheap, repeatable, catches known-bad patterns
  • • Blind spot: anything that only appears at runtime

Runtime containment (sandbox, permissions)

  • • Question: what can this skill do if it misbehaves?
  • • When: on every execution
  • • Strength: limits blast radius even for unknown tricks
  • • Blind spot: says nothing about what the skill contains

A layered setup that costs an afternoon

  1. 1. Scan every new or updated skill in CI (static-first, strict gates).
  2. 2. Install at project scope so changes show up in code review.
  3. 3. Give the agent least-privilege tool permissions and keep production credentials out of its environment.
  4. 4. Run skills that bundle scripts inside a container or VM with no ambient secrets and restricted network egress.
  5. 5. Keep logs of what the agent executed, so a miss becomes an investigation instead of a mystery.

8. When Not to Rely on It: The False Sense of Safety

A clean report is the most dangerous output this tool can produce, because it feels like permission. The README’s Limitations section is short and worth taking literally.

🌍

Non-English content

The README says it may miss patterns written in other languages. A hostile instruction in a language the rules do not cover is a known gap.

🖼️

Images

It cannot analyze text embedded in images, so instructions hidden in a screenshot or diagram are out of reach.

🔐

Encrypted or binary code

Compiled or encrypted content cannot be inspected, which is exactly where someone hiding a payload would go.

⏱️

Runtime behavior

Static analysis only, no dynamic execution. Whatever a skill downloads or decides at runtime is invisible to a static pass.

Also remember

  • • An incomplete scan is not a clean scan. Size limits, unsupported encodings or timeouts can leave part of a skill unread; NVIDIA’s docs say to treat is_complete: false as not safe to install.
  • • Exit code 0 includes CAUTION. Without strict gates, a CI check can be green while findings exist.
  • • The semantic layer can vary between runs. The baseline docs recommend --no-llm for repeatable acceptance.
  • • A signature is not verification: a root-level OpenSSF Model Signing file is recognized, but the README says the signature itself is not verified.
  • • Baselines can hide a new problem when a rule is too broad. Keep them narrow and review them.

✅ Good fit when...

  • • You consume third-party skills or MCP servers
  • • You vendor skills in git and want a PR gate
  • • You publish skills and want a pre-release check
  • • You need machine-readable output (JSON, SARIF) for policy

⚠️ Not a replacement for...

  • • A sandbox or least-privilege permissions
  • • Reading the skill yourself, especially scripts/
  • • Trust in the publisher: provenance, signing, review
  • • Content in languages or formats it cannot read

Golden rule

Treat DO_NOT_INSTALL as a stop sign and SAFE as “no known-bad pattern found”. The decision to install is still a human one.

Conclusion

SkillSpector earns its stars by doing one unglamorous job well: turning “is this skill sketchy?” from a gut feeling into a repeatable check with rule IDs, a score and an exit code. For anyone installing skills from strangers, which in 2026 is most of us, that is worth ten minutes to set up.

Use it as the first filter, not the last. Scan static-first, gate on completeness, install at project scope and keep a sandbox under anything that runs code. If your agents already pull skills from everywhere and nobody owns that audit, that is the kind of gap I close in project-rescue work.

Diego Rodriguez

Diego Rodriguez

Senior Full-Stack & AI Engineer

Diego has 10+ years of experience building production-grade AI-powered applications, from LLM orchestration and RAG pipelines to ML-driven risk detection and algorithmic trading systems.

Learn more about Diego →