Volver a actualizaciones
Nuevo releaseAug 8, 2026

SkillSpector v2.8.2

Escáner de seguridad para habilidades de agentes de IA. Detecta vulnerabilidades, patrones maliciosos, riesgos de seguridad, inyección de prompt, exfiltración de datos y riesgos de la cadena de suministro en las habilidades de Claude Code, Codex y MCP antes de instalarlas.

Compartir

SkillSpector

Escáner de seguridad para habilidades de agentes de IA. Detecta vulnerabilidades, patrones maliciosos y riesgos de seguridad antes de instalar habilidades de agentes.

Python 3.12+ License: Apache 2.0

Descripción general

Las habilidades de agentes de IA (usadas por Claude Code, Codex CLI, Gemini CLI, etc.) se ejecutan con confianza implícita y una verificación mínima. Las investigaciones muestran que el 26.1 % de las habilidades contienen vulnerabilidades y el 5.2 % muestra una probable intención maliciosa.

SkillSpector te ayuda a responder: "¿Es segura esta habilidad para instalar?"

SkillSpector es parte del pipeline NVIDIA Verified Skills, que escanea, evalúa y firma habilidades de agentes antes de su publicación. Las habilidades que pasan la verificación se publican en el catálogo de habilidades de NVIDIA.

Documentación

Características

  • Entrada de múltiples formatos: escanea repositorios Git, URL, archivos zip, directorios o archivos individuales
  • 68 patrones de vulnerabilidad en 17 categorías: inyección de prompts, exfiltración de datos, escalada de privilegios, cadena de suministro, agencia excesiva, manejo de salidas, fuga del prompt del sistema, envenenamiento de memoria, uso indebido de herramientas, agente malicioso, anti-rechazo, abuso de disparadores, código peligroso (AST), seguimiento de taint, firmas YARA, privilegio mínimo en MCP y envenenamiento de herramientas MCP
  • Análisis en dos etapas: análisis estático rápido + evaluación semántica opcional con LLM
  • Consultas de vulnerabilidades en vivo: SC4 consulta OSV.dev para obtener datos CVE en tiempo real con respaldo offline automático
  • Múltiples formatos de salida: informes en Terminal, JSON, Markdown y SARIF
  • Puntuación de riesgo: puntuación de 0 a 100 con etiquetas de severidad y recomendaciones claras
  • Supresión de línea base / falsos positivos: acepta hallazgos conocidos mediante una regla glob o una línea base de huellas digitales para que los nuevos escaneos solo muestren problemas nuevos (documentación)

Inicio rápido

Instalación

Aviso de software de código abierto: este proyecto descargará e instalará proyectos de software de código abierto adicionales de terceros. Revisa los términos de licencia de estos proyectos de código abierto antes de usarlos.

Primero crea y activa un entorno virtual (todos los objetivos de make asumen que el venv está activo). Usa uv o pip; el Makefile usa uv si está disponible, de lo contrario pip.

Instalación rápida con uv (solo CLI):```bash uv tool install git+https://github.com/NVIDIA/skillspector.git

Update later: uv tool update skillspector

Si planeas ejecutar `skillspector mcp`, instala la extra de MCP en el momento de la instalación:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'

Desde la fuente:```bash

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 requiere Python)

