Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
SkillSpector — Security scanner for AI agent skills. Detect vulnerabilities, malicious patterns, security risks, prompt injection, data exfiltration, and supply-chain risks in Claude Code, Codex, and MCP skills before you install them. | Kitploit
Tools/GitHubGitHub/nvidia/skillspector
Static AnalysisVulnerability ScannersDynamic Analysis (Sandboxing)Code AnalysisPenetration TestingDevSecOpsSecret DetectionThreat IntelligenceSupply Chain SecurityLearning & EducationAI Security
14.5k1.2k222 days agoReviewed by Kitploit
GitHub
nvidia/skillspector

SkillSpector

Security scanner for AI agent skills. Detect vulnerabilities, malicious patterns, security risks, prompt injection, data exfiltration, and supply-chain risks in Claude Code, Codex, and MCP skills before you install them.

View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

SkillSpector

Security scanner for AI agent skills. Detect vulnerabilities, malicious patterns, and security risks before installing agent skills.

Python 3.12+ License: Apache 2.0 OpenSSF Scorecard

Overview

AI 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.

SkillSpector helps you answer: "Is this skill safe to install?"

SkillSpector is part of the NVIDIA Verified Skills pipeline, which scans, evaluates, and signs agent skills before publication. Skills that pass are published to the NVIDIA skills catalog.

