
CLI de análisis estático que escanea bases de código en busca de inyección de prompts en LLM, exfiltración de datos, jailbreak y vulnerabilidades de agentes/herramientas inseguros. Se ejecuta completamente sin conexión, se integra con CI/CD y genera informes en consola, JSON y SARIF.
Herramienta de análisis estático que escanea tu código base en busca de vulnerabilidades de inyección de prompts y seguridad multimodal. Funciona sin conexión, no requiere llamadas a API.
ContextHound está disponible en todo tu flujo de trabajo de desarrollo y navegación:
| Herramienta | Lo que hace | Instalación |
|---|---|---|
| CLI / paquete npm | Escanea tu código base en busca de vulnerabilidades de inyección de prompts. Se integra con GitHub Actions, genera SARIF, JSON, HTML y más. | npm install -g context-hound |
| Extensión de VS Code | Hallazgos en línea mientras codificas, acciones de código, canal de salida, barra de estado. | VS Code Marketplace |
| Extensión del navegador | Píldora de escaneo en tiempo real en cualquier interfaz de chat de IA, panel DevTools para tráfico de API de LLM, escáner emergente. Chrome y Firefox. | Firefox: Instalar gratis · Chrome: en revisión · fuente |
A medida que las aplicaciones basadas en LLM se vuelven comunes en los códigos base de producción, la inyección de prompts ha surgido como una de las superficies de ataque más explotables; la mayoría de los escáneres de seguridad no la reconocen.
ContextHound lleva el análisis estático a tu capa de prompts:
Se adapta a tu flujo de trabajo existente como un comando CLI, un script npm o una GitHub Action, sin dependencias externas.
Instalación global — agrega el comando hound a tu PATH:```bash
npm install -g context-hound
**Instalación por proyecto** — limitado a un repositorio, se ejecuta mediante `npx hound` o un script npm:```bash
npm install --save-dev context-hound
Zero-install — no requiere instalación, utiliza la copia en caché del registro npm:```bash npx context-hound scan --dir .
## Inicio rápido```bash
# Scaffold a config file
hound init
# Scan your project
hound scan --dir ./my-ai-project
# Or via npm script (scans current directory)
npm run hound
# Verbose output, shows remediations and confidence levels
hound scan --verbose
# Fail the build on any critical finding
hound scan --fail-on critical
# Export JSON and SARIF reports
hound scan --format console,json,sarif --out results
# GitHub Annotations (for CI step summaries)
hound scan --format github-annotations
# Markdown report with findings tables
hound scan --format markdown --out report
# Stream findings as JSONL (one JSON object per line)
hound scan --format jsonl | jq '.severity'
# List all rules
hound scan --list-rules
# Explain a rule (or a rule family by prefix)
hound explain INJ-001
hound explain PST --format json
# Fast PR gate — scan only files changed vs. origin/main
hound scan --diff
# Interactive HTML report (self-contained, open in browser)
hound scan --format html --out report
# Re-scan on file changes
hound scan --watch
# Parallel scanning (default is 8; tune for your machine)
hound scan --concurrency 16
# Disable incremental cache for a clean run
hound scan --no-cache
# Baseline mode — only report findings new since the last saved scan
hound scan --format json --out baseline # save a baseline
hound scan --baseline baseline.json # compare future scans against it
# Load a custom rule from a local plugin file
hound scan # plugin declared in .contexthoundrc.json "plugins" field
# Only run high-confidence rules
hound scan --config .contexthoundrc.json # set minConfidence: "high"
# Fail if any single file scores >= 40
hound scan --fail-file-threshold 40
Códigos de salida:
Agregue a su flujo de trabajo para bloquear fusiones cuando el riesgo de solicitud sea demasiado alto:```yaml
name: Prompt Audit
on: [push, pull_request]
jobs: hound: runs-on: ubuntu-latest permissions: contents: read security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g context-hound
- run: hound scan --format console,sarif,github-annotations --out results.sarif
- name: Upload to GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Los hallazgos aparecerán en la pestaña **Seguridad > Análisis de código** de tu repositorio. El formato `github-annotations` publica comentarios en línea en las PR y escribe una tabla de resumen en el resumen del paso de GitHub.
---
## Configuración
Ejecuta `hound init` para generar un archivo `.contexthoundrc.json`, o créalo manualmente:```json
{
"include": ["**/*.ts", "**/*.js", "**/*.py", "**/*.go", "**/*.rs", "**/*.md", "**/*.txt", "**/*.yaml"],
"exclude": [
"**/node_modules/**",
"**/dist/**",
"**/tests/**",
"**/attacks/**"
],
"threshold": 60,
"formats": ["console", "sarif"],
"out": "results",
"verbose": false,
"failOn": "critical",
"maxFindings": 50,
"excludeRules": ["JBK-002"],
"includeRules": [],
"minConfidence": "medium",
"failFileThreshold": 80,
"concurrency": 8,
"cache": true,
"plugins": ["./rules/my-custom-rule.js"],
"baseline": "./baseline.json"
}
Todas las configuraciones clave pueden anularse en tiempo de ejecución sin editar el archivo de configuración:
.houndignoreColoca un archivo .houndignore en la raíz de tu proyecto para agregar patrones de exclusión sin editar .contexthoundrc.json. Sigue la misma sintaxis de glob; las líneas que comienzan con # son comentarios.
Silencia un falso positivo conocido directamente en el código fuente — no es necesario deshabilitar una regla en todo el repo. Las directivas se reconocen en cualquier tipo de archivo (la sintaxis de comentario circundante no importa):```ts
// hound-disable-next-line INJ-001 -- userInput is a validated enum
const prompt = Summarise the ${userInput} report;
const cmd = run(${shell}); // hound-disable-line CMD-001
// hound-disable RAG-007 -- trusted internal corpus only context.push(doc.metadata.title); context.push(doc.metadata.author); // hound-enable RAG-007
- `hound-disable-line [RULE...]` — suprimir hallazgos en la misma línea
- `hound-disable-next-line [RULE...]` — suprimir hallazgos en la línea siguiente
- `hound-disable [RULE...]` … `hound-enable [RULE...]` — suprimir un bloque (se cierra automáticamente al final del archivo)
- Omitir los ID de reglas para suprimir **todas** las reglas en esa ubicación; enumere una o más (separadas por espacio/comas) para acotarlo
- El texto después de `--` es una justificación de formato libre, que aparece en los informes
Ejecute con `--report-unused-suppressions` para listar las directivas que ya no coinciden con ningún hallazgo, de modo que las supresiones obsoletas se puedan limpiar:```bash
hound scan --report-unused-suppressions
Habilite un subconjunto seleccionado de reglas con --preset en lugar de listar IDs. Los presets se combinan con cualquier includeRules que ya tenga, y se pueden combinar varios:```bash
hound scan --preset owasp-llm-top10
hound scan --preset mcp,agentic
hound scan --list-presets # show all presets and their rule patterns
| Preconfiguración | Reglas |
|--------|-------|
| `owasp-llm-top10` | INJ, JBK, EXF, OUT, RAG, TOOL, SCH, DOS, VIS |
| `injection` | INJ, RAG, ENC |
| `jailbreak` | JBK |
| `exfiltration` | EXF |
| `agentic` | AGT, MCP, TOOL |
| `mcp` | MCP |
| `supply-chain` | SCH |
| `prompt-files` | INJ, JBK, EXF, ENC, SKL |
### hook de pre-commit
ContextHound incluye un [hook de pre-commit](https://pre-commit.com). Añádelo a tu `.pre-commit-config.yaml`:```yaml
repos:
- repo: https://github.com/IulianVOStrut/ContextHound
rev: v2.0.0
hooks:
- id: contexthound
# optional — scan only changed files and fail on high-severity findings:
# args: ["--diff", "HEAD", "--fail-on", "high"]
Cualquier archivo .js que exporte un Rule o Rule[] se puede cargar como complemento:```js
// my-rule.js
module.exports = {
id: 'CUSTOM-001',
title: 'Proprietary data pattern in prompt',
severity: 'high',
confidence: 'high',
category: 'injection',
remediation: 'Remove internal identifiers from prompts.',
check(prompt) {
if (prompt.text.includes('INTERNAL_PATTERN')) {
return [{ evidence: 'INTERNAL_PATTERN', lineStart: 1, lineEnd: 1 }];
}
return [];
},
};
Referencia en `.contexthoundrc.json`:```json
{ "plugins": ["./my-rule.js"] }
Las reglas de plugin están sujetas a los mismos filtros excludeRules, includeRules y minConfidence que las reglas integradas.
Guarde una línea base después de un análisis inicial, luego solo informe los hallazgos que sean nuevos en análisis posteriores:```bash
hound scan --format json --out baseline
hound scan --baseline baseline.json
Los hallazgos se emparejan por `ruleId + file` — los cambios de línea no generan falsas alertas de nuevos hallazgos.
### Changed-files-only (`--diff`)
Para puertas rápidas de pull-request, escanea solo los archivos que cambiaron en relación con una referencia de git en lugar de todo el árbol:```bash
hound scan --diff # vs. origin/main (default)
hound scan --diff main # vs. a named branch
hound scan --diff HEAD~5 # vs. an arbitrary ref
Cubre archivos confirmados, en staging, sin staging y no rastreados pero no ignorados. Si git no está disponible o la referencia no puede resolverse (por ejemplo, un clon superficial de CI), ContextHound imprime una advertencia y recurre a un escaneo completo en lugar de pasar silenciosamente. Combínalo con --baseline para un diff a nivel de hallazgos, o usa --diff solo para la retroalimentación más rápida del PR.
Cada hallazgo conlleva puntos de riesgo calculados como:``` risk_points = severity_weight × confidence_multiplier
Los puntos se suman, con un tope de 100, y se clasifican:
| Puntuación | Nivel | Acción sugerida |
|-------|-------|-----------------|
| 0-29 | 🟢 Bajo | No se requiere acción |
| 30-59 | 🟡 Medio | Revisar antes de fusionar |
| 60-79 | 🟠 Alto | Corregir antes de fusionar |
| 80-100 | 🔴 Crítico | Bloquear despliegue |
Si tus prompts incluyen un lenguaje de seguridad explícito (delimitadores de entrada, instrucciones para no revelar, listas de herramientas permitidas), los puntos de riesgo para ese prompt se reducen proporcionalmente.
---
## Reglas
### A. Inyección (INJ)
| ID | Gravedad | Descripción |
|----|----------|-------------|
| INJ-001 | Alto | Entrada de usuario directa concatenada en el prompt sin delimitador |
| INJ-002 | Medio | Falta de lenguaje de límite "tratar el contenido del usuario como datos" |
| INJ-003 | Alto | Contexto RAG/recuperado incluido sin separador no confiable |
| INJ-004 | Alto | Instrucciones de uso de herramientas anulables por contenido del usuario |
| INJ-005 | Alto | Objeto de usuario serializado (`JSON.stringify`) interpolado directamente en una plantilla de prompt |
| INJ-006 | Medio | Comentario HTML que contiene verbos de instrucción ocultos en contenido controlado por el usuario |
| INJ-007 | Medio | Entrada de usuario envuelta en delimitadores de bloque de código sin eliminar primero los backticks |
| INJ-008 | Alto | Datos de solicitud HTTP (`req.body`, `req.query`, `req.params`) interpolados en una cadena de plantilla de `role: "system"` |
| INJ-009 | Crítico | Cuerpo de solicitud HTTP analizado directamente como la matriz de mensajes — el atacante controla el rol y el contenido |
| INJ-010 | Alto | Transcripción de etiquetas de rol en texto plano (`User:`, `Assistant:`, `system:`) construida con concatenación de entrada no confiable |
| INJ-011 | Alto | Fuente DOM o URL del navegador (`window.location`, `document.cookie`, `getElementById`) alimentada directamente a la llamada LLM |
| INJ-012 | Alto | Historial de conversación extendido en la matriz de mensajes sin sanitización |
| INJ-013 | Alto | Resultado de llamada a herramienta/función insertado en mensajes sin sanitización |
| INJ-014 | Alto | Salida LLM canalizada como contenido de rol de usuario en una llamada LLM posterior |
| INJ-015 | Alto | Entrada externa no confiable (HTTP/CLI/DOM) fluye hacia un prompt — **análisis de contaminación** independiente del nombre, sigue alias, respeta sanitizadores |
### B. Exfiltración (EXF)
| ID | Gravedad | Descripción |
|----|----------|-------------|
| EXF-001 | Crítico | Prompt referencia secretos, claves de API o credenciales |
| EXF-002 | Crítico | Prompt instruye al modelo a revelar el prompt del sistema o instrucciones ocultas |
| EXF-003 | Alto | Prompt indica acceso a datos confidenciales o privados |
| EXF-004 | Alto | Prompt incluye URL internas o nombres de host de infraestructura |
| EXF-005 | Alto | Variable sensible (token, contraseña, clave) codificada como Base64 en la salida |
| EXF-006 | Alto | Prompt completo o matriz de mensajes registrados mediante `console.log` / `logger.*` sin redacción |
| EXF-007 | Crítico | Valor secreto real incrustado en el prompt junto con una instrucción de "nunca revelar" |
### C. Jailbreak (JBK)
| ID | Gravedad | Descripción |
|----|----------|-------------|
| JBK-001 | Crítico | Frase de jailbreak conocida detectada ("ignore instructions", "DAN", etc.) |
| JBK-002 | Alto | Redacción de seguridad débil ("always comply", "no matter what") |
| JBK-003 | Alto | Escape de juego de roles que socava las restricciones de seguridad |
| JBK-004 | Alto | Agente instruido para actuar sin confirmación o revisión humana ("proceed automatically", "no confirmation needed") |
| JBK-005 | Alto | Instrucción de borrado de evidencia o encubrimiento de rastros ("delete logs", "leave no trace") |
| JBK-006 | Alto | Encuadre de legitimidad de política combinado con una solicitud de acción insegura ("as a penetration tester, escalate privileges") |
| JBK-007 | Alto | Suplantación de identidad del modelo — afirma ser un modelo de IA diferente combinado con una directiva de elusión de seguridad |
| JBK-008 | Alto | Ataque de compresión de prompt — instrucción para comprimir o resumir el prompt del sistema |
| JBK-009 | Alto | Inyección de instrucciones anidadas — comandos imperativos envueltos en un marco de "resumen/traducción seguro/inocuo" |
### D. Uso inseguro de herramientas (TOOL)
| ID | Gravedad | Descripción |
|----|----------|-------------|
| TOOL-001 | Crítico | Ejecución de herramientas sin límites ("run any command", "browse anywhere", sustitución de shell con backticks) |
| TOOL-002 | Medio | Uso de herramientas descrito sin lista blanca ni política de uso |
| TOOL-003 | Alto | Ejecución de código mencionada sin restricciones de sandboxing |
| TOOL-004 | Crítico | Descripción de herramienta o campo de esquema obtenido de una variable controlada por el usuario |
| TOOL-005 | Crítico | `name` de herramienta o `url` de endpoint obtenido de entrada controlada por el usuario (`req.body`, `req.query`, etc.) |
### E. Inyección de comandos (CMD)
Detecta patrones vulnerables en el código que rodea a las herramientas de IA, donde una inyección de prompt exitosa puede escalar a ejecución completa de comandos. Informado por CVEs reales encontrados en Gemini CLI de Google por Cyera Research Labs (2025).
| ID | Gravedad | Descripción |
|----|----------|-------------|
| CMD-001 | Crítico | Comando de shell construido con interpolación de variable no sanitizada — JS/TS (`execSync(\`cmd ${var}\``), Python (`subprocess.run(f"cmd {var}")`), PHP (`shell_exec($var)`), Go (`exec.Command` + `fmt.Sprintf`), Rust (`Command::new` + `format!`) |
| CMD-002 | Alto | Filtrado de sustitución de comandos incompleto: bloquea `$()` pero no backticks, o viceversa |
| CMD-003 | Alto | Ruta de archivo de `glob.sync` o `readdirSync` utilizada directamente en un comando de shell sin sanitización |
| CMD-004 | Crítico | Python `subprocess.run`/`subprocess.call` invocado con `shell=True` y un argumento de comando variable o f-string |
| CMD-005 | Crítico | PHP `shell_exec`, `system`, `passthru`, `exec`, o `popen` llamado con un argumento `$variable` |
### F. Envenenamiento de RAG (RAG)
Detecta errores arquitectónicos en pipelines de Generación Aumentada por Recuperación que permiten que el contenido recuperado o ingerido anule las instrucciones a nivel de sistema.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| RAG-001 | Alto | Contenido recuperado o externo asignado a `role: "system"` en una matriz de mensajes |
| RAG-002 | Alto | Frases similares a instrucciones ("system prompt:", "always return", "never redact") detectadas dentro de un bucle de ingesta de documentos |
| RAG-003 | Alto | Almacén de memoria del agente escrito directamente desde entrada controlada por el usuario sin validación |
| RAG-004 | Medio | Prompt instruye al modelo a tratar el contexto recuperado como la máxima prioridad, anulando las instrucciones del desarrollador |
| RAG-005 | Medio | Recuperación sin procedencia — fragmentos insertados en el prompt sin verificación de metadatos de origen |
| RAG-006 | Alto | Sin filtro de ACL o nivel de confianza aplicado antes de que la recuperación entre en el prompt |
### G. Codificación (ENC)
Detecta técnicas de inyección y evasión basadas en codificación donde se utilizan codificaciones Base64 o similares para introducir instrucciones de contrabando más allá de los filtros basados en cadenas.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| ENC-001 | Medio | `atob`, `btoa`, o `Buffer.from(x, 'base64')` llamados sobre una variable controlada por el usuario cerca de la construcción del prompt |
| ENC-002 | Alto | Caracteres de control Unicode ocultos (espacios de ancho cero, anulaciones bidireccionales) detectados cerca de palabras clave de instrucción |
### H. Manejo de salida (OUT)
Cubre el lado de salida del pipeline LLM — cómo tu aplicación consume las respuestas del modelo. Un consumo inseguro puede convertir una carga útil de inyección de prompt en una explotación a nivel de aplicación.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| OUT-001 | Crítico | `JSON.parse()` (JS/TS) o `json.loads()` (Python) llamado en la salida LLM sin validación de esquema (Zod, AJV, Joi, Pydantic, Marshmallow, etc.) |
| OUT-002 | Crítico | Markdown o HTML generado por LLM renderizado sin DOMPurify o sanitizador equivalente |
| OUT-003 | Crítico | Salida LLM utilizada directamente como argumento para `exec()`, `eval()`, o `db.query()` |
| OUT-004 | Crítico | Python `eval()` o `exec()` llamado con salida generada por LLM como argumento |
### I. Multimodal (VIS)
Cubre violaciones de límites de confianza específicas de pipelines de visión, audio/video y OCR. Las entradas multimodales son un vector de inyección emergente: un atacante que controla una URL de imagen, un archivo de audio o un documento escaneado puede usar los patrones de estas reglas para introducir instrucciones en el modelo.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| VIS-001 | Crítico | URL de imagen proporcionada por el usuario o datos base64 reenviados a una API de visión (gpt-4o, Claude 3, Gemini Vision) sin validación de dominio o MIME |
| VIS-002 | Crítico | `fs.readFile`/`readFileSync` llamado con una ruta controlada por el usuario en un archivo que también construye un mensaje de API de visión — path traversal hacia entrada multimodal |
| VIS-003 | Alto | Salida de transcripción de audio/video (Whisper, AssemblyAI, Deepgram, etc.) alimentada directamente a los mensajes del prompt sin sanitización — envenenamiento de RAG mediante fuente de audio |
| VIS-004 | Alto | Salida OCR (Tesseract, Google Vision) interpolada en un mensaje de `role: "system"` o variable de prompt del sistema |
### J. Mercado de habilidades (SKL) — v1.1
Se dirige a archivos `SKILL.md` de OpenClaw y cualquier archivo markdown dentro de directorios `skills/`. Se activa en ataques de autoautoría, carga remota de habilidades, instrucciones inyectadas, despacho de comandos inseguro, acceso a rutas sensibles, afirmaciones de escalada de privilegios y credenciales codificadas en frontmatter YAML.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| SKL-001 | Crítico | El cuerpo de la habilidad instruye al agente a escribir o modificar otros archivos de habilidad — ataque de autoautoría que persiste entre reinicios del agente |
| SKL-002 | Crítico | El cuerpo de la habilidad instruye al agente a obtener o cargar habilidades desde una URL externa — permite al atacante cambiar el comportamiento de la habilidad después de la instalación |
| SKL-003 | Crítico | El cuerpo de la habilidad contiene frases de inyección de prompt dirigidas a las instrucciones principales del agente (`ignore previous instructions`, `you are now unrestricted`, etc.) |
| SKL-004 | Alto | Frontmatter de habilidad usa `command-dispatch: tool` con `command-arg-mode: raw` — reenvía la entrada bruta del usuario a una herramienta, evitando el razonamiento de seguridad del modelo |
| SKL-005 | Alto | El cuerpo de la habilidad referencia rutas de archivos sensibles (`~/.ssh`, `~/.env`, `/etc/passwd`, `../../`) para que el agente las lea y potencialmente las exfiltre |
| SKL-006 | Alto | El cuerpo de la habilidad afirma tener privilegios elevados o instruye al agente a anular o deshabilitar otras habilidades instaladas |
| SKL-007 | Crítico | Valor de credencial codificado (clave API, token, contraseña) encontrado en frontmatter YAML — expuesto a cualquiera que reciba o instale la habilidad |
| SKL-008 | Crítico | Heartbeat C2 — la habilidad programa una recuperación remota periódica para sobrescribir silenciosamente sus propias instrucciones después de una instalación limpia |
| SKL-009 | Crítico | Negación de identidad del agente — la habilidad instruye al agente a negar ser IA, afirmar ser humano o adoptar una personalidad engañosa |
| SKL-010 | Crítico | Evasión de escáner — la habilidad contiene texto diseñado explícitamente para engañar a herramientas de auditoría de seguridad |
| SKL-011 | Crítico | Persistencia SOUL.md / IDENTITY.md — la habilidad escribe instrucciones en archivos de identidad del agente que sobreviven a la desinstalación |
| SKL-012 | Alto | Gusano de autopropagación — la habilidad instruye al agente a propagarse a través de SSH o `curl\|bash` a hosts accesibles |
| SKL-013 | Alto | Transacciones financieras autónomas — la habilidad ejecuta transacciones criptográficas o posee claves privadas sin confirmación del usuario por transacción |
> **Escaneo de habilidades OpenClaw:** Ejecuta `npx hound scan --dir ./skills` o agrega `**/skills/**/*.md` y `**/SKILL.md` a tu configuración `include`. ContextHound emite automáticamente archivos de habilidad como `code-block` para análisis de reglas multilínea.
### K. Agentic (AGT) — v1.3 / v1.9
Se dirige a riesgos específicos de sistemas agénticos de múltiples pasos: bucles de ejecución ilimitados, escrituras de memoria no validadas, filtraciones de entrada del usuario en la planificación del agente, violaciones de límites de confianza entre agentes y brechas de OWASP Agentic AI Security Issues (ASI).
| ID | Gravedad | Descripción |
|----|----------|-------------|
| AGT-001 | Crítico | El parámetro de llamada a herramienta recibe contenido del prompt del sistema — valor de argumento `tool_call`/`function_call` que contiene contenido de campos `system:` o `instructions:` |
| AGT-002 | Alto | Bucle del agente sin protección de iteración o tiempo de espera — no hay `max_iterations`, `max_steps`, `max_turns`, `timeout`, o `recursion_limit` en la configuración o código del agente |
| AGT-003 | Alto | Memoria del agente escrita a partir de salida LLM no validada — `memory.save()`, `memory.add()`, o `vectorstore.upsert()` llamados con una variable de respuesta del modelo en bruto |
| AGT-004 | Alto | Inyección de plan — la entrada del usuario se interpola directamente en el prompt de planificación, tarea u objetivo del agente sin un envoltorio de límite de confianza |
| AGT-005 | Crítico | El agente confía en la identidad reclamada sin verificación criptográfica — decisión de confianza basada en el campo `agentId`, `sender`, `source`, o `from_agent` sin verificación HMAC, JWT o secreto compartido |
| AGT-006 | Alto | Salida bruta del agente encadenada como entrada a otro agente sin validación — `.run()`, `.invoke()`, o `.generate()` llamado con el `.output`/`.content`/`.result` de otro agente directamente como argumento |
| AGT-007 | Crítico | Automodificación del agente — el agente reescribe su propio `system_prompt`, `instructions`, o lista `tools` con contenido generado por LLM en tiempo de ejecución |
| AGT-008 | Crítico | ASI03 — El agente llama a `assumeRole`, `grantAccess`, o `setPermissions` con un valor derivado de la salida LLM; escalada de privilegios mediante inyección de prompt |
| AGT-009 | Alto | ASI04 — El agente carga una herramienta o plugin en tiempo de ejecución desde una ruta variable o importación dinámica, permitiendo la sustitución en la cadena de suministro |
| AGT-010 | Alto | ASI07 — La salida bruta del agente se reenvía a otro agente a través de `send`/`route`/`dispatch` sin HMAC, firma JWT o validación de esquema |
| AGT-011 | Alto | ASI08 — Error de paso del plan del agente capturado silenciosamente (sin relanzamiento, sin indicador de estado de error); los pasos posteriores proceden con estado incorrecto o incompleto |
### L. Seguridad MCP (MCP) — v1.7 / v1.8
Cubre riesgos de límites de confianza y cadena de suministro específicos del Protocolo de Contexto del Modelo. MCP introduce una nueva superficie de ataque: descripciones de herramientas, URL de transporte, cargas útiles de eventos y estado compartido entre servidores pueden transportar cargas útiles de inyección o escalada de privilegios.
| ID | Gravedad | Descripción |
|----|----------|-------------|
| MCP-001 | Crítico | Descripción de herramienta MCP inyectada en el prompt LLM sin sanitización — valor `tool.description` en bruto usado en `role: "system"` o `messages.push()` |
| MCP-002 | Alto | Herramienta MCP registrada con nombre o descripción dinámica — el primer argumento de `server.tool()` es una variable o plantilla literal, permitiendo ataques de cambio de configuración posterior a la aprobación |
| MCP-003 | Alto | Manejador de sampling/createMessage de MCP sin protección de aprobación humana — `setRequestHandler(CreateMessageRequestSchema)` sin verificación `requireHumanApproval`, `confirm`, o `approve` |
| MCP-004 | Medio | URL de transporte MCP construida a partir de una variable — `SSEClientTransport` o `WebSocketClientTransport` inicializados con `new URL(variable)` en lugar de una cadena estática |
| MCP-005 | Alto | Transporte stdio de MCP usa `shell: true` — hace que la cadena de comandos sea interpolada por el shell e inyectable si algún argumento es controlado por el usuario |
| MCP-006 | Crítico | Diputado confundido de MCP — token de autenticación de la solicitud MCP reenviado a la API descendente sin revalidación; valor del encabezado `Authorization` obtenido directamente de `request.params`, `context`, o `event` |
| MCP-007 | Alto | Envenenamiento de contexto MCP cruzado — almacén de contexto compartido/global escrito desde salida MCP sin verificación de hash, firma o procedencia |
| MCP-008 | Alto | Comando de transporte stdio de MCP cargado desde ruta variable — campo `command:` de `StdioClientTransport`/`StdioServerTransport` es una variable en lugar de un literal de cadena estática |
| MCP-009 | Alto | ID de sesión MCP usado como decisión de autenticación sin verificación de caducidad — comparación de igualdad de `sessionId`/`connectionId` sin guardia TTL, `expiresAt`, o `isExpired` (ataque de reproducción) |
| MCP-010 | Crítico | Carga útil de evento de transporte MCP inyectada en el contexto LLM sin sanitización — `.data`, `.content`, o `.payload` del evento/mensaje usado directamente en `messages.push()` o un campo `content:` |
---
## Ejemplo de salida```
=== ContextHound Prompt Audit ===
src/prompts/assistant.ts (file score: 73)
[HIGH] INJ-001: Direct user input concatenation without delimiter
File: src/prompts/assistant.ts:12
Evidence: Answer the user's question: ${userInput}
Confidence: medium
Risk points: 23
Remediation: Wrap user input with clear delimiters (e.g., triple backticks)
and label it as "untrusted user content".
[CRITICAL] EXF-001: Prompt references secrets, API keys, or credentials
File: src/prompts/assistant.ts:8
Evidence: The database password is: secret123.
Confidence: high
Risk points: 50
Remediation: Remove all secret values from prompts. Use environment
variables server-side; never embed credentials in prompt text.
────────────────────────────────────────────────────────
Repo Risk Score: 87/100 (CRITICAL)
Threshold: 60
Total findings: 5
By severity: critical: 2 high: 2 medium: 1
✗ FAILED - score meets or exceeds threshold.
src/ ├── cli.ts # CLI entry point (Commander.js) ├── types.ts # Shared TypeScript types ├── config/ │ ├── defaults.ts # Default include/exclude globs and settings │ └── loader.ts # .contexthoundrc.json loader + env var overrides ├── scanner/ │ ├── discover.ts # File discovery via fast-glob │ ├── extractor.ts # Prompt extraction (raw, code, structured) │ ├── languages.ts # LLM API trigger patterns per language extension │ ├── cache.ts # Incremental scan cache (.hound-cache.json) │ └── pipeline.ts # Orchestrates the full scan; parallel + cache + plugins ├── rules/ │ ├── types.ts # Rule interface and scoring helpers │ ├── injection.ts # INJ-* rules │ ├── exfiltration.ts # EXF-* rules │ ├── jailbreak.ts # JBK-* rules │ ├── unsafeTools.ts # TOOL-* rules │ ├── commandInjection.ts # CMD-* rules │ ├── rag.ts # RAG-* rules │ ├── encoding.ts # ENC-* rules │ ├── outputHandling.ts # OUT-* rules │ ├── multimodal.ts # VIS-* rules │ ├── skills.ts # SKL-* rules │ ├── agentic.ts # AGT-* rules │ ├── mcp.ts # MCP-* rules │ ├── supplyChain.ts # SCH-* rules │ ├── dos.ts # DOS-* rules │ ├── mitigation.ts # Mitigation presence detection │ └── index.ts # Rule registry ├── runtime/ │ ├── index.ts # createGuard() — runtime message inspection API │ ├── inspect.ts # Core inspection logic for live message arrays │ └── types.ts # RuntimeMessage, InspectResult, GuardConfig types ├── scoring/ │ └── index.ts # Risk score calculation and rule filtering └── report/ ├── console.ts # ANSI-coloured terminal output ├── json.ts # JSON report builder ├── sarif.ts # SARIF 2.1.0 report builder ├── githubAnnotations.ts# GitHub Actions annotation formatter ├── markdown.ts # Markdown report with findings tables ├── jsonl.ts # JSONL streaming formatter └── html.ts # Self-contained interactive HTML report attacks/ # Example injection strings (not executed against models) tests/ ├── fixtures/ # Sample prompts for testing ├── rules.test.ts # Unit tests for all rules ├── scoring.test.ts # Unit tests for scoring logic ├── scanner.test.ts # Integration tests for the scan pipeline ├── extractor.test.ts # Unit tests for prompt extraction ├── formatters.test.ts # Unit tests for all report formatters ├── mitigation.test.ts # Unit tests for mitigation detection └── cli.test.ts # CLI integration tests (init, list-rules, exit codes) .github/ ├── action.yml # Reusable composite GitHub Action └── workflows/ └── context-hound.yml # CI workflow
## Evaluación comparativa
ContextHound incluye un conjunto de datos de referencia etiquetado para medir tasas de falsos positivos y detección. Ejecútelo después de la compilación:```bash
npm run benchmark
| Directory | Propósito |
|---|---|
benchmarks/safe/ | 5 archivos con patrones seguros genuinos — espere 0 hallazgos |
benchmarks/unsafe/ | 8 archivos con vulnerabilidades reales — una regla cada uno |
Resultados en v1.4.0:``` File-level FP rate: 0.0% (0 / 5 safe files produced findings) Detection rate: 100.0% (8/8 expected findings triggered)
El benchmark termina con código 1 si se encuentra algún falso positivo o falso negativo, lo que lo hace adecuado como puerta de calidad de CI para cambios de reglas. Para añadir un fixture, coloca un archivo en `benchmarks/safe/` o `benchmarks/unsafe/` y actualiza `benchmarks/labels.json` con los hallazgos esperados.
### Precisión / recall por regla
El benchmark también imprime una **tabla de señales por regla** (peor F1 primero) para que las reglas de baja precisión sean fáciles de detectar: verdaderos/falsos positivos, falsos negativos, precisión, recall y F1 para cada regla etiquetada. Los recuentos de FP provienen de los fixtures de `safe/` (verdad fundamental: cero hallazgos); TP/FN provienen de los fixtures etiquetados de `unsafe/`. Pasa `--report <path>` para también emitir un informe JSON legible por máquina para paneles de control o seguimiento de tendencias de CI:```bash
npm run benchmark -- --report bench-report.json
La extensión de navegador ContextHound proporciona detección en tiempo real de inyección de prompts en Chrome y Firefox. Utiliza el mismo motor de reglas que la CLI, compilado y empaquetado localmente — sin solicitudes de red, sin backend.
Estado: La extensión de Firefox está activa — instalar desde Complementos de Firefox. El envío a Chrome está pendiente de revisión en la Web Store. Código fuente disponible en github.com/IulianVOStrut/ContextHound-Extensions.
Pastilla de escaneo Aparece un indicador ligero junto a cualquier entrada de chat de IA en cualquier sitio web. Mientras escribes, la extensión escanea el texto contra 70 reglas de detección y muestra una puntuación de riesgo y hallazgos en un panel desplegable — sin necesidad de navegar por la página.
Panel de DevTools Abre las DevTools del navegador y selecciona la pestaña ContextHound para monitorear el tráfico en vivo de la API de LLM. La extensión intercepta solicitudes salientes a OpenAI, Anthropic, Google Gemini, Mistral, Groq, Cohere, DeepSeek y otros servicios, escaneando tanto el cuerpo de la solicitud como la respuesta en busca de contenido de inyección. Una insignia en la barra de herramientas refleja la puntuación de riesgo más alta vista en la sesión actual.
Escáner emergente Haz clic en el icono de la barra de herramientas para pegar y escanear cualquier texto manualmente. Útil para revisar un prompt o instrucción del sistema recibida de un tercero antes de usarlo.
La API HAR de DevTools de Chrome y Firefox (onRequestFinished) no incluye de manera confiable los bytes del cuerpo de la solicitud para respuestas de streaming/SSE, que la mayoría de los servicios de chat de IA utilizan. La extensión resuelve esto con un enfoque de dos capas:
chrome.webRequest.onBeforeRequest intercepta los bytes brutos de la solicitud en el service worker antes de que se envíe, los almacena en caché brevemente en chrome.storage.session (TTL: 5 minutos).onRequestFinished se activa y postData está ausente, la página de DevTools obtiene el cuerpo almacenado en caché desde el service worker mediante un mensaje POP_BODY_CACHE.La extensión no recopila datos del usuario. Todo el escaneo es local. Consulta la política de privacidad.
Las contribuciones son bienvenidas. Para agregar una nueva regla:
src/rules/ (o crea uno nuevo para una nueva categoría)src/rules/index.tstests/rules.test.tsnpm test para verificar que todas las pruebas pasenMIT
| 95 reglas de seguridad | En 14 categorías: inyección, exfiltración, jailbreak, uso no seguro de herramientas, inyección de comandos, envenenamiento RAG, codificación, manejo de salida, multimodal, mercado de habilidades, agentico, MCP, cadena de suministro, DoS |
| Puntuación de riesgo numérica (0-100) | Puntuación normalizada a nivel de repositorio con umbrales bajo, medio, alto y crítico |
| Detección de mitigaciones | El lenguaje de seguridad explícito en tus prompts reduce tu puntuación |
| 7 formatos de salida | Consola, JSON, SARIF, Anotaciones de GitHub, Markdown, streaming JSONL y HTML interactivo |
| GitHub Action incluida | Falla CI en riesgo alto y sube resultados SARIF automáticamente |
| Escaneo multilingüe | Detecta uso de API de LLM en Python, Go, Rust, Java, C#, PHP, Ruby, Swift, Kotlin, Vue, Bash — no solo TypeScript/JavaScript |
| Filtrado de reglas | excludeRules/includeRules con sintaxis de prefijo-glob (CMD-*); filtro minConfidence |
| Caché incremental | .hound-cache.json omite archivos sin cambios en re-ejecuciones; --no-cache para deshabilitar |
| Sistema de plugins | Carga reglas personalizadas desde archivos .js locales mediante "plugins": ["./my-rule.js"] en la configuración |
| Modo de línea base / diff | --baseline results.json — solo reporta y falla en hallazgos no presentes en un escaneo anterior |
| Modo de vigilancia | --watch re-escannea al cambiar archivos y muestra hallazgos delta |
| Escaneo paralelo | Procesamiento concurrente de archivos (--concurrency <n>, predeterminado 8) |
| Completamente sin conexión | Sin llamadas a API, sin telemetría, sin dependencias de pago |
| Código | Significado |
|---|
0 | Correcto — puntuación por debajo del umbral, sin violación de failOn |
1 | Error no controlado o argumentos incorrectos |
2 | Umbral superado — puntuación del repositorio ≥ umbral, o se excedió el umbral del archivo |
3 | Violación de --fail-on — hallazgo de la gravedad especificada encontrado |
| Opción | Predeterminado | Descripción |
|---|
include | **/*.{ts,tsx,js,jsx,py,go,rs,java,kt,cs,php,rb,swift,vue,sh,bash,hs,md,txt,yaml,yml,json} | Patrones glob para escanear |
exclude | **/node_modules/**, **/dist/**, etc. | Patrones glob para ignorar |
threshold | 60 | Fallar si la puntuación del repo es igual o superior a este valor (código de salida 2) |
formats | ["console"] | Formatos de salida: console, json, sarif, github-annotations, markdown, jsonl, html |
out | auto | Ruta base para la salida de archivos |
verbose | false | Mostrar correcciones y confianza por hallazgo |
failOn | sin definir | Código de salida 3 al primer hallazgo de: critical, high o medium |
maxFindings | sin definir | Detenerse después de N hallazgos |
excludeRules | [] | IDs de reglas o globs de prefijo para omitir (ej. "CMD-*", "JBK-002") |
includeRules | [] | Ejecutar solo estos IDs de reglas (vacío = ejecutar todas) |
minConfidence | sin definir | Omitir reglas por debajo de esta confianza: low, medium o high |
failFileThreshold | sin definir | Fallar (código de salida 2) si cualquier archivo individual puntúa igual o superior a este valor |
concurrency | 8 | Máximo de archivos procesados en paralelo |
cache | true | Habilitar caché de escaneo incremental (.hound-cache.json); establecer false o usar --no-cache para deshabilitar |
plugins | [] | Rutas a plugins de reglas .js locales; cada uno debe exportar un Rule o Rule[] |
baseline | sin definir | Ruta a un informe JSON previo; solo se reportan hallazgos ausentes en la línea base |
| Variable | Anula |
|---|
HOUND_THRESHOLD | threshold |
HOUND_FAIL_ON | failOn |
HOUND_MIN_CONFIDENCE | minConfidence |
HOUND_VERBOSE | verbose (true: 1, true, yes) |
HOUND_CONFIG | ruta al archivo de configuración |