Ejecuta SkillSpector sin instalar Python compilándolo localmente desde el [Dockerfile](https://github.com/nvidia/skillspector/blob/HEAD/Dockerfile) incluido. La imagen está basada en la imagen oficial de Docker Python `3.12-slim-bookworm`.

**Construye la imagen:**```bash
make docker-build
# or: docker build -t skillspector .

Escanea un directorio local montando tu directorio actual en /scan, el directorio de trabajo del contenedor:```bash docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm

**Escaneo con análisis LLM** pasando credenciales con un archivo local `.env`:```bash
cat > .env <<'EOF'
SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
EOF

I don't see any actual content to translate in your message. The chunk text appears to be missing after "INPUT:". Please provide the Markdown content for chunk 13 of 47, and I'll translate it into Spanish.```bash docker run --rm
-v "$PWD:/scan"
--env-file .env
skillspector scan ./my-skill/

O pasa las credenciales directamente desde tu entorno de shell:```bash
docker run --rm \
  -v "$PWD:/scan" \
  -e SKILLSPECTOR_PROVIDER=anthropic \
  -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
  skillspector scan ./my-skill/

Escribe un informe al sistema de archivos del host escribiendo en el directorio montado:```bash docker run --rm
-v "$PWD:/scan"
skillspector scan ./my-skill/ --no-llm --format json --output report.json

**Alias opcional** para escaneos estáticos repetidos:```bash
alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
skillspector-docker scan ./my-skill/ --no-llm

Uso básico```bash

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

#### Límites de tamaño

SkillSpector aplica dos límites independientes a las entradas remotas y de archivos comprimidos para acotar el impacto de descargas sobredimensionadas y bombas zip:

- **Límite por ingesta**: `INGEST_MAX_BYTES` (100 MiB) — aplicado a descargas de URL en streaming, al tamaño total sin comprimir de los archivos zip y al uso de disco posterior a la clonación de repositorios Git.
- **Límite de miembros del zip**: `INGEST_MAX_ZIP_MEMBERS` (10 000) — limita el número de entradas en un único zip.

Ten en cuenta que el límite de análisis de 1 MB por archivo (`MAX_FILE_BYTES`) es un límite posterior independiente: acota lo que los analizadores individuales leerán de un directorio ya ingerido. Los límites de ingesta anteriores acotan cuánto contenido puede terminar en disco en primer lugar. Un incumplimiento de cualquiera de los límites de ingesta falla en modo cerrado con un `IngestLimitExceededError`.

### Formatos de salida```bash
# 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

Escaneo por Lotes

Escanea directorios completos de habilidades en paralelo desde contrib/batch_scan/:```bash 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

Admite detección multilingüe (zh/ja/ko) y salida en terminal/JSON/Markdown.

Para escaneos LLM con mayor concurrencia, configura varias claves de API siguiendo
[`.env.example`](https://github.com/nvidia/skillspector/blob/HEAD/contrib/batch_scan/.env.example) — el conjunto mejora el rendimiento
y la resiliencia, siempre que las claves no compartan un límite de tasa a nivel de cuenta.

Consulta la [guía de contribución](https://github.com/nvidia/skillspector/blob/HEAD/contrib/batch_scan/docs/) para obtener más detalles.

> **Nota sobre el soporte LLM:** La configuración predeterminada apunta a DeepSeek como la
> opción pública más económica. Se espera que DeepSeek-Chat
> [llegue a su fin](https://api-docs.deepseek.com/), y el colaborador
> no dispone de hardware para probar modelos locales. El escáner por lotes se probó
> originalmente con endpoints compatibles con OpenAI — la falta de soporte de
> salida estructurada de DeepSeek requirió parches manuales de análisis de JSON. Si puedes
> contribuir con un backend más universal (Ollama, vLLM u otro proveedor),
> los PR son muy bienvenidos.

### Supresión de Falsos Positivos (línea base)

Suprime hallazgos conocidos/aceptados para que la puntuación de riesgo refleje solo los
problemas sin clasificar y los reescaneos solo muestren hallazgos *nuevos*. Consulta la
[guía de supresión](https://github.com/nvidia/skillspector/blob/HEAD/docs/SUPPRESSION.md) para la referencia completa.```bash
# 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

Una línea base también puede usar reglas glob tolerantes a la deriva (por id de regla, ruta de archivo o mensaje) — consulte .skillspector-baseline.example.yaml. Las líneas base de huella exacta están ligadas a la evidencia: cambiar la fuente escaneada o la versión de SkillSpector mantiene el hallazgo activo hasta que se revise de nuevo. Cuando una línea base seleccionada o la salida de una línea base se almacena dentro del directorio de la skill, SkillSpector excluye ese archivo exacto del análisis de contenido para que su texto de supresión no pueda crear hallazgos ni incorporarse a huellas regeneradas; los archivos hermanos permanecen en el ámbito de escaneo normal.

Análisis LLM

Para obtener los mejores resultados, configure un endpoint LLM compatible con OpenAI para el análisis semántico. Elija un proveedor con SKILLSPECTOR_PROVIDER; los proveedores alojados incluyen modelos predeterminados integrados, mientras que los proveedores CLI recurren al modelo predeterminado del runtime local a menos que se establezca SKILLSPECTOR_MODEL. SkillSpector también funciona con servidores locales compatibles con OpenAI (Ollama, vLLM, llama.cpp) y con puertas de enlace de inferencia administradas.

Proveedor (SKILLSPECTOR_PROVIDER)Variable de entorno de credencialEndpointModelo predeterminado
openaiOPENAI_API_KEY (+ opcional OPENAI_BASE_URL)api.openai.com (o cualquier URL compatible con OpenAI)gpt-5.4
anthropicANTHROPIC_API_KEYapi.anthropic.comclaude-opus-4-6
anthropic_proxyANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URLCualquier proxy de predicción sin procesar estilo Vertexclaude-sonnet-4-6
bedrockAWS_PROFILE (opcional) + AWS_REGION — SigV4 mediante boto3AWS Bedrock Runtimeus.anthropic.claude-sonnet-4-6-20250915-v1:0
nv_buildNVIDIA_INFERENCE_KEYbuild.nvidia.comdeepseek-ai/deepseek-v4-flash
claude_cli(ninguno — usa autenticación CLI local)binario local clauderespaldo del runtime local de Claude, o SKILLSPECTOR_MODEL
codex_cli(ninguno — usa autenticación CLI local)binario local codexrespaldo del runtime local de Codex, o SKILLSPECTOR_MODEL

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

### Servidor MCP

Ejecuta SkillSpector como un servidor [Model Context Protocol](https://modelcontextprotocol.io)
para que cualquier agente compatible con MCP (Claude Code, Codex CLI, Gemini CLI) o entorno
de ejecución remoto pueda invocar el escaneo como herramienta y **condicionar las
instalaciones de skills/MCP al resultado** — convirtiendo a SkillSpector en una salvaguarda
en tiempo de ejecución en lugar de un paso de auditoría fuera de banda.

`skillspector mcp` requiere `skillspector[mcp]`.```bash
# 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

El transporte stdio es la ruta actual de FastMCP para agentes CLI locales, y el bloqueo de inicialización reportado en el issue #199 sigue aplicándose allí.

El servidor expone una única herramienta:

  • scan_skill(target, use_llm=true, output_format="json") — escanea una URL de Git, una URL de archivo, un .zip, un .md o un directorio y devuelve un veredicto estructurado: risk_score (0-100), severity, recommendation, safe_to_install y findings. También informa llm_used / scan_mode para que una puntuación baja de un escaneo únicamente estático nunca se confunda con un escaneo completo limpio.

Regístralo con Claude Code mediante:```bash claude mcp add skillspector -- skillspector mcp

> **Seguridad — modelo de confianza del transporte HTTP**
>
> El transporte HTTP se distribuye **sin autenticación**. Cualquier llamador que pueda
> alcanzar el puerto puede invocar `scan_skill`. Sobre stdio o `127.0.0.1` esto es
> el mismo límite de confianza que la CLI. Si se vincula a una interfaz enrutable:
>
> - Coloca el servidor detrás de un proxy inverso con autenticación (p. ej. nginx + mTLS)
>   antes de exponerlo externamente.
> - Las rutas locales y las URL `file://` son **rechazadas automáticamente** sobre HTTP para
>   evitar que llamadores no autenticados lean archivos arbitrarios del host. Solo
>   se aceptan URL remotas de Git y `.zip`.

## Patrones de Vulnerabilidad

SkillSpector detecta **68 patrones de vulnerabilidad** en 17 categorías:

### Inyección de Prompt (5 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| P1 | Anulación de Instrucciones | ALTO | Comandos para ignorar restricciones de seguridad |
| P2 | Instrucciones Ocultas | ALTO | Directivas maliciosas en comentarios/texto invisible |
| P3 | Comandos de Exfiltración | ALTO | Instrucciones para transmitir contexto externamente |
| P4 | Manipulación de Comportamiento | MEDIO | Instrucciones sutiles que alteran las decisiones del agente |
| P5 | Contenido Dañino | CRÍTICO | Instrucciones que podrían causar daño físico |

### Anti-Rechazo (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| AR1 | Supresión de Rechazo | ALTO | Instrucciones para nunca negarse o cumplir siempre (p. ej. "never refuse", "always comply") |
| AR2 | Supresión de Descargos | ALTO | Instrucciones para omitir advertencias, descargos o comentarios éticos (p. ej. "no disclaimers", "do not moralize") |
| AR3 | Anulación de Política de Seguridad | ALTO | Marco de jailbreak que anula las salvaguardas (p. ej. "you have no restrictions", "ignore your guidelines", "do anything now") |

### Exfiltración de Datos (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| E1 | Transmisión Externa | MEDIO | Envío de datos a URL externas |
| E2 | Recolección de Variables de Entorno | ALTO | Recopilación de claves API y secretos |
| E3 | Enumeración del Sistema de Archivos | MEDIO | Escaneo de directorios en busca de archivos sensibles |
| E4 | Fuga de Contexto | ALTO | Transmisión del contexto de la conversación externamente |

### Escalada de Privilegios (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| PE1 | Permisos Excesivos | BAJO | Solicitar acceso más allá de la funcionalidad declarada |
| PE2 | Ejecución Sudo/Root | MEDIO | Invocar privilegios elevados del sistema |
| PE3 | Acceso a Credenciales | ALTO | Lectura de claves SSH, tokens y contraseñas |

### Cadena de Suministro (6 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| SC1 | Dependencias sin Fijar | BAJO | Sin restricciones de versión en los paquetes |
| SC2 | Obtención de Scripts Externos | ALTO | curl \| bash y ejecución remota de código |
| SC3 | Código Ofuscado | ALTO | Ejecución codificada en Base64/hex |
| SC4 | Dependencias con Vulnerabilidades Conocidas | ALTO | Dependencias con CVEs conocidos (consulta en vivo a OSV.dev) |
| SC5 | Dependencias Abandonadas | MEDIO | Paquetes sin mantenimiento ni actualizaciones de seguridad |
| SC6 | Typosquatting | ALTO | Nombres de paquetes similares a paquetes populares |

### Agencia Excesiva (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| EA1 | Acceso Ilimitado a Herramientas | ALTO | Acceso irrestricto a herramientas sin limitaciones |
| EA2 | Toma de Decisiones Autónoma | ALTO | Decisiones de alto impacto sin supervisión humana |
| EA3 | Ampliación del Alcance | MEDIO | Capacidades que se extienden más allá del propósito declarado |
| EA4 | Acceso Ilimitado a Recursos | MEDIO | Sin límites de velocidad ni cuotas sobre el consumo de recursos |

### Manejo de Salida (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| OH1 | Inyección de Salida no Validada | ALTO | Salida del modelo utilizada sin saneamiento |
| OH2 | Salida entre Contextos | MEDIO | La salida fluye entre límites de confianza sin validación |
| OH3 | Salida Ilimitada | MEDIO | Sin límites en el tamaño de la salida ni en la tasa de generación |

### Fuga del Prompt del Sistema (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| P6 | Fuga Directa | ALTO | Instrucciones que exponen prompts del sistema o reglas internas |
| P7 | Extracción Indirecta | MEDIO | Extracción mediante reformulación, traducción o canales laterales |
| P8 | Exfiltración Basada en Herramientas | ALTO | Prompts del sistema exfiltrados mediante escrituras de archivos o peticiones de red |

### Envenenamiento de Memoria (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| MP1 | Inyección Persistente de Contexto | ALTO | Contenido diseñado para persistir entre interacciones |
| MP2 | Relleno de la Ventana de Contexto | MEDIO | Contenido de relleno que desplaza las restricciones de seguridad |
| MP3 | Manipulación de Memoria | ALTO | Alteración de la memoria del agente o del estado almacenado |

### Uso Indebido de Herramientas (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TM1 | Abuso de Parámetros de Herramienta | ALTO | Parámetros diseñados para un comportamiento no intencionado (shell=True, --force) |
| TM2 | Abuso de Encadenamiento | ALTO | Cadenas de herramientas que omiten las comprobaciones de seguridad individuales |
| TM3 | Valores Predeterminados Inseguros | MEDIO | Valores predeterminados demasiado permisivos (TLS deshabilitado, sin autenticación) |

### Agente Rebelde (2 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| RA1 | Auto-Modificación | CRÍTICO | Modificación del propio código o configuración en tiempo de ejecución |
| RA2 | Persistencia de Sesión | ALTO | Persistencia no autorizada mediante tareas cron o scripts de inicio |

### Abuso de Disparadores (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TR1 | Disparador Demasiado Amplio | MEDIO | Patrones de disparador que coinciden con palabras comunes |
| TR2 | Disparador de Comando Sombrío | ALTO | Disparadores que ensombrecen comandos integrados u otras habilidades |
| TR3 | Disparador de Cebo por Palabras Clave | MEDIO | Disparadores genéricos diseñados para maximizar la activación |

### AST de Comportamiento (9 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| AST1 | Llamada a exec() | CRÍTICO | exec() directo que habilita la ejecución arbitraria de código |
| AST2 | Llamada a eval() | ALTO | eval() directo que evalúa expresiones arbitrarias |
| AST3 | Importación Dinámica | ALTO | \_\_import\_\_() que carga módulos arbitrarios en tiempo de ejecución |
| AST4 | Llamada a subprocess | ALTO | Ejecución de comandos externos mediante subprocess |
| AST5 | os.system / familia exec | ALTO | Comandos shell mediante el módulo os |
| AST6 | Llamada a compile() | MEDIO | Creación de objetos de código a partir de cadenas |
| AST7 | getattr() dinámico | MEDIO | Acceso arbitrario a atributos con nombres no literales |
| AST8 | Cadena de Ejecución Peligrosa | CRÍTICO | exec/eval combinado con fuente dinámica (red, datos codificados) |
| AST9 | Sumidero getattr() reflectante | ALTO | exec reflectante mediante `getattr(os,'system')` / `getattr(builtins,'exec')` que evade AST1/AST5 |

### Seguimiento de Taint (5 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TT1 | Flujo de Taint Directo | ALTO | Los datos fluyen directamente de una fuente a un sumidero sin saneamiento |
| TT2 | Flujo de Taint Mediado por Variables | MEDIO | Los datos fluyen de la fuente al sumidero a través de variables intermedias |
| TT3 | Cadena de Exfiltración de Credenciales | CRÍTICO | Las credenciales (variables de entorno, secretos) fluyen a sumideros de salida de red |
| TT4 | Lectura de Archivo hacia Exfiltración de Red | ALTO | Los contenidos de archivos fluyen a sumideros de salida de red |
| TT5 | Entrada Externa hacia Ejecución de Código | CRÍTICO | Entrada de red o de usuario fluye a sumideros exec/eval/subprocess |

### Firmas YARA (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| YR1 | Coincidencia de Malware | CRÍTICO | Coincidencia de regla YARA para firmas de malware conocidas |
| YR2 | Coincidencia de Webshell | CRÍTICO | Coincidencia de regla YARA para patrones de webshell |
| YR3 | Coincidencia de Criptominero | ALTO | Coincidencia de regla YARA para indicadores de criptominería |
| YR4 | Coincidencia de Herramienta de Hackeo / Exploit | ALTO | Coincidencia de regla YARA para herramientas de hackeo o código de exploit |

### MCP de Mínimo Privilegio (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| LP1 | Capacidad Subdeclarada | ALTO | El código utiliza capacidades no listadas en los permisos declarados |
| LP2 | Permiso Comodín | MEDIO | La lista de permisos contiene comodines (\*, all, full, any) |
| LP3 | Declaración de Permiso Faltante | MEDIO | Sin campo de permisos pero el código tiene capacidades detectables |
| LP4 | Permiso Sobredeclarado | BAJO | Permiso declarado pero no se encontró ninguna capacidad de código correspondiente |

### Envenenamiento de Herramientas MCP (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TP1 | Instrucciones Ocultas | ALTO | Directivas ocultas en metadatos (comentarios HTML, caracteres de ancho cero, base64, data URIs) |
| TP2 | Engaño Unicode | ALTO | Homoglifos, anulaciones RTL, identificadores de escritura mixta en metadatos de herramientas |
| TP3 | Inyección en Descripción de Parámetros | MEDIO | Patrones de inyección en definiciones de parámetros (anulaciones, tokens del sistema, valores predeterminados maliciosos) |
| TP4 | Desajuste Descripción-Comportamiento | MEDIO | La descripción declarada de la herramienta no coincide con el comportamiento real del código (potenciado por LLM) |

Todos los patrones detectados se enumeran en las tablas anteriores.

## Puntuación de Riesgo

### Cálculo de Puntuación

- **Problemas CRÍTICOS**: +50 puntos
- **Problemas ALTOS**: +25 puntos
- **Problemas MEDIOS**: +10 puntos
- **Problemas BAJOS**: +5 puntos
- **Scripts ejecutables**: multiplicador de 1.3x

### Niveles de Severidad

| Puntuación | Severidad | Recomendación |
|-------|----------|----------------|
| 0-20 | BAJO | SEGURO |
| 21-50 | MEDIO | PRECAUCIÓN |
| 51-80 | ALTO | NO INSTALAR |
| 81-100 | CRÍTICO | NO INSTALAR |

## Ejemplo de Salida

### Salida de Terminal```
 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.

Configuración

Variables de Entorno

VariableDescripciónRequerido
SKILLSPECTOR_PROVIDERProveedor de LLM activo: openai, anthropic, anthropic_proxy, bedrock, nv_build, claude_cli, codex_cli o gemini_cli. Los proveedores alojados usan los valores predeterminados del model_registry.yaml incluido; claude_cli y codex_cli recurren al modelo predeterminado del runtime CLI local a menos que se establezca SKILLSPECTOR_MODEL. El valor predeterminado es nv_build.Opcional
NVIDIA_INFERENCE_KEYCredencial para el proveedor nv_build (build.nvidia.com).Requerida para el análisis con LLM cuando SKILLSPECTOR_PROVIDER=nv_build
OPENAI_API_KEYCredencial para el proveedor OpenAI (SKILLSPECTOR_PROVIDER=openai). También actúa como respaldo de nivel 2 en la cascada de credenciales cuando el proveedor activo no devuelve credenciales.Requerida para el análisis con LLM cuando SKILLSPECTOR_PROVIDER=openai
OPENAI_BASE_URLAnula el endpoint de OpenAI (p. ej., apuntar a Ollama).Opcional
SKILLSPECTOR_REASONING_EFFORTConfiguración opcional de esfuerzo de razonamiento dependiente del proveedor y del modelo. Los valores no vacíos se recortan y se pasan sin cambios; si no se establece o está vacío, se conserva el comportamiento predeterminado del proveedor.Opcional
ANTHROPIC_API_KEYCredencial para el proveedor Anthropic (SKILLSPECTOR_PROVIDER=anthropic).Requerida para el análisis con LLM cuando SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_BASE_URLAnula el endpoint nativo de Anthropic (predeterminado: https://api.anthropic.com).Opcional
ANTHROPIC_PROXY_ENDPOINT_URLURL completa del endpoint para el proveedor proxy de Anthropic (raw-predict estilo Vertex).Requerida cuando SKILLSPECTOR_PROVIDER=anthropic_proxy
ANTHROPIC_PROXY_API_KEYToken Bearer para el proveedor proxy de Anthropic.Requerida cuando SKILLSPECTOR_PROVIDER=anthropic_proxy
ANTHROPIC_PROXY_API_VERSIONValor de anthropic_version enviado en el cuerpo de la solicitud (predeterminado: vertex-2023-10-16).Opcional
AWS_PROFILEPerfil AWS con nombre para el proveedor Bedrock: autentica mediante SigV4 a través de boto3. Si no se establece, se resuelve mediante la cadena de credenciales estándar de boto3 (variables de entorno, metadatos de instancia, SSO, etc.).Opcional (se usa cuando SKILLSPECTOR_PROVIDER=bedrock)
AWS_REGIONRegión de AWS para el endpoint de Bedrock Runtime. El valor predeterminado es us-west-2.Opcional (se usa cuando SKILLSPECTOR_PROVIDER=bedrock)
SKILLSPECTOR_MODELAnula el modelo del proveedor activo. Para proveedores alojados, reemplaza el valor predeterminado incluido de la tabla de Análisis con LLM. Para claude_cli y codex_cli, se reenvía como --model en lugar de usar el respaldo del runtime CLI local.Opcional
SKILLSPECTOR_MODEL_REGISTRYAnula el registro YAML incluido por proveedor (src/skillspector/providers/<provider>/model_registry.yaml) con una ruta personalizada.Opcional
SKILLSPECTOR_LOG_LEVELNivel de registro: DEBUG, INFO, WARNING, ERROR (predeterminado: WARNING).Opcional

Proveedores CLI (claude_cli, codex_cli): no se necesita clave API. La autenticación la gestiona por completo la sesión de inicio de sesión del propio CLI del agente (claude auth login / codex login). SkillSpector nunca lee ni reenvía claves API cuando estos proveedores están activos. El subproceso se ejecuta en un sandbox reforzado: herramientas deshabilitadas, sin MCP, modo sandbox de solo lectura (codex), y el contenido de habilidades no confiable se entrega únicamente a través de stdin.

Opciones de CLI```bash

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 [-o FILE] [--no-llm] [--reason TEXT]

## Integración con SkillSpector

SkillSpector está diseñado para ser impulsado por otras herramientas (pipelines de CI, puertas de instalación, integraciones de editor). Su código de salida y la salida JSON son un contrato estable.

### Códigos de salida

`skillspector scan` termina con:

| Código | Significado |
|------|---------|
| `0` | Escaneo completado, `risk_score` ≤ 50 (recomendación `SAFE` o `CAUTION`) |
| `1` | Escaneo completado, `risk_score` > 50 (recomendación `DO_NOT_INSTALL`) |
| `2` | Error (entrada incorrecta, fuente ilegible, fallo interno) |

> El código de salida agrupa `SAFE` y `CAUTION` en `0`. Para actuar de forma diferente según el caso (p. ej., *advertir* en `CAUTION` pero *bloquear* en `DO_NOT_INSTALL`), lea el campo `recommendation` de la salida JSON en lugar de depender del código de salida.

### Salida legible por máquina

`--format json` genera un informe JSON; sin `--output`/`-o` se escribe en stdout:```bash
skillspector scan ./my-skill/ --format json

La forma de nivel superior es (este ejemplo muestra un escaneo completo respaldado por LLM; con --no-llm, metadata.llm_requested es false):```json { "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": "anthropic", "model": "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`, mapeado desde la severidad: `LOW → SAFE`, `MEDIUM → CAUTION`, `HIGH`/`CRITICAL → DO_NOT_INSTALL`.
- `metadata.llm_error` aparece solo cuando se solicitó análisis de LLM pero no estuvo disponible.
- `metadata.inference_usage` contiene un registro saneado por cada respuesta de LLM cuando el
  proveedor expone contadores de tokens. Es una lista vacía cuando el uso no está disponible;
  SkillSpector nunca estima tokens faltantes. Los totales de prompt incluyen lecturas de caché
  y escrituras para que la facturación posterior pueda separar esas particiones de forma segura.
  `model_source` distingue un modelo de proveedor identificado de forma independiente del
  modelo exacto solicitado que se usa cuando la identidad de la respuesta está ausente o es ambigua.
  SkillSpector actualmente no envía controles de caché de prompt de Anthropic, por lo que sus
  solicitudes de escaneo no pueden seleccionar los niveles separados de escritura en caché de 5 minutos o 1 hora;
  los campos de respuesta específicos de TTL se normalizan de forma defensiva en el contador agregado de
  escritura en caché.
- Consulta [Telemetría de uso de inferencia](https://github.com/nvidia/skillspector/blob/HEAD/docs/INFERENCE_USAGE.md) para conocer el contrato
  completo de procedencia, contabilidad de caché, privacidad, ingesta de cierre ante fallos y
  facturación posterior.
- La forma completa por problema se define mediante `Finding.to_dict()` en [models.py](https://github.com/nvidia/skillspector/blob/HEAD/src/skillspector/models.py); confía en los campos anteriores y trata cualquier campo adicional como de mejor esfuerzo.

Para herramientas de CI/IDE, `--format sarif` emite SARIF 2.1.0.

### Mapeo de compuerta recomendado

Al usar SkillSpector como compuerta de instalación, asigna la recomendación a una acción:

| `recommendation` | Acción sugerida |
|------------------|------------------|
| `SAFE` | permitir |
| `CAUTION` | preguntar / advertir al usuario |
| `DO_NOT_INSTALL` | bloquear |

SkillSpector calcula la banda de puntuación y la recomendación; lo estricta que sea la compuerta (p. ej., si `CAUTION` bloquea en CI) es una decisión de política para la herramienta integradora.

## Desarrollo

### Configuración

Todos los objetivos de `make` asumen que ya se ha creado y activado un entorno virtual. El Makefile usa **uv** si está disponible; de lo contrario, **pip**.```bash
# 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

Cómo funciona

SkillSpector utiliza un pipeline de detección en dos etapas:

Etapa 1: Análisis estático

  • Coincidencia rápida de patrones basada en regex en 11 analizadores estáticos
  • Análisis de comportamiento basado en AST que detecta llamadas peligrosas (exec, eval, subprocess, etc.)
  • Consultas de vulnerabilidades en vivo a través de OSV.dev para CVEs conocidos en dependencias
  • Escanea todos los archivos elegibles por los analizadores en la skill
  • Alta exhaustividad (detecta la mayoría de los problemas)
  • Precisión moderada (algunos falsos positivos)

Una firma válida de OpenSSF Model Signing de nivel raíz (skill.oms.sig) se conserva en el inventario de componentes como tipo oms_signature, pero se excluye del análisis estático y de contenido LLM. Los paquetes OMS contienen necesariamente campos largos de payload, firma y certificado codificados en base64; las comprobaciones genéricas de código ofuscado podrían clasificar erróneamente esos campos como contenido ejecutable oculto. El reconocedor verifica la estructura mínima OMS DSSE/in-toto; no verifica la firma, la cadena de certificados, la entrada del registro de transparencia ni la identidad del firmante. Los archivos de firma inválidos o no reconocidos se escanean normalmente.

Etapa 2: Análisis semántico LLM (opcional)

  • Evalúa el contexto y la intención
  • Filtra falsos positivos
  • Proporciona explicaciones legibles por humanos
  • Mejora la precisión hasta ~87%

El prompt LLM incluye protecciones anti-jailbreak para evitar que skills maliciosos manipulen el análisis.

Consultas de vulnerabilidades en vivo (SC4)

SC4 utiliza la API de OSV.dev para comprobar las dependencias contra la base de datos completa de Vulnerabilidades de Código Abierto, que cubre decenas de miles de avisos en PyPI y npm.

  • No se requiere clave API — OSV.dev es gratuito y sin autenticación.
  • Consultas por lotes — todas las dependencias se comprueban en una sola llamada HTTP.
  • Respaldo automático — si OSV.dev no es accesible (aislado/sin conexión), se usa una pequeña lista de respaldo integrada.
  • Almacenamiento en caché — los resultados se guardan en memoria durante 1 hora para evitar llamadas API redundantes durante una sesión.

La herramienta requiere acceso HTTPS saliente a api.osv.dev para obtener datos de vulnerabilidades en vivo. Cuando no está disponible, los hallazgos se limitan a la lista de respaldo estática.

Modelo de confianza y salida de datos

SkillSpector es defensa en profundidad, no un sandbox. Conoce lo que hace y lo que no hace antes de confiar en él:

  • Nunca ejecuta la skill escaneada. Todo el análisis es estático (regex, AST de Python, YARA) más una evaluación LLM opcional del contenido de los archivos — el código de la skill nunca se ejecuta.
  • El análisis LLM envía el contenido de los archivos elegibles por los analizadores al proveedor configurado. Cuando el análisis LLM está habilitado (por defecto), el contenido de los archivos se envía al endpoint activo SKILLSPECTOR_PROVIDER. Los archivos de firma OMS reconocidos se excluyen. Usa --no-llm para mantener el contenido local (solo análisis estático).
  • SC4 envía los nombres de dependencias a OSV.dev. La comprobación de la cadena de suministro consulta OSV.dev con los nombres y versiones de paquetes que declara la skill, para buscar CVEs conocidos. Esto es fundamental para la comprobación y se ejecuta incluso con --no-llm. Envía coordenadas de dependencias (no contenido de archivos), no requiere clave API y recurre a una lista empaquetada cuando OSV.dev no es accesible.
  • No aísla el host. SkillSpector señala patrones arriesgados antes de que instales una skill; no contiene ni aísla una skill que decidas instalar de todos modos.

Limitaciones

  • Contenido no inglés: Puede pasar por alto patrones en otros idiomas
  • Ataques basados en imágenes: No puede analizar texto en imágenes
  • Código cifrado/binario: No puede analizar contenido compilado o cifrado
  • Comportamiento en tiempo de ejecución: Solo análisis estático, sin ejecución dinámica
  • SC4 sin conexión: Sin acceso de red a api.osv.dev, SC4 usa una pequeña lista de respaldo estática

Antecedentes de la investigación

Basado en la investigación de "Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale" (Liu et al., 2026):

  • Conjunto de datos: 42,447 skills de los principales marketplaces
  • Vulnerables: el 26,1% contienen al menos una vulnerabilidad
  • Alta severidad: el 5,2% muestra probable intención maliciosa
  • Hallazgo clave: los skills con scripts ejecutables tienen 2,12 veces más probabilidades de ser vulnerables

Integración de la API de Python```python

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']}")

## Licencia

Apache License 2.0 - consulte [LICENSE](https://github.com/nvidia/skillspector/blob/HEAD/LICENSE) para conocer los detalles.

## Contribuciones

¡Las contribuciones son bienvenidas! Por favor, lea nuestras pautas de contribución y envíe sus pull requests.

## Soporte

- **Issues**: [GitHub Issues](https://github.com/NVIDIA/skillspector/issues)

Categorías