Documentation

  • Scan agent skills before installation — Hosted guide: when to scan, how to read a report, and how to gate installs.
  • Development guide — Architecture, package layout, and how to extend the analyzer pipeline.
  • Analysis resource bounds — Fail-closed bundle, parser, nested-artifact, ledger, and finding ceilings.
  • Pi extension — Install SkillSpector as a Pi tool for scanning skills from inside agent sessions.
  • Features

    • Multi-format input: Scan Git repos, URLs, zip files, directories, or single files
    • 71 vulnerability patterns across 17 categories: prompt injection, data exfiltration, privilege escalation, supply chain, excessive agency, output handling, system prompt leakage, memory poisoning, tool misuse, rogue agent, anti-refusal, trigger abuse, dangerous code (AST), taint tracking, YARA signatures, MCP least privilege, and MCP tool poisoning
    • Two-stage analysis: Fast static analysis + optional LLM semantic evaluation
    • Live vulnerability lookups: SC4 queries OSV.dev for real-time CVE data with automatic offline fallback
    • Multiple output formats: Terminal, JSON, Markdown, and SARIF reports
    • Risk scoring: 0-100 score with severity labels and clear recommendations
    • Baseline / false-positive suppression: Accept known findings via a glob-rule or fingerprint baseline so re-scans surface only new issues (docs)

    Quick Start

    Installation

    Open-source software notice: This project will download and install additional third-party open source software projects. Review the license terms of these open source projects before use.

    Create 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.

    Quick install with uv (CLI-only):

    root@kitploit:~
    uv tool install git+https://github.com/NVIDIA/skillspector.git
    # Update later: uv tool update skillspector
    

    If you plan to run skillspector mcp, install the MCP extra at install time:

    root@kitploit:~
    uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
    

    From source:

    root@kitploit:~
    # Clone the repository
    git clone https://github.com/NVIDIA/skillspector.git
    cd skillspector
    
    # Create and activate virtual environment
    uv venv .venv && source .venv/bin/activate
    # or: python3 -m venv .venv && source .venv/bin/activate
    
    # Install for production use
    make install
    
    # Or install with development dependencies
    make install-dev
    

    Docker (no Python required)

    Run SkillSpector without installing Python by building it locally from the included Dockerfile. The image is based on the Docker Official Python 3.12-slim-bookworm image.

    Build the image:

    root@kitploit:~
    make docker-build
    # or: docker build -t skillspector .
    

    Scan a local directory by mounting your current directory into /scan, the container's working directory:

    root@kitploit:~
    docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
    

    Scan with LLM analysis by passing credentials with a local .env file:

    root@kitploit:~
    cat > .env <<'EOF'
    SKILLSPECTOR_PROVIDER=anthropic
    ANTHROPIC_API_KEY=sk-ant-...
    EOF
    
    root@kitploit:~
    docker run --rm \
      -v "$PWD:/scan" \
      --env-file .env \
      skillspector scan ./my-skill/
    

    Or pass credentials directly from your shell environment:

    root@kitploit:~
    docker run --rm \
      -v "$PWD:/scan" \
      -e SKILLSPECTOR_PROVIDER=anthropic \
      -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
      skillspector scan ./my-skill/
    

    Write a report to the host filesystem by writing to the mounted directory:

    root@kitploit:~
    docker run --rm \
      -v "$PWD:/scan" \
      skillspector scan ./my-skill/ --no-llm --format json --output report.json
    

    Optional alias for repeated static scans:

    root@kitploit:~
    alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
    skillspector-docker scan ./my-skill/ --no-llm
    

    Basic Usage

    root@kitploit:~
    # 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
    

    Size limits

    SkillSpector enforces two independent caps on remote and archive inputs to bound the impact of oversized downloads and zip bombs:

    • Per-ingest cap: INGEST_MAX_BYTES (100 MiB) — applied to streamed URL downloads, total uncompressed size of zip archives, and post-clone disk usage of Git repos.
    • Zip member cap: INGEST_MAX_ZIP_MEMBERS (10,000) — caps the number of entries in a single zip.

    Note that the per-file 1 MB analysis cap (MAX_FILE_BYTES) is a separate, downstream limit: it bounds what individual analyzers will read out of an already-ingested directory. The ingest caps above bound how much content can land on disk in the first place. A breach of either ingest cap fails closed with an IngestLimitExceededError.

    Output Formats

    root@kitploit:~
    # Terminal output (default) - pretty formatted
    skillspector scan ./my-skill/
    
    # 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
    

    Batch Scanning

    Scan entire directories of skills in parallel from contrib/batch_scan/:

    root@kitploit:~
    python -m contrib.batch_scan.batch_scan ./my-skills/ --no-llm
    python -m contrib.batch_scan.batch_scan ./my-skills/ --workers 20 -f json -o report.json
    python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 20
    

    Supports multilingual detection (zh/ja/ko) and terminal/JSON/Markdown output.

    For LLM scans with higher concurrency, configure multiple API keys following .env.example — the pool improves throughput and resilience, provided the keys don't share an account-level rate limit.

    See the contrib guide for details.

    Note on LLM support: The default configuration targets DeepSeek as the cheapest public option. DeepSeek-Chat is expected to sunset, and the contributor does not have hardware to test against local models. The batch scanner was originally tested with OpenAI-compatible endpoints — DeepSeek's lack of structured-output support required manual JSON-parsing patches. If you can contribute a more universal backend (Ollama, vLLM, or a different provider), PRs are very welcome.

    Suppressing False Positives (baseline)

    Suppress known/accepted findings so the risk score reflects only un-triaged issues and re-scans surface only new findings. See the suppression guide for the full reference.

    root@kitploit:~
    # Accept all current findings into a baseline (run once), then commit it.
    skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
    
    # Scan against the baseline — only NEW findings are reported and scored.
    skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml
    
    # Review what was suppressed (still excluded from the score).
    skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml --show-suppressed
    

    A baseline can also use drift-tolerant glob rules (by rule id, file path, or message) — see .skillspector-baseline.example.yaml. Exact fingerprint baselines are evidence-bound: changing the scanned source or SkillSpector version keeps the finding active until it is reviewed again. When a selected baseline or baseline output is stored inside the skill directory, SkillSpector excludes that exact file from content analysis so its suppression text cannot create findings or enter regenerated fingerprints; sibling files remain in normal scan scope.

    LLM Analysis

    For the best results, configure an OpenAI-compatible LLM endpoint for semantic analysis. Pick a provider with SKILLSPECTOR_PROVIDER; hosted providers ship bundled default models, while CLI providers fall back to the local runtime's default model unless SKILLSPECTOR_MODEL is set. SkillSpector also works against local OpenAI-compatible servers (Ollama, vLLM, llama.cpp) and managed inference gateways.

    Provider (SKILLSPECTOR_PROVIDER)Credential env varEndpointDefault model
    openaiOPENAI_API_KEY (+ optional OPENAI_BASE_URL)api.openai.com (or any OpenAI-compatible URL)gpt-5.4
    anthropicANTHROPIC_API_KEYapi.anthropic.comclaude-opus-4-6
    anthropic_proxyANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URLAny Vertex-style raw-predict proxyclaude-sonnet-4-6
    bedrockAWS_PROFILE (optional) + AWS_REGION — SigV4 via boto3AWS Bedrock Runtimeus.anthropic.claude-sonnet-4-6-20250915-v1:0
    nv_buildNVIDIA_INFERENCE_KEYbuild.nvidia.comdeepseek-ai/deepseek-v4-flash
    claude_cli(none — uses local CLI auth)local claude binarylocal Claude runtime fallback, or SKILLSPECTOR_MODEL
    codex_cli(none — uses local CLI auth)local codex binarylocal Codex runtime fallback, or SKILLSPECTOR_MODEL
    root@kitploit:~
    # Stock OpenAI
    export SKILLSPECTOR_PROVIDER=openai
    export OPENAI_API_KEY=sk-...
    skillspector scan ./my-skill/
    
    # Anthropic
    export SKILLSPECTOR_PROVIDER=anthropic
    export ANTHROPIC_API_KEY=sk-ant-...
    skillspector scan ./my-skill/
    
    # Anthropic via Vertex-style proxy (corporate gateways, GCP Vertex AI)
    export SKILLSPECTOR_PROVIDER=anthropic_proxy
    export ANTHROPIC_PROXY_ENDPOINT_URL=https://my-gateway.example.com/models/claude-sonnet-4-6:streamRawPredict
    export ANTHROPIC_PROXY_API_KEY=your-bearer-token
    export SKILLSPECTOR_MODEL=claude-sonnet-4-6
    skillspector scan ./my-skill/
    
    # AWS Bedrock (Claude via SigV4)
    export SKILLSPECTOR_PROVIDER=bedrock
    # Optional: select an AWS named profile. When unset, the standard
    # boto3 credential chain (env vars, instance metadata, SSO, etc.) resolves.
    # export AWS_PROFILE=my-profile
    export AWS_REGION=us-west-2  # default if unset
    # Default model: us.anthropic.claude-sonnet-4-6-20250915-v1:0
    # Override with any Bedrock model ID, cross-region inference-profile
    # ID, or your own application-inference-profile ARN:
    # export SKILLSPECTOR_MODEL=us.anthropic.claude-opus-4-6-20250915-v1:0
    skillspector scan ./my-skill/
    
    # NVIDIA build.nvidia.com
    export SKILLSPECTOR_PROVIDER=nv_build
    export NVIDIA_INFERENCE_KEY=nvapi-...
    skillspector scan ./my-skill/
    
    # Local Claude CLI — no API key; uses your existing `claude auth login` session
    # Requires: claude CLI installed and authenticated (claude auth login)
    export SKILLSPECTOR_PROVIDER=claude_cli
    # Uses the local Claude CLI runtime fallback unless SKILLSPECTOR_MODEL is set.
    # export SKILLSPECTOR_MODEL=claude-sonnet-4-6
    skillspector scan ./my-skill/
    
    # Local Codex CLI — no API key; uses your existing `codex login` session
    # Requires: codex CLI installed and authenticated
    export SKILLSPECTOR_PROVIDER=codex_cli
    skillspector scan ./my-skill/
    
    # Local Ollama or any OpenAI-compatible endpoint
    export SKILLSPECTOR_PROVIDER=openai
    export OPENAI_API_KEY=ollama
    export OPENAI_BASE_URL=http://localhost:11434/v1
    export SKILLSPECTOR_MODEL=llama3.1:8b
    skillspector scan ./my-skill/
    
    # Override the provider's default model
    export SKILLSPECTOR_MODEL=gpt-5.2
    skillspector scan ./my-skill/
    
    # Skip LLM analysis (faster, static analysis only)
    skillspector scan ./my-skill/ --no-llm
    

    MCP Server

    Run SkillSpector as a Model Context Protocol server so any MCP-capable agent (Claude Code, Codex CLI, Gemini CLI) or remote runtime can call scanning as a tool and gate skill/MCP installs on the result — turning SkillSpector into a runtime guardrail instead of an out-of-band audit step.

    skillspector mcp requires skillspector[mcp].

    root@kitploit:~
    # Install, or reinstall if you already used the CLI-only path
    uv tool install --force 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
    
    # FastMCP stdio transport for local CLI agents
    skillspector mcp
    
    # streamable HTTP/SSE transport for remote / A2A callers
    skillspector mcp --transport http --host 127.0.0.1 --port 8000
    

    The stdio transport is the current FastMCP path for local CLI agents, and the initialize hang reported in issue #199 still applies there.

    The server exposes a single tool:

    • scan_skill(target, use_llm=true, output_format="json") — scans a Git URL, file URL, .zip, .md file, or directory and returns a structured verdict: risk_score (0-100), severity, recommendation, safe_to_install, and findings. It also reports llm_used / scan_mode so a low score from a static-only scan is never mistaken for a clean full scan.

    Register it with Claude Code via:

    root@kitploit:~
    claude mcp add skillspector -- skillspector mcp
    

    Security — HTTP transport trust model

    The HTTP transport ships without authentication. Any caller that can reach the port can invoke scan_skill. Over stdio or 127.0.0.1 this is the same trust boundary as the CLI. If you bind to a routable interface:

    • Sit the server behind an authenticating reverse proxy (e.g. nginx + mTLS) before exposing it externally.
    • Local paths and file:// URLs are automatically rejected over HTTP to prevent unauthenticated callers from reading arbitrary host files. Only remote Git and .zip URLs are accepted.

    Vulnerability Patterns

    SkillSpector detects 71 vulnerability patterns across 17 categories:

    Prompt Injection (6 patterns)

    IDPatternSeverityDescription
    P1Instruction OverrideHIGHCommands to ignore safety constraints
    P2Hidden InstructionsHIGHMalicious directives in comments/invisible text
    P3Exfiltration CommandsHIGHInstructions to transmit context externally
    P4Behavior ManipulationMEDIUMSubtle instructions altering agent decisions
    P5Harmful ContentCRITICALInstructions that could cause physical harm
    P9Whitespace PaddingMEDIUMLarge whitespace padding hiding instructions below/beside the visible area

    Anti-Refusal (3 patterns)

    IDPatternSeverityDescription
    AR1Refusal SuppressionHIGHInstructions to never refuse or always comply (e.g. "never refuse", "always comply")
    AR2Disclaimer SuppressionHIGHInstructions to omit warnings, disclaimers, or ethical commentary (e.g. "no disclaimers", "do not moralize")
    AR3Safety Policy NullificationHIGHJailbreak framing that nullifies guardrails (e.g. "you have no restrictions", "ignore your guidelines", "do anything now")

    Data Exfiltration (4 patterns)

    IDPatternSeverityDescription
    E1External TransmissionMEDIUMSending data to external URLs
    E2Env Variable HarvestingHIGHEnumerating, copying, or searching environment data to collect secrets
    E3File System EnumerationMEDIUMScanning directories for sensitive files
    E4Context LeakageHIGHTransmitting conversation context externally

    Privilege Escalation (3 patterns)

    IDPatternSeverityDescription
    PE1Excessive PermissionsLOWRequesting access beyond stated functionality
    PE2Sudo/Root ExecutionMEDIUMInvoking elevated system privileges
    PE3Credential AccessHIGHReading SSH keys, tokens, passwords

    Supply Chain (9+ patterns)

    IDPatternSeverityDescription
    SC1Unpinned DependenciesLOWNo version constraints on packages
    SC2External Script FetchingHIGHcurl | bash and remote code execution
    SC3Obfuscated CodeHIGHBase64/hex encoded execution
    SC4Known Vulnerable DependenciesHIGHDependencies with known CVEs (live OSV.dev lookup)
    SC5Abandoned DependenciesMEDIUMUnmaintained packages without security updates
    SC6TyposquattingHIGHPackage names similar to popular packages
    SC8Shipped Python BytecodeHIGH__pycache__ / .pyc present (discovery skips; malicious bytecode bypass)
    SC9Concealed Executable ArtifactHIGHExecutable nested in a document container or hidden/disguised artifact

    Excessive Agency (5 patterns)

    IDPatternSeverityDescription
    EA1Unrestricted Tool AccessHIGHUnfettered tool access without constraints
    EA2Autonomous Decision MakingHIGHHigh-impact decisions without human-in-the-loop
    EA3Scope CreepMEDIUMCapabilities extending beyond stated purpose
    EA4Unbounded Resource AccessMEDIUMNo rate limits or quotas on resource consumption
    EA5External Model or Provider SelectionMEDIUM/HIGHModel/provider pins or coding-CLI shell-outs that can switch billing accounts

    Output Handling (3 patterns)

    IDPatternSeverityDescription
    OH1Unvalidated Output InjectionHIGHModel output used without sanitization
    OH2Cross-Context OutputMEDIUMOutput flows across trust boundaries without validation
    OH3Unbounded OutputMEDIUMNo limits on output size or generation rate

    System Prompt Leakage (3 patterns)

    IDPatternSeverityDescription
    P6Direct LeakageHIGHInstructions that expose system prompts or internal rules
    P7Indirect ExtractionMEDIUMExtraction via rephrasing, translation, or side-channels
    P8Tool-Based ExfiltrationHIGHSystem prompts exfiltrated via file writes or network requests

    Memory Poisoning (3 patterns)

    IDPatternSeverityDescription
    MP1Persistent Context InjectionHIGHContent designed to persist across interactions
    MP2Context Window StuffingMEDIUMFiller content displacing safety constraints
    MP3Memory ManipulationHIGHTampering with agent memory or stored state

    Tool Misuse (3 patterns)

    IDPatternSeverityDescription
    TM1Tool Parameter AbuseHIGHCrafted parameters for unintended behavior (shell=True, --force)
    TM2Chaining AbuseHIGHTool chains that bypass individual safety checks
    TM3Unsafe DefaultsMEDIUMOverly permissive defaults (disabled TLS, no auth)

    Rogue Agent (2 patterns)

    IDPatternSeverityDescription
    RA1Self-ModificationCRITICALModifying own code or configuration at runtime
    RA2Session PersistenceHIGHUnauthorized persistence via cron jobs or startup scripts

    Trigger Abuse (3 patterns)

    IDPatternSeverityDescription
    TR1Overly Broad TriggerMEDIUMTrigger patterns matching common words
    TR2Shadow Command TriggerHIGHTriggers that shadow built-in commands or other skills
    TR3Keyword Baiting TriggerMEDIUMGeneric triggers designed to maximize activation

    Behavioral AST (9 patterns)

    IDPatternSeverityDescription
    AST1exec() CallCRITICALDirect exec() enabling arbitrary code execution
    AST2eval() CallHIGHDirect eval() evaluating arbitrary expressions
    AST3Dynamic ImportHIGH__import__() loading arbitrary modules at runtime
    AST4subprocess CallHIGHExternal command execution via subprocess
    AST5os.system / exec-familyHIGHShell commands via os module
    AST6compile() CallMEDIUMCode object creation from strings
    AST7Dynamic getattr()MEDIUMArbitrary attribute access with non-literal names
    AST8Dangerous Execution ChainCRITICALexec/eval combined with dynamic source (network, encoded data)
    AST9Reflective getattr() SinkHIGHReflective exec via getattr(os,'system') / getattr(builtins,'exec') that evades AST1/AST5

    Taint Tracking (5 patterns)

    IDPatternSeverityDescription
    TT1Direct Taint FlowHIGHData flows directly from a source to a sink without sanitization
    TT2Variable-Mediated Taint FlowMEDIUMData flows from source to sink through intermediate variables
    TT3Credential Exfiltration ChainCRITICALCredentials (env vars, secrets) flow to network output sinks
    TT4File Read to Network ExfiltrationHIGHFile contents flow to network output sinks
    TT5External Input to Code ExecutionCRITICALNetwork or user input flows to exec/eval/subprocess sinks

    YARA Signatures (4 patterns)

    IDPatternSeverityDescription
    YR1Malware MatchCRITICALYARA rule match for known malware signatures
    YR2Webshell MatchCRITICALYARA rule match for webshell patterns
    YR3Cryptominer MatchHIGHYARA rule match for crypto mining indicators
    YR4Hack Tool / Exploit MatchHIGHYARA rule match for hack tools or exploit code

    MCP Least Privilege (4 patterns)

    IDPatternSeverityDescription
    LP1Underdeclared CapabilityHIGHCode uses capabilities not listed in declared permissions
    LP2Wildcard PermissionMEDIUMPermission list contains wildcards (*, all, full, any)
    LP3Missing Permission DeclarationMEDIUMNo permissions field but code has detectable capabilities
    LP4Overdeclared PermissionLOWPermission declared but no corresponding code capability found

    MCP Tool Poisoning (4 patterns)

    IDPatternSeverityDescription
    TP1Hidden InstructionsHIGHHidden directives in metadata (HTML comments, zero-width chars, base64, data URIs)
    TP2Unicode DeceptionHIGHHomoglyphs, RTL overrides, mixed-script identifiers in tool metadata
    TP3Parameter Description InjectionMEDIUMInjection patterns in parameter definitions (overrides, system tokens, malicious defaults)
    TP4Description-Behavior MismatchMEDIUMDeclared tool description does not match actual code behavior (LLM-powered)

    All detected patterns are listed in the tables above.

    Risk Scoring

    Score Calculation

    • CRITICAL issues: +50 points
    • HIGH issues: +25 points
    • MEDIUM issues: +10 points
    • LOW issues: +5 points
    • Executable scripts: 1.3x multiplier

    Severity Levels

    ScoreSeverityRecommendation
    0-20LOWSAFE
    21-50MEDIUMCAUTION
    51-80HIGHDO NOT INSTALL
    81-100CRITICALDO NOT INSTALL

    Example Output

    Terminal Output

    root@kitploit:~
     SkillSpector Security Report  v2.0.0
    
    Skill: suspicious-skill
    Source: ./suspicious-skill/
    Scanned: 2026-01-29 10:30:00 UTC
    
            Risk Assessment
     Metric          Value
     Score           78/100
     Severity        HIGH
     Recommendation  DO NOT INSTALL
    
            Components (3)
     File              Type      Lines  Executable
     SKILL.md          markdown    142  No
     scripts/sync.py   python       87  Yes
     requirements.txt  text          3  No
    
    Issues (2)
    
      HIGH: Env Variable Harvesting (E2)
        Location: scripts/sync.py:23
        Finding: for key, val in os.environ.items():...
        Confidence: 94%
        Explanation: This code collects environment variables containing
        API keys and secrets, then sends them to an external server.
    
      HIGH: External Transmission (E1)
        Location: scripts/sync.py:45
        Finding: requests.post("https://api.skill.io/env"...
        Confidence: 89%
        Explanation: Data is being sent to an external server. Combined
        with env harvesting above, this indicates credential exfiltration.
    

    Configuration

    Environment Variables

    VariableDescriptionRequired
    SKILLSPECTOR_PROVIDERActive LLM provider: openai, anthropic, anthropic_proxy, bedrock, nv_build, claude_cli, codex_cli, or gemini_cli. Hosted providers use bundled model_registry.yaml defaults; claude_cli and codex_cli fall back to the local CLI runtime's default model unless SKILLSPECTOR_MODEL is set. Defaults to nv_build.Optional
    NVIDIA_INFERENCE_KEYCredential for the nv_build provider (build.nvidia.com).Required for LLM analysis when SKILLSPECTOR_PROVIDER=nv_build
    OPENAI_API_KEYCredential for the OpenAI provider (SKILLSPECTOR_PROVIDER=openai). Also serves as the tier-2 fallback in the credential waterfall when the active provider returns no credentials.Required for LLM analysis when SKILLSPECTOR_PROVIDER=openai
    OPENAI_BASE_URLOverride the OpenAI endpoint (e.g. point at Ollama).Optional
    SKILLSPECTOR_REASONING_EFFORTOptional provider- and model-dependent reasoning-effort setting. Non-empty values are trimmed and passed through unchanged; unset or blank preserves provider-default behavior.Optional
    SKILLSPECTOR_OUTPUT_LANGUAGEShort, single-line language label (letters, numbers, spaces, _, or -; maximum 64 characters) for human-readable LLM finding text such as messages, explanations, and remediation. Rule IDs, severity values, paths, code, and other machine-readable values remain unchanged. Unset, blank, or invalid values preserve the default output language.Optional
    SKILLSPECTOR_TEMPERATUREOptional sampling temperature from 0 to 1 for hosted providers. Unset or blank preserves the provider default. Lower values can reduce run-to-run variation but do not guarantee identical output.Optional

    CLI providers (claude_cli, codex_cli): No API key is needed. Authentication is managed entirely by the agent CLI's own login session (claude auth login / codex login). SkillSpector never reads or forwards API keys when these providers are active. The subprocess is run in a hardened sandbox: tools disabled, no MCP, read-only sandbox mode (codex), and untrusted skill content is delivered only via stdin.

    CLI Options

    root@kitploit:~
    skillspector scan --help
    
    Options:
      -f, --format [terminal|json|markdown|sarif]  Output format [default: terminal]
      -o, --output PATH                            Output file path
      --no-llm                                     Skip LLM analysis (static only)
      --yara-rules-dir PATH                        Extra YARA rules directory
      -b, --baseline PATH                          Suppress findings listed in a baseline
      --show-suppressed                            List baseline-suppressed findings
      -V, --verbose                                Show detailed progress
      --help                                       Show this message and exit
    
    # Generate a baseline of all current findings (see docs/SUPPRESSION.md)
    skillspector baseline <path> [-o FILE] [--no-llm] [--reason TEXT]
    

    Integrating SkillSpector

    SkillSpector is built to be driven by other tools (CI pipelines, install gates, editor integrations). Its exit code and JSON output are a stable contract.

    Exit codes

    skillspector scan exits with:

    CodeMeaning
    0Scan completed, risk_score ≤ 50 (recommendation SAFE or CAUTION)
    1Scan completed, risk_score > 50 (recommendation DO_NOT_INSTALL)
    2Error (bad input, unreadable source, internal failure)

    The exit code collapses SAFE and CAUTION into 0. To act differently on them (e.g. warn on CAUTION but block on DO_NOT_INSTALL), read the recommendation field from the JSON output rather than relying on the exit code.

    Machine-readable output

    --format json produces a JSON report; with no --output/-o it is written to stdout:

    root@kitploit:~
    skillspector scan ./my-skill/ --format json
    

    The top-level shape is (this example shows a full LLM-backed scan; with --no-llm, metadata.llm_requested is false):

    root@kitploit:~
    {
      "skill": { "name": "...", "source": "...", "scanned_at": "<ISO 8601>" },
      "risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
      "components": [ { "path": "...", "type": "...", "lines": 0, "executable": false, "size_bytes": 0 } ],
      "issues": [ { "id": "...", "category": "...", "severity": "...", "confidence": 0.0, "location": { "file": "...", "start_line": 0 } } ],
      "metadata": {
        "has_executable_scripts": false,
        "skillspector_version": "...",
        "llm_requested": true,
        "llm_available": true,
        "inference_usage": [
          {
            "node": "semantic_security_discovery",
            "request_kind": "structured_output",
            "provider": "nv_inference",
            "model": "azure/anthropic/claude-opus-4-6",
            "model_source": "provider_response",
            "usage_source": "provider_response",
            "prompt_tokens": 1000,
            "completion_tokens": 100,
            "cached_tokens": 400,
            "cache_write_tokens": 50,
            "total_tokens": 1100
          }
        ]
      }
    }
    
    • risk_assessment.severity ∈ LOW | MEDIUM | HIGH | CRITICAL.
    • risk_assessment.recommendation ∈ SAFE | CAUTION | DO_NOT_INSTALL, mapped from severity: LOW → SAFE, MEDIUM → CAUTION, HIGH/CRITICAL → DO_NOT_INSTALL.
    • metadata.llm_error appears only when LLM analysis was requested but unavailable.
    • metadata.inference_usage contains one sanitized record per LLM response when the provider exposes token counters. It is an empty list when usage is unavailable; SkillSpector never estimates missing tokens. Prompt totals are inclusive of cache reads and writes so downstream pricing can separate those partitions safely. model_source distinguishes an independently identified provider model from the exact requested model used when response identity is absent or ambiguous. SkillSpector does not currently send Anthropic prompt-cache controls, so its scan requests cannot select the separate 5-minute or 1-hour cache-write tiers; TTL-specific response fields are normalized defensively into the aggregate cache-write counter.
    • See Inference usage telemetry for the complete provenance, cache-accounting, privacy, fail-closed ingestion, and downstream pricing contract.
    • The full per-issue shape is defined by Finding.to_dict() in models.py; rely on the fields above and treat any additional fields as best-effort.

    For CI/IDE tooling, --format sarif emits SARIF 2.1.0.

    Recommended gate mapping

    When using SkillSpector as an install gate, map the recommendation to an action:

    recommendationSuggested action
    SAFEallow
    CAUTIONprompt / warn the user
    DO_NOT_INSTALLblock

    SkillSpector computes the score band and recommendation; how strict the gate is (e.g. whether CAUTION blocks in CI) is a policy decision for the integrating tool.

    Development

    Setup

    All make targets assume a virtual environment is already created and activated. The Makefile uses uv if available, else pip.

    root@kitploit:~
    # Clone, create venv, activate, install dev dependencies
    git clone https://github.com/NVIDIA/skillspector.git
    cd skillspector
    uv venv .venv && source .venv/bin/activate
    # or: python3 -m venv .venv && source .venv/bin/activate
    make install-dev
    
    # Run tests
    make test
    
    # Run tests with coverage
    make test-cov
    
    # Run linting
    make lint
    
    # Format code
    make format
    

    How It Works

    SkillSpector uses a two-stage detection pipeline:

    Stage 1: Static Analysis

    • Fast regex-based pattern matching across 11 static analyzers
    • AST-based behavioral analysis detecting dangerous calls (exec, eval, subprocess, etc.)
    • Live vulnerability lookups via OSV.dev for known CVEs in dependencies
    • Scans all analyzer-eligible files in the skill
    • High recall (catches most issues)
    • Moderate precision (some false positives)

    A valid, root-level OpenSSF Model Signing signature (skill.oms.sig) is retained in the component inventory as type oms_signature, but excluded from static and LLM content analysis. OMS bundles necessarily contain long base64-encoded payload, signature, and certificate fields; generic obfuscated-code checks can otherwise misclassify those fields as hidden executable content. The recognizer checks the minimal OMS DSSE/in-toto structure; it does not verify the signature, certificate chain, transparency-log entry, or signer identity. Invalid or unrecognized signature files are scanned normally.

    Stage 2: LLM Semantic Analysis (Optional)

    • Evaluates context and intent
    • Filters false positives
    • Provides human-readable explanations
    • Improves precision to ~87%

    The LLM prompt includes anti-jailbreak protections to prevent malicious skills from manipulating the analysis.

    Live Vulnerability Lookups (SC4)

    SC4 uses the OSV.dev API to check dependencies against the full Open Source Vulnerabilities database — covering tens of thousands of advisories across PyPI and npm.

    • No API key required — OSV.dev is free and unauthenticated.
    • Batch queries — all dependencies are checked in a single HTTP call.
    • Automatic fallback — if OSV.dev is unreachable (air-gapped/offline), a small built-in fallback list is used.
    • Caching — results are cached in-memory for 1 hour to avoid redundant API calls during a session.

    The tool requires outbound HTTPS access to api.osv.dev for live vulnerability data. When that is not available, findings are limited to the static fallback list.

    Trust model and data egress

    SkillSpector is defense-in-depth, not a sandbox. Know what it does and does not do before relying on it:

    • It never executes the scanned skill. All analysis is static (regex, Python AST, YARA) plus optional LLM evaluation of file contents — the skill's code is never run.
    • LLM analysis sends analyzer-eligible file contents to the configured provider. When LLM analysis is enabled (the default), file contents are sent to the active SKILLSPECTOR_PROVIDER endpoint. Recognized OMS signature files are excluded. Use --no-llm to keep contents local (static analysis only).
    • SC4 sends dependency names to OSV.dev. The supply-chain check queries OSV.dev with the package names and versions the skill declares, to look up known CVEs. This is fundamental to the check and runs even with --no-llm. It sends dependency coordinates (not file contents), requires no API key, and falls back to a bundled list when OSV.dev is unreachable.
    • It does not sandbox the host. SkillSpector flags risky patterns before you install a skill; it does not contain or isolate a skill you choose to install anyway.

    Limitations

    • Non-English content: May miss patterns in other languages
    • Image-based attacks: Cannot analyze text in images
    • Encrypted/binary code: Cannot analyze compiled or encrypted content
    • Runtime behavior: Static analysis only, no dynamic execution
    • Offline SC4: Without network access to api.osv.dev, SC4 uses a small static fallback list

    Research Background

    Based on research from "Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale" (Liu et al., 2026):

    • Dataset: 42,447 skills from major marketplaces
    • Vulnerable: 26.1% contain at least one vulnerability
    • High-severity: 5.2% show likely malicious intent
    • Key finding: Skills with executable scripts are 2.12x more likely to be vulnerable

    Python API Integration

    root@kitploit:~
    from skillspector import graph
    
    # Invoke the LangGraph workflow
    result = graph.invoke({
        "input_path": "/path/to/skill",
        "output_format": "json",   # terminal, json, markdown, or sarif
        "use_llm": True,           # False for static-only analysis
    })
    
    # Access results
    print(f"Risk Score: {result['risk_score']}/100")
    print(f"Severity: {result['risk_severity']}")
    print(f"Recommendation: {result['risk_recommendation']}")
    
    for finding in result["filtered_findings"]:
        print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")
    

    License

    Apache License 2.0 - see LICENSE for details.

    Contributing

    Contributions are welcome! Please read our contributing guidelines and submit pull requests.

    Support

    • Issues: GitHub Issues
    Download Tool
    SKILLSPECTOR_SEEDOptional integer sampling seed for OpenAI-compatible and Azure OpenAI providers. Other hosted providers and CLI providers do not receive it. Provider support remains model-dependent.Optional
    ANTHROPIC_API_KEYCredential for the Anthropic provider (SKILLSPECTOR_PROVIDER=anthropic).Required for LLM analysis when SKILLSPECTOR_PROVIDER=anthropic
    ANTHROPIC_BASE_URLOverride the native Anthropic endpoint (default: https://api.anthropic.com).Optional
    ANTHROPIC_PROXY_ENDPOINT_URLFull endpoint URL for the Anthropic proxy provider (Vertex-style raw-predict).Required when SKILLSPECTOR_PROVIDER=anthropic_proxy
    ANTHROPIC_PROXY_API_KEYBearer token for the Anthropic proxy provider.Required when SKILLSPECTOR_PROVIDER=anthropic_proxy
    ANTHROPIC_PROXY_API_VERSIONanthropic_version value sent in the request body (default: vertex-2023-10-16).Optional
    AWS_PROFILENamed AWS profile for the Bedrock provider — authenticates via SigV4 through boto3. When unset, the standard boto3 credential chain (env vars, instance metadata, SSO, etc.) resolves.Optional (used when SKILLSPECTOR_PROVIDER=bedrock)
    AWS_REGIONAWS region for the Bedrock Runtime endpoint. Defaults to us-west-2.Optional (used when SKILLSPECTOR_PROVIDER=bedrock)
    SKILLSPECTOR_MODELOverride the active provider model. For hosted providers, this replaces the bundled default from the LLM Analysis table. For claude_cli and codex_cli, this is forwarded as --model instead of using the local CLI runtime fallback.Optional
    SKILLSPECTOR_MODEL_REGISTRYOverride the bundled per-provider YAML registry (src/skillspector/providers/<provider>/model_registry.yaml) with a custom path.Optional
    SKILLSPECTOR_LOG_LEVELLog level: DEBUG, INFO, WARNING, ERROR (default: WARNING).Optional