Repository avatar
Security
v1.0.0
active

garita-mcp

io.github.Garitalab5/garita-mcp

30 security tools + the Vigia agent to audit MCP servers before you connect.

Documentation

Garita MCP — servidor remoto

Esto convierte a Garita MCP de "una página que un humano abre" a "algo que un agente de IA puede llamar directamente". Expone treinta herramientas que cualquier cliente MCP puede invocar:

  • audit_mcp_server — audita el manifiesto de un servidor MCP (mismo motor probado en garita-mcp.html, Versión 4, después de 3 rondas de ataques) y devuelve un puntaje de 0 a 100.

  • simulate_approval — decide si una acción de un agente debería auto-aprobarse o quedar retenida para revisión humana.

  • detect_poisoned_tool_descriptions (Garita Escudo) — analiza el texto de la(s) descripción(es) de una herramienta MCP en busca de instrucciones escondidas o inyectadas (caracteres invisibles, esteganografía Unicode, homoglifos, entidades HTML en capas, pseudo-instrucciones ocultas, instrucciones para ocultar la acción al usuario, manipular otra herramienta, redirigir datos, o activarse recién después de la aprobación combinada con acceso a credenciales/SSH). Es el mismo motor probado en garita-tools/garita-escudo/tool.html (Versión 4, 4 rondas de ataques), portado a Node (lib/escudo.js) — mismas reglas, mismo orden de decodificación, mismo puntaje, solo devuelve JSON en vez de HTML.

  • check_known_vulnerabilities — revisa si un paquete (npm, PyPI, Go, crates.io, Maven, RubyGems, entre otros) tiene vulnerabilidades ya conocidas y publicadas, consultando la base de datos abierta OSV.dev (gratis, sin llave de API). Devuelve cada vulnerabilidad con su CVE oficial (si existe), severidad, fecha y link. A diferencia de las otras, esta depende de un servicio externo (OSV.dev) — si ese servicio falla o no responde, la llamada no descuenta ningún uso ni crédito (se revierte automáticamente, ver lib/vulnerabilidades.js y licensing.refundUse), porque el cliente no recibió ningún resultado real.

  • detect_tool_rug_pull — compara dos versiones del manifiesto de un mismo servidor MCP (la que aprobaste antes y la de ahora) y avisa si el texto de alguna herramienta ya aprobada cambió desde entonces. Detecta el patrón conocido como "MCP Tool Rug-Pull" (catalogado como ATR-2026-00581, OWASP Agentic ASI02/ASI05, MITRE ATLAS AML.T0053/T0051/T0104): una herramienta se ve benigna al aprobarse, pero su descripción se redefine DESPUÉS para meter una instrucción peligrosa. detect_poisoned_tool_descriptions revisa una sola foto en el tiempo; esta herramienta revisa si algo cambió desde la última vez — se complementan. Construida en lib/rugpull.js, reutiliza el motor de Garita Escudo para analizar lo que cambió.

  • detect_poisoned_config_files — sexta herramienta (2026-09). Analiza archivos de configuración/instrucciones que un agente de código carga y confía DE INMEDIATO, sin ningún paso de aprobación (AGENTS.md, CLAUDE.md, .cursorrules, archivos de "skills", y similares) — un canal totalmente distinto al de un manifiesto MCP, que detect_poisoned_tool_descriptions nunca mira. Motivada por un caso real de 2026 (Mitiga): un archivo de reglas envenenado exfiltró credenciales de AWS/Kubernetes/Terraform en menos de 2 minutos en una prueba controlada. Reutiliza el motor de Garita Escudo tal cual (lib/escudo.js, sin duplicar reglas), pero ajustado a este género de archivo: el lenguaje de autoridad (IMPORTANTE, CRÍTICO) no se penaliza porque es normal ahí, y se agrega una regla nueva sin gatillo temporal ("filtración de credenciales") porque, a diferencia de una herramienta MCP, un archivo de instrucciones no pasa por ningún paso de aprobación. Construida en lib/config-poison.js.

  • check_package_authenticity — séptima herramienta (2026-09). Revisa si un paquete (por ahora solo npm) tiene señales de ser un impostor recién publicado en vez de un paquete legítimo: nombre casi idéntico a uno de los paquetes más populares con muy poco historial propio (typosquatting clásico, ej. "loadash" en vez de "lodash"), publicado hace muy poco con un número de versión inicial ya "maduro" (ej. 35.x.y en vez de 0.x/1.x — el patrón documentado en una campaña real de agosto 2026 con 800-1.000+ paquetes maliciosos en npm), un script que se ejecuta solo al instalar (postinstall/preinstall) en un paquete reciente, o ausencia total de repositorio/homepage/README. Motivada por el fenómeno de 2026 conocido como "slopsquatting": un asistente de código con IA a veces alucina el nombre de un paquete que no existe, y hay campañas activas que registran esos nombres alucinados de verdad con malware adentro, apostando a que alguien lo instale sin volver a revisar. Si el paquete no existe en el registro, la herramienta avisa de ese riesgo directamente. Distinta y complementaria a check_known_vulnerabilities: esa busca CVEs ya publicados en un paquete probablemente legítimo; esta busca señales de que el paquete en sí es falso, aunque no tenga ningún CVE todavía. Construida en lib/slopsquatting.js.

  • detect_memory_poisoning — octava herramienta (2026-09). Revisa un texto que un agente con memoria de largo plazo va a guardar (o que ya guardó) en busca de instrucciones plantadas para activarse recién en una sesión futura sin relación con la conversación donde se coló el texto. Distinta de detect_poisoned_tool_descriptions: esa revisa la descripción de una HERRAMIENTA; esta revisa contenido que va HACIA la memoria — una nota, un hecho guardado, un resumen automático de una conversación vieja, o texto traído por otra herramienta (documento, web, salida de una API). Detecta instrucciones condicionales tipo "si el usuario dice que sí, entonces..." (el ataque real documentado contra Gemini por el investigador Johann Rehberger, 2025, y el método MINJA de NeurIPS 2025 con más de 95% de éxito contra agentes en producción), la combinación "recordá esto para siempre" + "no se lo menciones al usuario" (casi nunca legítima venga de donde venga), texto que se hace pasar por una instrucción del sistema, instrucciones de exfiltrar datos la próxima vez que se recupere la memoria, etiquetas falsas de sistema escondidas en el contenido, y texto que se dirige directamente al asistente por su nombre dentro de contenido que debería ser pasivo. El campo fuente pesa en el puntaje: un usuario pidiéndole directamente al agente que recuerde algo (uso normal del producto) se pondera distinto a lo mismo encontrado en un documento, un resumen automático o la salida de otra herramienta. Construida en lib/memoria.js.

  • detect_ssrf_risk — novena herramienta (2026-09). Analiza el código fuente de una herramienta que hace una petición HTTP a una URL (traer una página, un webhook, un scraper) en busca de señales de riesgo de SSRF (Server-Side Request Forgery): una llamada HTTP cuya URL depende de una entrada externa sin ninguna validación reconocible cerca, una referencia directa a una IP privada/loopback o a un endpoint de metadata de la nube (AWS/GCP/Azure — el patrón real para robar credenciales temporales) dentro de la propia llamada, verificación TLS desactivada junto con una petición externa, redirecciones seguidas automáticamente sin revalidar el destino final, y ausencia de restricción de esquema (http/https) aunque sí se valide la IP. Motivada por un censo real de 2026 sobre 9.695 servidores MCP escaneados (bex.co, "MCP Vulnerability Census"): SSRF fue el 8.5% de los 4.982 problemas encontrados (422 casos), dentro de un 60% de servidores con algún problema de seguridad — y solo el 8.5% de esos servidores usa OAuth de verdad. Es un análisis estático por patrones de texto (no ejecuta nada), mismo enfoque que Garita Escudo. Construida en lib/ssrf.js.

  • detect_path_traversal_risk — décima herramienta (2026-09). Analiza el código fuente de una herramienta que lee, escribe o borra un archivo a partir de una ruta que le pasa el agente (abrir un documento, guardar un adjunto, exportar un reporte) en busca de señales de riesgo de path traversal: una operación de archivo cuya ruta depende de una entrada externa sin ninguna validación reconocible contra secuencias de escape ("../") cerca, una referencia directa a una ruta sensible del sistema (/etc/passwd, una llave SSH, un archivo de credenciales) dentro de la propia operación, y ausencia de rechazo explícito de rutas absolutas — aunque se filtren las secuencias "../", una ruta absoluta directa puede seguir escapando del directorio permitido. Motivada por ser la categoría MÁS GRANDE de vulnerabilidades reales del censo de 2026 sobre 9.695 servidores MCP escaneados: acceso arbitrario a archivos fue el 17.7% de los 4.982 problemas encontrados (880 casos) — más grande que denegación de servicio, inyección de comandos o SSRF. Caso real: CVE-2026-40576 (CVSS 9.4, crítico) en un servidor MCP de Excel, cuya función de rutas permitía tanto rutas absolutas como secuencias "../" sin resolverlas contra el directorio permitido. Mismo enfoque de análisis estático que detect_ssrf_risk. Construida en lib/traversal.js.

  • detect_command_injection_risk — undécima herramienta (2026-09). Analiza el código fuente de una herramienta que ejecuta un comando del sistema operativo a partir de una entrada que le pasa el agente (un nombre de archivo, un argumento de búsqueda, cualquier parámetro) en busca de señales de riesgo de inyección de comandos: una llamada que SIEMPRE invoca una shell (exec, execSync, os.system, os.popen, shell_exec, passthru, system, y equivalentes) con un argumento dependiente de una entrada externa sin validación o escape reconocible cerca; una llamada que invoca una shell solo CONDICIONALMENTE (spawn/execFile de Node, subprocess.run/Popen/call de Python) únicamente cuando trae la opción shell:true/shell=True explícita — sin esa opción, un arreglo de argumentos se ejecuta directamente sin pasar por ningún intérprete de shell y no se marca como riesgo; el patrón "descargar y ejecutar" (curl/wget encadenado con una tubería directa a bash/sh); y ausencia de cualquier filtrado reconocible de metacaracteres de shell (;, &&, |, backtick, $(), >, <) — una lista de comandos permitidos que solo revisa el primer token del comando deja pasar cualquier cosa encadenada después de ese token. Motivada por ser la SEGUNDA categoría más grande de vulnerabilidades reales del censo de 2026 sobre 9.695 servidores MCP escaneados: inyección de comandos fue el 9.6% de los 4.982 problemas encontrados (476 casos) — solo detrás de acceso arbitrario a archivos. Casos reales: CVE-2026-55581/55582/55580 (CVSS hasta 8.6) en mcp-shell, cuyo "modo seguro" solo validaba el primer token del comando contra una lista blanca; y CVE-2025-6514 (CVSS 9.6, crítico) en mcp-remote. Mismo enfoque de análisis estático que detect_ssrf_risk y detect_path_traversal_risk. Construida en lib/command-injection.js.

  • detect_sql_injection_risk — duodécima herramienta (2026-09). Analiza el código fuente de una herramienta que ejecuta una consulta SQL a partir de una entrada que le pasa el agente (un nombre de usuario, un filtro de búsqueda, un identificador cualquiera) en busca de dos señales de riesgo distintas: (1) el patrón clásico de inyección — una llamada que ejecuta SQL crudo (.query, .execute, .raw, .exec_driver_sql, mysqli_query, y equivalentes) con la consulta armada por concatenación o interpolación de una variable/entrada externa, en vez de un parámetro preparado, sin ninguna función de escape reconocible cerca; y (2) un patrón propio de Garita motivado por un caso real: el código (o su comentario/descripción) afirma que la herramienta es de "solo lectura", pero no hay ninguna señal de que eso se aplique de verdad a nivel de base de datos — exactamente lo que Datadog Security Labs encontró en el servidor MCP de referencia de Postgres de Anthropic, donde la restricción de "solo lectura" vivía únicamente en el texto que lee el agente, no como un permiso real. Motivada por un censo real de 2026 sobre 9.695 servidores MCP escaneados: inyección SQL fue el 4.2% de los 4.982 problemas encontrados (211 casos). También documentado en CVE-2026-7206 (sqlite-mcp) y CVE-2025-66335 (Apache Doris MCP Server). Mismo enfoque de análisis estático que detect_ssrf_risk, detect_path_traversal_risk y detect_command_injection_risk. Construida en lib/sql-injection.js.

  • detect_token_passthrough_risk — decimotercera herramienta (2026-09). Analiza el código fuente de un middleware o herramienta MCP que maneja el token de autorización de quien lo llama, en busca del antipatrón "token passthrough" (confused deputy) que la propia especificación de MCP prohíbe explícitamente: un servidor no debe aceptar ni reenviar tokens que no fueron emitidos para él. Busca cuatro señales: (1) un middleware que deja pasar la petición (next()/call_next()) sin ninguna verificación de autorización reconocible antes — el patrón exacto detrás de CVE-2026-48039 (Meta Ads MCP, CVSS 9.1 crítico), donde un dispatch() reenviaba peticiones sin validar el header Authorization y filtraba el token de larga duración del operador; (2) el token de la petición entrante reenviado tal cual hacia otra llamada saliente, sin revalidarlo ni reemitir uno propio; (3) una verificación de JWT (jwt.verify/jwt.decode) sin validar el claim audience/aud, con lo que nada distingue un token emitido para este servidor de uno emitido para cualquier otro; y (4) un token colocado como parámetro de una URL en vez de en un header, expuesto en logs y cabeceras Referer. El mismo patrón de reenvío sin validar también aparece en CVE-2025-6514 (mcp-remote, CVSS 9.6) y CVE-2026-27826 (MCP Atlassian, CVSS 8.2). Mismo enfoque de análisis estático que detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk y detect_sql_injection_risk. Construida en lib/token-passthrough.js.

  • detect_hardcoded_secrets_risk — decimocuarta herramienta (2026-09). Analiza código fuente o un archivo de configuración (incluido el bloque env de mcpServers, o un archivo .env) en busca de credenciales escritas tal cual en texto plano en vez de venir de una variable de entorno o un gestor de secretos: (1) cadenas con el formato reconocible de una credencial real (llaves de OpenAI, AWS, GitHub, Slack, Google, o el encabezado de una llave privada PEM); (2) una variable o llave de configuración con nombre de credencial (api_key, secret, token, password…) con un valor literal en el propio código; (3) una línea al estilo .env que asigna un valor literal a una variable de entorno cuyo nombre indica una credencial; y (4) una variable de entorno con un valor de reserva ("fallback") hardcodeado, que anula el propósito de usar la variable de entorno para empezar. Motivada por un reporte real de Hush Security (septiembre 2026) que escaneó ~82.000 archivos de configuración MCP públicos en GitHub: el 12% de los espacios de credenciales tenía un secreto literal embebido, el 53% de esos con acceso a nivel de toda la organización, y el 55% sin ningún formato de token conocido. También documentado por Trend Micro (48% de 19.402 servidores MCP con almacenamiento inseguro de secretos) y catalogado como MCP01 en el OWASP MCP Top 10. Reconoce placeholders/ejemplos comunes ("your-api-key-here", "changeme", la llave de ejemplo oficial de AWS) para no marcarlos como riesgo. Mismo enfoque de análisis estático que detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk, detect_sql_injection_risk y detect_token_passthrough_risk. Construida en lib/hardcoded-secrets.js.

  • detect_insecure_deserialization_risk — decimoquinta herramienta (2026-09). Analiza el código fuente de una herramienta MCP que deserializa datos (un modelo de IA, un archivo de configuración, un objeto guardado) en busca de funciones que pueden ejecutar código arbitrario al "leer" esos datos: (1) funciones sin ninguna variante segura (pickle.load/loads, cPickle, marshal.loads, dill.loads, joblib.load, unserialize() de PHP); (2) funciones peligrosas solo si no se usa su opción segura — yaml.load() sin Loader=yaml.SafeLoader (o yaml.safe_load()), y torch.load() sin weights_only=True; y (3) un método __reduce__/__reduce_ex__ que ejecuta un comando del sistema al reconstruirse — la firma clásica de un payload malicioso de pickle. Motivada por CVE-2025-45146 (CVSS 9.8, crítico) en ModelCache, una librería de caché para agentes/LLM que llamaba a torch.load() sobre bytes sin validar; y CVE-2025-32434 (CVSS 9.3), que mostró que ni siquiera weights_only=True bastaba solo en versiones de PyTorch anteriores a la 2.6.0. Reconoce un Unpickler restringido (RestrictedUnpickler/find_class) como señal de que ya se tomó una precaución real. Mismo enfoque de análisis estático que detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk, detect_sql_injection_risk, detect_token_passthrough_risk y detect_hardcoded_secrets_risk. Construida en lib/deserialization.js.

  • detect_toxic_flow_risk — decimosexta herramienta (2026-09). A diferencia de las otras herramientas de detección, que analizan una función de código a la vez, esta analiza el MANIFIESTO completo de un servidor MCP — igual que audit_mcp_server — buscando una COMBINACIÓN peligrosa de capacidades entre varias herramientas: una que lee datos privados/sensibles (archivos locales, base de datos, credenciales, repos privados) o contenido externo no confiable (correo, páginas web, issues/tickets públicos, adjuntos), junto con una que puede enviar/publicar datos hacia afuera (correo, HTTP, webhook, crear un comentario o issue público, subir un adjunto) sin ningún campo de confirmación EXIGIDO (required) en su esquema de entrada — cada herramienta individual puede estar perfectamente descrita y no tener ningún problema por sí sola; el riesgo está en la combinación ("confused deputy" / "lethal trifecta"). Marca con más severidad el caso donde coinciden las TRES piezas completas: datos privados + contenido no confiable + canal de salida. Motivada por CVE-2026-77255 (mcp-atlassian, CVSS 8.6, septiembre 2026) — el parámetro de adjuntos de una herramienta leía cualquier archivo local y lo subía solo a un ticket de Jira —, EchoLeak/CVE-2025-32711 (Microsoft 365 Copilot, CVSS 9.3, primer exploit real de inyección de prompt de cero clics) y el caso reportado por Invariant Labs en un servidor MCP de GitHub ("Toxic Flow Analysis"). Complementa a audit_mcp_server (puntaje general del manifiesto) y a detect_poisoned_tool_descriptions (texto oculto dentro de UNA descripción) — revisa cómo INTERACTÚAN entre sí las herramientas que un agente tendría disponibles a la vez. Construida en lib/toxic-flows.js.

  • detect_ssti_risk — decimoséptima herramienta (2026-09). Analiza el código fuente de una herramienta que compila una plantilla (Jinja2, EJS, Handlebars, Pug, Mustache, lodash, o un PromptTemplate de LangChain) en busca de una fuente de plantilla que no escribió el desarrollador — una variable/entrada externa usada como el TEXTO de la plantilla, en vez de como un dato que se rellena en una plantilla fija. La mayoría de estos motores permiten llamar métodos y recorrer atributos de objetos desde dentro de la plantilla, así que una plantilla controlada por un atacante puede terminar en ejecución arbitraria de código en el servidor (SSTI) — distinto de XSS y no cubierto por ningún analizador de HTML. También detecta una falsa sensación de seguridad propia de Garita: el código afirma estar protegido porque "escapa la salida" (autoescape=True, html.escape, MarkupSafe) — una defensa real contra XSS pero irrelevante acá, porque la ejecución ocurre al COMPILAR la plantilla, antes de que exista ninguna salida que escapar. Reconoce un entorno sandboxeado de Jinja2 (SandboxedEnvironment) como una mitigación real. Motivada por CVE-2026-33154 (CVSS 8.1) en Dynaconf, una librería de configuración muy usada por apps de IA/agentes; un aviso en Agenta-AI (plataforma de evaluación de LLMs) por SSTI vía plantillas Jinja2 de evaluador personalizado; y un aviso en LangChain mismo, el framework de agentes más usado, por inyección en plantillas de prompt vía acceso a atributos. Mismo enfoque de análisis estático que detect_sql_injection_risk, detect_command_injection_risk y detect_insecure_deserialization_risk. Construida en lib/ssti.js.

  • detect_dynamic_code_risk (Escudo de Código Dinámico) — decimoctava herramienta (2026-09). Analiza el código fuente en busca de ejecución de código dinámico no confiable (CWE-95): eval(), el constructor Function() de JS, exec() de Python, y las variantes del módulo vm de Node (vm.runInContext/runInNewContext/runInThisContext) llamadas con un texto que NO escribió el desarrollador — una variable, la respuesta de un modelo, un documento recuperado de un pipeline RAG, o un parámetro de herramienta — en vez de un texto fijo. También detecta el patrón de "eval implícito": setTimeout()/setInterval() llamado con un string en vez de una referencia a función. Detecta además una falsa sensación de seguridad propia de Garita: usar la librería vm2 para "sandboxear" la ejecución no es una mitigación real — vm2 está oficialmente deprecada desde 2023 tras varias fugas de sandbox críticas y documentadas (CVE-2023-32314, CVE-2023-37903, CVE-2023-37466); reconoce isolated-vm (aislamiento real a nivel de V8 Isolate) como mitigación genuina. Motivada por CVE-2026-26030 (CVSS 9.8, feb 2026) en Microsoft Semantic Kernel: el filtro de un vector store (InMemoryVectorStore) interpolaba contenido recuperado de un documento indexado — dato envenenado de un pipeline RAG, no una entrada directa del usuario — directamente en una expresión evaluada con eval(), dando RCE completo en el proceso del agente. Mismo enfoque de análisis estático que detect_ssti_risk, y una clase de vulnerabilidad distinta de detect_command_injection_risk: ahí se invoca una shell externa (CWE-78), acá se evalúa código directamente dentro del propio intérprete/motor del agente. Construida en lib/dynamic-code.js.

  • detect_dns_rebinding_risk (Escudo de Rebinding DNS) — decimonovena herramienta (2026-09). Analiza el código que arma el transporte HTTP/SSE de un servidor MCP (el constructor StreamableHTTPServerTransport/SSEServerTransport, o el registro de la ruta /mcp) en busca de la ausencia de validación del header Origin (o Host) antes de procesar peticiones entrantes — sin esa validación, una página web maliciosa que el navegador de la víctima visita puede hacer que el navegador hable directamente con ese servidor, que suele correr en localhost, como si fuera un cliente MCP de confianza ("rebinding DNS"). Detecta además un malentendido documentado propio de Garita: creer que bindear el servidor solo a localhost/127.0.0.1 ya protege — eso NO evita el rebinding, porque el atacante registra un dominio que primero resuelve a su propio servidor y luego cambia el DNS para que resuelva a 127.0.0.1; la única defensa real es validar el header Origin contra una lista explícita. Motivada por un patrón repetido en 2026, encontrado de forma independiente en tres SDK/implementaciones de MCP en tres lenguajes distintos: CVE-2026-42559 (CVSS 8.8) en rmcp, el SDK oficial de Rust; CVE-2026-35568 en el SDK de Java; y CVE-2026-59971 en mysql-mcp-server (Python). Mismo enfoque de análisis estático que detect_ssrf_risk y detect_command_injection_risk. Construida en lib/dns-rebinding.js.

  • detect_missing_auth_risk (Centinela de Autenticación) — vigésima herramienta (2026-09). Analiza el código que arma el transporte HTTP/SSE de un servidor MCP (StreamableHTTPServerTransport/SSEServerTransport, o el registro de las rutas /mcp, /sse, /messages) en busca de la ausencia de CUALQUIER verificación de autenticación antes de despachar la petición (CWE-306) — sin login, sin llave de API, sin token, cualquiera que sepa la URL puede invocar las herramientas del servidor. Distinto de detect_dns_rebinding_risk: ahí el problema es de dónde viene la petición; acá es que no se verifica quién la hace, en absoluto. Es el patrón más repetido entre los CVEs de MCP de 2026: CVE-2026-44895 (CVSS 9.1, crítico) en un servidor MCP de GitLab, sin autenticación y con CORS totalmente abierto — cualquiera podía invocar sus 86 herramientas (incluido borrar repos) usando el token del operador; mismo patrón (CWE-306) confirmado también en Azure MCP Server (Microsoft, CVE-2026-32211), deepseek-mcp-server (CVE-2026-55605), NetLicensing-MCP (CVE-2026-54446), obsidian-web-mcp (CVE-2026-54618) y mcp-documentation-server (CVE-2026-54504). Detecta además una regla propia de Garita: cuando además de faltar la autenticación el CORS está completamente abierto (Access-Control-Allow-Origin: * o un cors() sin restringir origen), el riesgo es estrictamente peor — la combinación exacta que hizo explotable a CVE-2026-44895. Construida en lib/missing-auth.js.

  • detect_mcp_stdio_launch_risk (Escudo de Lanzamiento MCP (STDIO)) — vigésimo primera herramienta (2026-10). Analiza el código que arma una conexión de CLIENTE MCP por transporte stdio (StdioClientTransport de TypeScript, StdioServerParameters de Python) en busca de un campo command dependiente de una entrada externa sin lista de lanzadores permitidos — el sistema operativo ejecuta ese comando de inmediato al construir la conexión, ANTES de que exista ninguna validación del protocolo MCP, a diferencia de la validación de autenticación o de origen que sí ocurre en el transporte HTTP/SSE. Es una falla de diseño confirmada en 2026 en los cuatro SDKs oficiales de MCP (Python, TypeScript, Java, Rust). Busca cuatro señales: (1) un command dinámico sin ninguna validación reconocible contra una lista de lanzadores permitidos cerca; (2) una brecha de "rehidratación" — el archivo sí valida contra una lista blanca en algún lado, pero el lanzamiento que se está analizando viene de una configuración ya guardada/cargada antes, sin revalidar al momento de lanzarla de verdad (el mismo patrón detrás de CVE-2026-30623 antes de su parche); (3) un bypass vía bandera de ejecución directa — el comando SÍ está en una lista blanca razonable de lanzadores (python, node, etc.), pero sus argumentos incluyen -c/-e/--eval con un valor que no es fijo, así que el atacante no necesita elegir el comando, solo el código que ese comando ya permitido va a ejecutar; y (4) un comentario o texto que asume una falsa sensación de seguridad — "si no es un servidor MCP válido, el protocolo fallaría" — sin notar que el comando del sistema operativo ya se ejecutó antes de llegar a esa validación. Caso real: CVE-2026-30623 (LiteLLM) — un endpoint de "probar conexión" pasaba el command que mandaba el propio usuario directo al lanzador, sin restringirlo a una lista de binarios conocidos, arreglado con una lista blanca por nombre base ({npx, uvx, python, python3, node, docker, deno}). También documentado en CVE-2026-22688 (Tencent WeKnora, CVSS 9.9), mismo patrón expuesto en un endpoint /test sin control de acceso de administrador. Distinta y complementaria a detect_command_injection_risk: esa cubre inyección de comandos clásica vía shell; esta cubre la falla propia del contrato de los SDK de MCP, que existe aunque no haya ninguna shell de por medio. Construida en lib/mcp-stdio.js.

  • detect_redos_risk (Escudo Anti-ReDoS) — vigésimo segunda herramienta (2026-10). Analiza el código fuente de una herramienta/agente que compila o aplica una expresión regular en busca de (1) un patrón con forma de "cuantificador anidado" (backtracking catastrófico, ej. (a+)+, (\s*\w+)*, (a|a)*) aplicado contra una entrada que no es un texto fijo, sin ningún tope de longitud ni motor con timeout/librería segura (re2, safe-regex, recheck) reconocibles cerca — un solo string cuidadosamente armado puede colgar el proceso del agente entero (ReDoS, CWE-1333); y (2) un regex compilado dinámicamente (RegExp()/new RegExp()/re.compile()) a partir de una fuente que NO es un texto fijo que escribió el desarrollador, sino una variable — quien llame a la herramienta puede inyectar directamente un patrón catastrófico o cambiar por completo la lógica de validación. Motivada por CVE-2026-0621 (CVSS 7.5): el patrón vulnerable vivía en una sola función de validación de formato alcanzable sin autenticación, y un único request bastaba para saturar el hilo del proceso. Reconoce un regex evil envuelto directamente en el constructor de un motor seguro (new RE2(...)) como mitigación real. Mismo enfoque de análisis estático que detect_dynamic_code_risk y detect_ssti_risk. Construida en lib/redos.js.

  • detect_session_hijack_risk (Escudo de Secuestro de Sesión) — vigésimo tercera herramienta (2026-10). Analiza el código que busca o genera sesiones de un cliente en busca de (1) una sesión resuelta SOLO por el identificador que trae la petición (sessions[id]/.get(id)/.findOne({id})), sin comparar después ningún campo de dueño/principal (userId/owner/accountId) contra quien hace la petición ahora — quien consiga ese ID (adivinándolo, robándolo de un log o interceptándolo) hereda la sesión de otro cliente por completo (CWE-384); y (2) un identificador de sesión generado con poca entropía (Math.random(), Date.now()/time.time() solo, o un contador incremental) en vez de un generador criptográficamente seguro (crypto.randomBytes/randomUUID, secrets.token_hex), adivinable por fuerza bruta. Reconoce una comparación explícita de dueño, o un token firmado y verificado (jwt.verify, crypto.timingSafeEqual), como vínculo real; y distingue una búsqueda de lectura (riesgosa) de una escritura que CREA la sesión (sessions[id] = {...}, no riesgosa por sí sola). El mismo patrón detrás de CVE-2026-52869. Mismo enfoque de análisis estático que detect_missing_auth_risk y detect_token_passthrough_risk. Construida en lib/session-hijack.js.

  • detect_oauth_audience_confusion_risk (Escudo de Confusión de Audiencia OAuth) — vigésimo cuarta herramienta (2026-10). Analiza el VERIFICADOR PROPIO de tokens OAuth/JWT de un servidor con más profundidad que detect_token_passthrough_risk (que solo mira si "audience"/"aud" aparece cerca, una señal superficial): detecta cuando esa validación SÍ existe pero está rota de forma sutil — (1) condicionada a una bandera de configuración (config.checkAudience, options.strictMode) que puede estar desactivada; (2) su rama de "no coincide" solo registra una advertencia en vez de rechazar la petición (sin throw/return/res.status); o (3) un bloque catch() silencia el error que la librería ya lanzó al detectar la discrepancia — y también la ausencia total de cualquier chequeo de audiencia. En los tres primeros casos el código "tiene" una validación que un lector apurado asumiría que funciona, pero que en la práctica deja pasar un token emitido para otro servidor (confused deputy vía audiencia). El mismo patrón detrás de CVE-2026-14541. Mismo enfoque de análisis estático que detect_token_passthrough_risk y detect_missing_auth_risk. Construida en lib/oauth-audience.js.

  • detect_unbounded_allocation_risk (Escudo de Asignación sin Límite) — vigésimo quinta herramienta (2026-10). Analiza el código en busca de agotamiento de memoria/CPU (CWE-770): (1) lectura completa de un cuerpo de petición o un archivo hacia memoria sin ningún tope de tamaño configurado (sin limit en express.json()/bodyParser, sin chequeo de tamaño en la acumulación manual de un stream req.on('data'), o sin fs.statSync() antes de leer un archivo con ruta no fija); y (2) una reserva de array/buffer (new Array()/Buffer.alloc()), o un bucle, cuyo tamaño/cantidad de vueltas viene directamente de una variable sin ningún tope (Math.min/comparación contra un máximo) antes — un solo mensaje o número grande puede agotar la memoria o la CPU del proceso del agente. El mismo patrón detrás de CVE-2026-14539. Mismo enfoque de análisis estático que detect_dynamic_code_risk y detect_ssrf_risk. Construida en lib/unbounded-allocation.js.

  • detect_cross_client_leak_risk (Escudo de Fuga Entre Clientes) — vigésimo sexta herramienta (2026-10). Analiza el código que arma el transporte HTTP de un servidor MCP en busca de (1) una instancia de McpServer/Server declarada a nivel de MÓDULO (fuera de cualquier handler de ruta) y reutilizada dentro de un handler junto con StreamableHTTPServerTransport — el mismo servidor compartido entre conexiones de distintos clientes puede filtrar estado/respuestas de un cliente hacia otro; y (2) estado mutable (let/var) declarado a nivel de módulo y referenciado dentro de un callback de registerTool/tool — cualquier variable que persiste entre peticiones ahí es, en los hechos, estado compartido entre clientes que no debería existir. Motivada por CVE-2026-25536 (CVSS 7.1) en el SDK oficial de TypeScript de MCP (versiones v1.10.0–v1.25.3): reutilizar una sola instancia de McpServer con StreamableHTTPServerTransport entre clientes hacía que el estado de respuesta de un cliente se filtrara hacia otro — catalogado como MCP10 ("Context Injection and Over Sharing") en el OWASP MCP Top 10. Distingue, con un cálculo de rangos de handlers, una instancia/variable realmente a nivel de módulo de una creada de nuevo dentro de cada handler (segura). Construida en lib/cross-client-leak.js.

  • detect_sampling_hijack_risk (Escudo de Secuestro de Sampling) — vigésimo séptima herramienta (2026-10). Analiza el código del lado CLIENTE/HOST que maneja peticiones de sampling entrantes de un servidor MCP (setRequestHandler(CreateMessageRequestSchema, ...) o el método literal 'sampling/createMessage') — la función de MCP que deja que un SERVIDOR le pida al modelo del CLIENTE que genere una completion, no al revés. Busca (1) una petición de sampling cumplida sin ningún paso reconocible de revisión/aprobación humana antes de mandarle el contenido al modelo, aunque la propia especificación de MCP recomienda ese paso; (2) invocación encubierta de herramientas — el mismo handler llama a callTool/executeTool a partir de la completion generada, sin aprobación explícita de la persona, el vector más grave; y (3) ausencia de un tope de longitud/tokens (maxTokens/max_tokens), que permite gastar cómputo/créditos de más sin que la persona lo note ("robo de recursos"). Documentado en una investigación de Unit42 (Palo Alto Networks) reportada de nuevo el 16 de octubre de 2026 contra una app de tipo copiloto de código, demostrando los tres vectores: robo de recursos, secuestro de conversación e invocación encubierta de herramientas. Mismo enfoque de análisis estático que detect_toxic_flow_risk y detect_missing_auth_risk. Construida en lib/sampling-hijack.js.

  • detect_output_schema_ssrf_risk (Escudo de Esquema de Salida) — vigésimo octava herramienta (2026-10). Analiza el código del lado CLIENTE que valida el outputSchema/inputSchema de una herramienta MCP con la librería jsonschema de Python, en busca de (1) una validación (jsonschema.validate/Draft*Validator/validator_for) sobre un esquema que vino de un servidor MCP no confiable, sin ningún Registry/Resolver que restrinja la resolución de referencias externas ($ref/$dynamicRef/$id) — un servidor malicioso puede forzar al cliente a hacer una petición SSRF hacia una URL arbitraria (CWE-918); y (2) una llamada de red SÍNCRONA (urllib.request.urlopen/requests.get-post-put-delete) dentro de una función async def, sin timeout ni delegarse a un hilo aparte (asyncio.to_thread/run_in_executor) — un único endpoint "tarpit" que nunca responde congela el event loop entero del proceso, con todas sus tareas y sesiones concurrentes (denegación de servicio). Motivada por CVE-2026-116686 (CVSS 6.5, CWE-918) en el SDK oficial de Python de MCP (paquete mcp en PyPI, versiones 1.10.0-1.29.1 y 2.0.0-2.1.1; parchado en 1.30.0/2.2.0 resolviendo referencias solo dentro del propio documento). Mismo enfoque de análisis estático que detect_ssrf_risk y detect_redos_risk. Construida en lib/output-schema-ssrf.js.

  • detect_excessive_agency_risk (Escudo de Agencia Excesiva) — vigésimo novena herramienta (2026-10). A diferencia de las herramientas que analizan código fuente, esta analiza el MANIFIESTO de un servidor MCP — igual que audit_mcp_server y detect_toxic_flow_risk, pero mirando una sola herramienta a la vez — en busca de "agencia excesiva" (OWASP LLM06): una herramienta cuyo nombre o descripción indica una acción irreversible o de alto valor (transferir, retirar, pagar, borrar, eliminar, apagar) sin ningún campo de confirmación EXIGIDO (required) en su esquema de entrada, y/o sin ningún tope máximo (maximum/exclusiveMaximum) en un campo de monto/cantidad — nada impide que una sola llamada mueva una cantidad arbitrariamente grande ni que se ejecute sin que nada la revise antes. Motivada directamente por el hackeo de Binance de octubre de 2026 (6.300 millones de dólares, el mayor robo cripto de la historia): según el relato preliminar de la propia Binance y el análisis de TRM Labs, un solo dispositivo/credencial comprometido alcanzó un sistema con autoridad para autorizar retiros, y pudo ordenarlos sin ninguna aprobación independiente ni tope por operación — el mismo patrón de diseño que esta herramienta busca en el esquema de entrada de una herramienta MCP, antes de que un incidente así ocurra con un agente de IA de por medio. Misma convención de "gatillo real vs. afirmación de texto" que detect_toxic_flow_risk: una herramienta separada de "pedir aprobación" no cuenta como mitigación real. Construida en lib/excessive-agency.js.

  • detect_call_spoofing_risk (Escudo de Suplantación de Llamada) — trigésima herramienta (2026-10). Analiza el código de ORQUESTACIÓN del lado del AGENTE (la capa que interpreta la respuesta del modelo) en busca de la extracción de llamadas a herramientas desde el TEXTO LIBRE de la respuesta (una marca como TOOL_CALL:, un bloque ```json, una etiqueta <tool_call>) en vez de leerlas únicamente del campo ESTRUCTURADO y dedicado de la API (tool_calls/function_call/tool_use), que solo se llena cuando el modelo invocó de verdad el mecanismo nativo de function-calling. El problema: ese texto libre puede contener cualquier cosa que haya llegado al contexto del modelo — un documento cargado, una página web, el resultado de una herramienta anterior — y si ese contenido ya tiene algo con pinta de llamada a herramienta y el modelo simplemente lo "repite" (porque se le pidió resumir, citar o traducir ese contenido), el orquestador no tiene manera de distinguir un patrón repetido de una decisión real del modelo. Este es el ataque "Repeat-After-Me", documentado en una investigación de GBHackers de octubre de 2026 contra 6 frameworks de agentes de uso extendido — LangGraph, Microsoft Agent Framework, Google ADK 2.0, AutoGen, AWS Strands y CrewAI — en los 6, la capa de orquestación confiaba en un parseo de texto/regex de la salida del modelo en vez de exigir la API de function-calling estructurada. Mismo enfoque de análisis estático por patrones de texto que detect_sampling_hijack_risk. Construida en lib/call-spoofing.js.

Las treinta herramientas requieren una llave de acceso (con usos gratis y luego créditos comprados) — ver la sección "Cobro con llave de acceso" más abajo. Las páginas web (garita-mcp.html, garita-escudo/tool.html) siguen siendo gratis e ilimitadas, esto solo aplica a este servidor.

Antes de empezar: qué es distinto de la página web

La página web (garita-mcp.html) la abre una persona en el navegador y funciona sola, sin nada que mantener corriendo. Esto es distinto: es un programa que tiene que quedar encendido todo el tiempo en algún servidor con una dirección pública (una URL), para que otros sistemas lo puedan llamar por internet. Eso implica cosas nuevas que la página no necesitaba:

  1. Hay que "publicarlo" en un servicio de hosting (Render, gratis, ver abajo).
  2. Necesita una base de datos pequeña para recordar las llaves de acceso y sus créditos entre reinicios (Upstash, gratis, ver abajo).
  3. Para cobrar créditos de verdad necesita una cuenta de CoinGate (la misma que ya elegiste para Garita Labs).
  4. Vas a necesitar cuentas de GitHub, Render, Upstash y CoinGate — todas tienen plan gratis y ninguna pide tarjeta de crédito para lo que necesitamos, excepto CoinGate cuando actives el modo real (no el de pruebas).

Paso a paso para publicarlo (usando Render, gratis, sin tarjeta)

1. Crea una cuenta de GitHub (si no tienes una ya): entra a github.com, "Sign up", sigue los pasos con tu correo.

2. Sube esta carpeta a un repositorio nuevo:

  • En github.com, dale a "New repository" (botón verde).
  • Ponle un nombre, por ejemplo garita-mcp-server. Puede ser privado o público, no importa.
  • Sigue las instrucciones de GitHub para "upload existing files" (subir archivos existentes) y arrastra ahí todos los archivos de esta carpeta (server.js, package.json, la carpeta lib/, este README.md, y el .gitignore — no subas la carpeta node_modules si la ves, no hace falta; tampoco hace falta subir los test-*.js, aunque no pasa nada si los subes).

3. Crea una cuenta en Render: entra a render.com, "Get Started", puedes registrarte con tu cuenta de GitHub directamente (más fácil, un solo clic).

4. Crea el servicio:

  • En el panel de Render, "New +" → "Web Service".
  • Conecta el repositorio garita-mcp-server que acabas de subir.
  • Render va a detectar que es Node.js solo. Déjalo con los valores que proponga (Build command: npm install, Start command: npm start).
  • Elige el plan Free.
  • Todavía no le des a "Create Web Service" — primero baja a la sección "Environment Variables" en esta misma pantalla y sigue el siguiente paso, para que arranque ya configurado.

Cobro con llave de acceso (usos gratis + créditos comprados)

Cada cliente recibe una llave de acceso (un texto largo que empieza con gar_). Las primeras 5 llamadas son gratis por llave — de una sola vez, nunca se renuevan — y después de eso, cada llamada a cualquiera de las treinta herramientas (audit_mcp_server, simulate_approval, detect_poisoned_tool_descriptions, check_known_vulnerabilities, detect_tool_rug_pull, detect_poisoned_config_files, check_package_authenticity, detect_memory_poisoning, detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk, detect_sql_injection_risk, detect_token_passthrough_risk, detect_hardcoded_secrets_risk, detect_insecure_deserialization_risk, detect_toxic_flow_risk, detect_ssti_risk, detect_dynamic_code_risk, detect_dns_rebinding_risk, detect_missing_auth_risk, detect_mcp_stdio_launch_risk, detect_redos_risk, detect_session_hijack_risk, detect_oauth_audience_confusion_risk, detect_unbounded_allocation_risk, detect_cross_client_leak_risk, detect_sampling_hijack_risk, detect_output_schema_ssrf_risk, detect_excessive_agency_risk, detect_call_spoofing_risk) consume un crédito. Cuando se acaban los créditos, el servidor responde con un mensaje explicando cómo comprar más — nunca deja pasar una llamada sin cobrar cuando corresponde. Excepción: si check_known_vulnerabilities o check_package_authenticity fallan porque el servicio externo que consultan (OSV.dev o el registro de npm) no respondió, ese uso/crédito se devuelve solo — no es justo cobrarle al cliente por una falla que no es suya.

Aparte de eso hay un tope diario de 50 llamadas por llave (constante DAILY_CALL_LIMIT en lib/licensing.js, fácil de subir o bajar), que aplica incluso si la llave tiene créditos de sobra — es una protección aparte, pensada para que un agente con un error en bucle no se gaste de golpe todos los créditos comprados en minutos. Se resetea solo cada día, sin que tengas que hacer nada.

El paquete empresarial (ver tabla de paquetes abajo) es la excepción: además de sumar créditos, marca la llave para siempre como exenta de ese tope diario (unlimitedDaily, en lib/licensing.js) — pensado para un cliente cuyos agentes llaman las herramientas en volumen alto y constante, donde el tope de 50/día se volvería una limitación real del negocio en vez de una protección contra abuso. Una vez otorgado, no hay forma de quitarlo desde el código (ni siquiera si después se le acaban los créditos) — solo se otorga comprando ese paquete, o a mano desde Upstash (ver más abajo).

Esto necesita dos cosas configuradas en el servidor: un lugar donde recordar las llaves y sus créditos (Upstash), y la conexión con CoinGate para procesar los pagos.

5. Crea una base de datos gratis en Upstash (para recordar las llaves y créditos)

Sin esto, el servidor "olvida" todas las llaves y créditos cada vez que se reinicia o se duerme — inaceptable para cobrar de verdad, así que este paso no es opcional.

  1. Entra a upstash.com y crea una cuenta gratis (puedes usar tu cuenta de GitHub).
  2. En el panel, crea una base de datos nueva: "Create Database" → dale un nombre (ej. garita-licencias) → tipo Redis → elige la región más cercana a donde esté tu servidor de Render → plan Free.
  3. Dentro de la base de datos ya creada, busca la sección "REST API" (o "Connect" → "REST API"). Ahí vas a ver dos valores que necesitas copiar:
    • UPSTASH_REDIS_REST_URL
    • UPSTASH_REDIS_REST_TOKEN

6. Crea tu cuenta de CoinGate y saca el token de la API

Si ya tienes cuenta de CoinGate de cuando la elegimos para Garita Labs, puedes reusarla.

  1. Para probar primero SIN dinero real: crea una cuenta en sandbox.coingate.com (es una copia de pruebas, separada de la cuenta real).
  2. En el panel de esa cuenta, busca "API Apps" o "Integrations" → crea una App nueva → ahí te da un API Token. Ese es tu COINGATE_API_TOKEN de pruebas.
  3. Cuando quieras cobrar dinero real, repite el mismo proceso pero en coingate.com (cuenta real, verificación de identidad incluida) y usa ese otro token en su lugar — son dos cuentas y dos tokens completamente separados, no se mezclan.
  4. En esa misma App, en la configuración de "Callbacks" o "Webhooks", asegúrate de que el formato esté puesto en JSON (no form-encoded) — el servidor espera ese formato.

7. Configura las variables de entorno en Render

De vuelta en la pantalla de creación del servicio en Render (o en "Environment" si ya lo creaste), agrega estas variables:

VariableValor
UPSTASH_REDIS_REST_URLel que copiaste de Upstash
UPSTASH_REDIS_REST_TOKENel que copiaste de Upstash
COINGATE_API_TOKENel token de tu App de CoinGate (sandbox al probar, real cuando ya quieras cobrar de verdad)
COINGATE_ENVsandbox mientras pruebas, live cuando ya cobres de verdad
PUBLIC_BASE_URLla URL pública que te va a dar Render, ej. https://garita-mcp-server.onrender.com (si no la sabes todavía, puedes dejarla vacía y agregarla después de que Render te dé la URL — sin esta variable el servidor adivina la URL sola, pero es más confiable ponerla a mano)
ANTHROPIC_API_KEYsolo si quieres activar Vigía (ver la sección "Vigía" más abajo) — tu propia llave de la API de Anthropic, no la del cliente. Sin esta variable, el resto del servidor (las 30 herramientas vía /mcp) funciona exactamente igual; solo /vigia/analizar responde 503 avisando que falta configurarla.
VIGIA_MODELopcional — qué modelo de Claude usa Vigía (por defecto claude-sonnet-4-5-20250929). Cámbialo si Anthropic libera un modelo más nuevo/barato, sin tocar código.

Dale a "Create Web Service" (o guarda las variables si ya lo habías creado — Render lo reinicia solo).

8. Espera unos minutos. Cuando termine, te va a dar una URL parecida a https://garita-mcp-server.onrender.com. Si pusiste PUBLIC_BASE_URL antes de saber la URL final, entra otra vez a "Environment" y corrígela para que coincida exactamente, luego guarda (Render se reinicia solo).

9. Prueba que funciona: abre esa URL en el navegador — deberías ver la lista de endpoints. Si ves eso, ya está publicado.

Paquetes de créditos y precios

Definidos en lib/coingate.js, se pueden ajustar ahí cuando quieras:

PaqueteCréditosPrecioExtra
basico50 usos5 USD
pro300 usos25 USD
empresarial5.000 usos300 USDquita el tope diario de 50 usos/día para siempre en esa llave

CoinGate cobra su comisión (1%) sobre el precio — no está restada en la tabla de arriba, es lo que paga el cliente.

Cómo consigue un cliente su llave y compra créditos

  1. Conseguir una llave gratis: POST https://tu-servidor.onrender.com/crear-llave (sin cuerpo). Devuelve la llave y le avisa que la guarde — no se puede recuperar después si la pierde (tocaría crear una nueva, empezando de cero con otros 5 usos gratis).
  2. Usarla: al conectar el servidor MCP, manda el header Authorization: Bearer gar_... con esa llave.
  3. Consultar cuánto le queda: GET https://tu-servidor.onrender.com/consultar-llave?apiKey=gar_... — devuelve usos gratis, créditos, y cuántos usos lleva hoy contra el tope diario.
  4. Comprar créditos cuando se acaben: POST https://tu-servidor.onrender.com/comprar-creditos con cuerpo { "apiKey": "gar_...", "pack": "basico" } (o "pro", o "empresarial" para quitar además el tope diario). Devuelve un payment_url de CoinGate (el cliente paga ahí, con cripto) y un orderId — en cuanto CoinGate confirma el pago, el servidor acredita los créditos solo, sin que tengas que hacer nada manualmente.

Si el pago tarda en confirmarse

Con cripto es normal que la confirmación tarde — desde un par de minutos hasta más, según qué tan congestionada esté la red de esa moneda en ese momento. Eso no es un error de nada: mientras tanto, la llave sigue sin créditos hasta que se confirme.

CoinGate avisa solo en cuanto se confirma (el webhook), y si por lo que sea nuestro servidor no llega a recibir ese aviso a la primera (por ejemplo, si Render estaba "dormido" en el plan gratis), CoinGate reintenta avisar automáticamente durante varios días — así que casi nunca debería perderse un pago confirmado.

Si un cliente escribe preguntando "ya pagué, ¿por qué no me llegaron los créditos?", puedes revisar el estado real en el momento (sin esperar el próximo reintento) con: GET https://tu-servidor.onrender.com/verificar-pago?orderId=EL_ORDERID_QUE_DEVOLVIÓ_/comprar-creditos. Si CoinGate ya confirmó el pago, esto lo acredita ahí mismo; si todavía está "confirmando", te lo dice y no hace falta hacer nada más que esperar.

Emitir una llave a mano (por ejemplo, para un cliente que te escribió directo)

Si quieres regalarle créditos a alguien sin pasar por CoinGate (una cortesía, una prueba extendida), puedes hacerlo llamando directamente a la base de datos de Upstash desde su panel web (pestaña "Data Browser" o "CLI"), con el comando:

SET garita:key:gar_LO-QUE-SEA {"freeUsesRemaining":0,"credits":100,"createdAt":"2026-01-01T00:00:00.000Z"}

(cambia gar_LO-QUE-SEA por una llave que tú inventes y le mandes al cliente, y 100 por los créditos que quieras regalarle). Para regalar también la condición "empresarial" (sin tope diario), agrega "unlimitedDaily":true al mismo JSON.

Cómo lo conecta un agente

Cualquier cliente MCP (Claude, u otro) se conecta agregando esta URL como un "servidor MCP remoto" (a veces llamado "conector"), apuntando a https://tu-servicio.onrender.com/mcp, mandando el header Authorization: Bearer <llave> con una llave conseguida en /crear-llave. Una vez conectado, el agente ve las treinta herramientas (audit_mcp_server, simulate_approval, detect_poisoned_tool_descriptions, check_known_vulnerabilities, detect_tool_rug_pull, detect_poisoned_config_files, check_package_authenticity, detect_memory_poisoning, detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk, detect_sql_injection_risk, detect_token_passthrough_risk, detect_hardcoded_secrets_risk, detect_insecure_deserialization_risk, detect_toxic_flow_risk, detect_ssti_risk, detect_dynamic_code_risk, detect_dns_rebinding_risk, detect_missing_auth_risk, detect_mcp_stdio_launch_risk, detect_redos_risk, detect_session_hijack_risk, detect_oauth_audience_confusion_risk, detect_unbounded_allocation_risk, detect_cross_client_leak_risk, detect_sampling_hijack_risk, detect_output_schema_ssrf_risk, detect_excessive_agency_risk y detect_call_spoofing_risk) y las puede llamar solo, sin que una persona abra nada — cada llamada consume un uso gratis o un crédito automáticamente, y el propio mensaje de error le explica al agente (o a quien lo esté configurando) cómo conseguir más si se acaban.

Vigía — el agente especializado (Escalón 1 / "Centinela Básico")

POST /vigia/analizar es un servicio distinto de /mcp: en vez de exponer las 30 herramientas sueltas para que un agente externo decida cuál llamar, expone un agente PROPIO de Garita Labs (llamado "Vigía" — no "Centinela", para no chocar con el nombre comercial de la herramienta 20, "Centinela de Autenticación") que decide él mismo cuáles de las 30 herramientas usar sobre lo que el cliente le mande, combina los resultados, y responde en español, en lenguaje llano, con un informe priorizado y recomendaciones de corrección. Pensado para un cliente sin perfil técnico de seguridad, o para integrarlo directo en un flujo (un bot, un pipeline de CI/CD) sin tener que orquestar las 30 herramientas a mano.

Cómo se llama:

POST https://tu-servidor.onrender.com/vigia/analizar
Content-Type: application/json
Authorization: Bearer gar_... (o mandá "apiKey" en el cuerpo)

{ "mensaje": "Revisá este código: ..." }

Devuelve:

{
  "informe": "...(el análisis en español, listo para mostrarle al cliente)...",
  "herramientasUsadas": [ { "herramienta": "detect_command_injection_risk", "entrada": {...}, "ok": true }, ... ],
  "licenciaAgotada": false,
  "vueltas": 2
}

Principio de diseño (acordado explícitamente con el negocio): Vigía nunca modifica ni aplica cambios directamente sobre el código o los sistemas del cliente, ni aunque se lo pidan explícitamente — solo analiza, explica y sugiere la corrección. Aplicar un cambio con aprobación humana de por medio queda reservado para un escalón futuro ("Centinela Enterprise").

Cómo se cobra: cada herramienta real que Vigía decide llamar se cobra exactamente igual que si el cliente la hubiera llamado directo por /mcp — mismo licensing.checkAndConsume()/refundUse(), sin un sistema de cobro paralelo. Lo que todavía no se cobra por separado es el costo de los tokens de Claude que usa el propio Vigía para razonar (decidir qué llamar y redactar el informe) — eso lo está absorbiendo Garita Labs por ahora, mientras se decide cómo medirlo/cobrarlo (una suscripción mensual aparte es la idea que se viene barajando). Hay que decidir esto antes de ofrecer Vigía a un volumen grande de clientes, para no operar a pérdida.

Requisito para que funcione: la variable de entorno ANTHROPIC_API_KEY tiene que estar configurada en Render (ver la tabla de variables más arriba) — es la llave de Anthropic de Garita Labs, no la del cliente. Sin ella, el endpoint responde 503 con un mensaje claro en vez de romperse; el resto del servidor sigue funcionando normal.

Límites de seguridad incluidos: un tope de 6 "vueltas" de razonamiento+herramientas por pedido (para no dejar que el agente se quede dando vueltas sin terminar, y por costo), un tope de 20.000 caracteres en el "mensaje" de entrada, y si la licencia del cliente se agota a mitad del análisis, se corta ahí mismo y se le avisa en vez de seguir intentando (y fallando) sin parar.

Una cosa a tener en cuenta con el plan gratis de Render

El plan gratis de Render "duerme" el servicio después de 15 minutos sin uso, y tarda como un minuto en despertar cuando llega la próxima llamada. Para un uso moderado está perfectamente bien; si esto se vuelve algo que se usa todo el tiempo, ahí sí conviene pasar a un plan pago para que no "duerma".

Probar todo localmente antes de subirlo (opcional, para verificar cambios)

npm install
node server.js

Sin las variables de Upstash configuradas, el servidor arranca en un modo de memoria (avisa con una advertencia bien visible) — sirve para probar el flujo completo sin gastar nada, pero se le olvida todo al reiniciarse. Con el servidor corriendo:

  • node test-heuristics.js — prueba el motor de reglas en sí (sin servidor). Incluye la ronda 5 de ataques (2026-09), propia de este puerto a servidor: notación científica como string, lista de invisibles ampliada, y destructiveHint: false mintiendo sobre una herramienta destructiva.
  • node test-licensing.js — prueba el ciclo completo de una llave: usos gratis, agotamiento, tope diario, compra simulada, webhook, créditos, sin llamar a CoinGate de verdad.
  • node test-verificar-pago.js — prueba el respaldo manual de /verificar-pago (pago que tarda, se confirma después, y no se duplica), simulando las respuestas de CoinGate sin llamarlo de verdad.
  • node test-client.js — se conecta como lo haría un agente real: pide una llave, llama las dos herramientas, y agota los usos gratis para ver el mensaje de "compra más créditos".
  • node test-escudo.js — prueba el motor de Garita Escudo (sin servidor), reutilizando los casos de las 4 rondas de ataques ya hechas contra la versión de navegador, más una 5ª ronda (2026-09) contra la regla gatillo_diferido: exfiltración con curl/wget sin tubería y scp/rsync a host remoto, y dos frases-gatillo en español que faltaban.
  • node test-vulnerabilidades.js — prueba el parseo de respuestas de OSV.dev (severidad, CVE, orden, truncado, errores) con un fetch simulado — no depende de tener salida a internet ni de que el contenido de OSV.dev no cambie. Incluye una ronda de ataques de robustez (2026-09): registros malformados que antes reventaban la herramienta entera, y topes de tamaño en el resumen y en la cantidad de resultados.
  • node test-rugpull.js — prueba el detector de rug-pull: ataque real (instrucción diferida + ssh/exfiltración), cambio benigno de redacción, sin cambios, herramienta nueva, herramienta eliminada, un caso mixto con las cuatro categorías a la vez, y una ronda de ataques (2026-09) contra su propia lógica de comparación: renombrar la herramienta comprometida entre revisiones, y un nombre de herramienta duplicado en el manifiesto.
  • node test-config-poison.js — prueba el detector de archivos de configuración/instrucciones envenenados (sexta herramienta, 2026-09): verifica que el lenguaje de autoridad NO se penalice en este género de archivo, que la regla nueva de filtración de credenciales dispare sin necesitar gatillo temporal (en ambos órdenes, y con pronombres enclíticos en español — "léelo y envíalo" — encontrado como evasión real durante la construcción y ya corregido), que una instrucción defensiva en español ("nunca lo muestres") NO dispare por la diferencia de conjugación, documenta como límite conocido que la misma defensa en inglés SÍ puede disparar un falso positivo, y confirma que el resto del motor de Garita Escudo (invisibles, homoglifos, etiquetas ocultas, gatillo diferido) se reutiliza tal cual dentro de este archivo.
  • node test-slopsquatting.js — prueba el verificador de autenticidad de paquetes (séptima herramienta, 2026-09): paquete inexistente (avisa de alucinación + riesgo de squat futuro), typosquat clásico (nombre a 1 edición de un paquete popular con poco historial, con su control de que un nombre parecido pero YA establecido no se marca), el patrón de "slopsquatting" documentado en 2026 (recién publicado + versión inicial anómala tipo 35.x.y, con su control de que un paquete nuevo con versión 0.x/1.x normal no dispara la regla fuerte), script de instalación automática en un paquete reciente (con su control de que el mismo script en un paquete viejo no se penaliza), y ausencia total de repositorio/homepage/README. La mayoría usa un fetch simulado del registro de npm; un puñado de casos confirmados aparte contra la API real (left-pad, chalkk, loadash — este entorno sí tiene salida a registry.npmjs.org, a diferencia de api.osv.dev).
  • node test-memoria.js — prueba el detector de envenenamiento de memoria (octava herramienta, 2026-09): la combinación crítica de persistencia + secreto ("recordalo para siempre" + "no se lo digas al usuario"), el gatillo condicional documentado en el ataque real contra Gemini (Rehberger, 2025), suplantación de autoridad del sistema, exfiltración programada para la próxima recuperación de memoria, etiquetas falsas de sistema escondidas en el contenido, y una batería de casos negativos que confirman que el uso normal del producto — un usuario pidiéndole directamente al agente que recuerde una preferencia, aunque sea "para siempre" — nunca se marca como riesgo.
  • node test-ssrf.js — prueba el detector de riesgo de SSRF (novena herramienta, 2026-09): llamada HTTP con URL sin validar (en JS y en Python), IP de metadata de la nube o loopback hardcodeada dentro de la propia llamada, verificación TLS desactivada junto con una petición externa, redirecciones seguidas sin revalidar el destino, ausencia de restricción de esquema, y una batería de casos negativos — URL fija, validación por lista de hosts permitidos + esquema, uso de una librería conocida contra SSRF, código sin ninguna llamada HTTP, y un chequeo defensivo que solo MENCIONA una IP de metadata para bloquearla (no debe marcarse como si la estuviera llamando).
  • node test-traversal.js — prueba el detector de riesgo de path traversal (décima herramienta, 2026-09): operación de archivo con ruta sin validar (en JS y en Python), el patrón exacto del CVE real de un servidor MCP de Excel (CVE-2026-40576, CVSS 9.4), referencia directa a /etc/passwd o a una llave SSH dentro de la propia operación, validación contra "../" sin rechazar rutas absolutas, y una batería de casos negativos — ruta fija, validación completa (rechazo de rutas absolutas + path.resolve comparado contra el directorio base), uso de path.basename para quedarse solo con el nombre de archivo, uso de secure_filename de Werkzeug/Flask, y código sin ninguna operación de archivo.
  • node test-command-injection.js — prueba el detector de riesgo de inyección de comandos (undécima herramienta, 2026-09): comando armado por concatenación (en JS y en Python), template literal interpolado, spawn/execFile con shell:true explícito y un comando variable, el patrón exacto de CVE-2026-55581 (lista de comandos permitidos que solo revisa el primer token), el patrón "descargar y ejecutar" (curl | bash), y una batería de casos negativos — comando fijo, subprocess.run/execFile con arreglo de argumentos sin shell=True (la forma segura), escapado con shlex.quote, y una lista de permitidos completa combinada con filtrado de metacaracteres.
  • node test-sql-injection.js — prueba el detector de riesgo de inyección SQL (duodécima herramienta, 2026-09): consulta armada por concatenación (en JS y en Python, incluido un f-string interpolado), un nombre de tabla interpolado directo en la consulta, el patrón exacto encontrado por Datadog Security Labs (afirma "solo lectura" sin ninguna aplicación real), y una batería de casos negativos — consulta parametrizada ($1, %s con tupla), escapado con connection.escape(), y un "solo lectura" real respaldado por SET TRANSACTION READ ONLY.
  • node test-token-passthrough.js — prueba el detector de riesgo de reenvío de tokens OAuth (decimotercera herramienta, 2026-09): middleware Express/FastAPI que deja pasar la petición sin verificar autorización (patrón CVE-2026-48039), reenvío directo del header Authorization entrante hacia una llamada saliente, un token capturado en variable y reenviado sin reemitir uno propio, jwt.verify sin validar audience, un token expuesto como parámetro de URL, y una batería de casos negativos — middleware con verificación explícita antes de next(), token reemitido vía exchangeToken() antes de reenviarlo, jwt.verify con audience validado, y una llamada saliente con el token de servicio propio en vez del header entrante.
  • node test-hardcoded-secrets.js — prueba el detector de secretos embebidos en texto plano (decimocuarta herramienta, 2026-09): una API key de OpenAI con formato reconocible, una llave de acceso de AWS, un bloque env de configuración MCP con un token literal (patrón exacto del reporte de Hush Security), una línea .env con contraseña, una llave privada PEM pegada en el código, un valor de reserva hardcodeado en process.env.X || '...', y una batería de casos negativos — llave leída de una variable de entorno, referencia ${...} en config MCP, placeholders comunes ("your-api-key-here", "changeme"), y la llave de ejemplo oficial de AWS (que contiene "EXAMPLE").
  • node test-deserialization.js — prueba el detector de deserialización insegura (decimoquinta herramienta, 2026-09): pickle.loads sobre bytes de una petición, torch.load sin weights_only=True (patrón CVE-2025-45146/ModelCache), yaml.load sin Loader seguro, unserialize() de PHP sobre $_POST, un método __reduce__ con os.system (payload de pickle), y una batería de casos negativos — yaml.safe_load, yaml.load con Loader=yaml.SafeLoader, torch.load con weights_only=True, un RestrictedUnpickler/find_class, y json.loads (que no deserializa objetos, solo datos).
  • node test-toxic-flows.js — prueba el detector de flujos tóxicos (decimosexta herramienta, 2026-09): el patrón mcp-atlassian (leer un archivo local + subir un adjunto sin aprobación), el patrón EchoLeak (correo no confiable + calendario privado + renderizado automático → trifecta completa), el patrón Invariant Labs/GitHub (issue público + repo privado + crear comentario → trifecta completa), una sola herramienta que combina ambas capacidades a la vez, el efecto de varias herramientas de salida sin aprobar, un campo de aprobación EXIGIDO en el esquema (required) que sí mitiga, ese mismo campo presente pero NO exigido (que no mitiga), y una batería de casos negativos — solo lectura, solo salida, list_comments/get_comments que no se confunden con una herramienta de salida, y una herramienta ajena al tema.
  • node test-ssti.js — prueba el detector de inyección en plantillas (decimoséptima herramienta, 2026-09): render_template_string de Flask, Environment().from_string() de Jinja2, PromptTemplate(template=...) y .from_template() de LangChain, ejs.render, Handlebars.compile, _.template de lodash, la combinación con una afirmación de "escapar la salida" como defensa (peor puntaje que sin esa afirmación), y una batería de casos negativos — un texto fijo del desarrollador, un SandboxedEnvironment, un PromptTemplate con placeholders fijos, y código sin ninguna compilación de plantilla.
  • node test-dynamic-code.js — prueba el Escudo de Código Dinámico (decimoctava herramienta, 2026-09): eval() sobre contenido recuperado (patrón CVE-2026-26030), Function() armado por concatenación, vm.runInContext/runInNewContext, exec() de Python, setTimeout/setInterval con un string dinámico ("eval implícito"), vm2 usado como falsa mitigación (peor puntaje que sin esa afirmación), varios sinks no literales a la vez, y una batería de casos negativos — texto fijo del desarrollador, setTimeout con una referencia a función, y isolated-vm como aislamiento real.
  • node test-dns-rebinding.js — prueba el Escudo de Rebinding DNS (decimonovena herramienta, 2026-09): StreamableHTTPServerTransport/SSEServerTransport y rutas /mcp de Express/FastAPI sin validar el header Origin, la afirmación de que "solo escucha en localhost" ya protege (peor puntaje que sin esa afirmación), varios endpoints sin validar a la vez, y una batería de casos negativos — validación explícita de req.headers.origin, una función validate_origin() reconocible, y una lista ALLOWED_ORIGINS usada cerca del endpoint.
  • node test-missing-auth.js — prueba el Centinela de Autenticación (vigésima herramienta, 2026-09): StreamableHTTPServerTransport/SSEServerTransport y rutas /mcp, /sse, /messages de Express/FastAPI sin ninguna verificación de autenticación, la combinación agravante de CORS completamente abierto (mirror exacto de CVE-2026-44895), varios endpoints sin autenticar a la vez, y una batería de casos negativos — verificación explícita del header Authorization, la función checkAndConsume() que ya usa el propio servidor de Garita, request.headers.get("authorization") de FastAPI, y un middleware requireAuth() reconocible.
  • node test-mcp-stdio.js — prueba el Escudo de Lanzamiento MCP (STDIO) (vigésimo primera herramienta, 2026-10): StdioClientTransport (TS) y StdioServerParameters (Python) con command dinámico sin validar, la propiedad abreviada de JS { command, args }, dos construcciones sin validar bajando más el puntaje que una sola, la brecha de "rehidratación" (validación en otra función, lanzamiento desde configuración ya guardada — con su propio control para no confundirla con la ausencia total de validación), el bypass vía bandera -c con un comando en lista blanca (patrón CVE-2026-30623) y su control con un script literal, la falsa sensación de seguridad de "el protocolo MCP fallaría", y una batería de casos negativos — comando literal, validación por constante nombrada, y validación basename(command) not in <lista> en la misma expresión (Python).
  • node test-redos.js — prueba el Escudo Anti-ReDoS (vigésimo segunda herramienta, 2026-10): (a+)+ aplicado contra req.body sin tope, (\s*\w+)* usado vía texto.match(re), alternancia con ramas superpuestas y cuantificador (a|ab)+, RegExp(x)/re.compile(x) construido a partir de una variable (patrón CVE-2026-0621), re.match() de Python con patrón catastrófico literal y sujeto variable, la combinación evil-aplicada + regex-dinámico empeorando el puntaje, un regex evil definido pero sin aplicación confirmada (riesgo moderado), y una batería de casos negativos — aplicado solo contra un texto fijo, mitigado por un tope de longitud, envuelto en el motor seguro RE2, RegExp() con un string literal, y un regex simple sin cuantificadores anidados.
  • node test-session-hijack.js — prueba el Escudo de Secuestro de Sesión (vigésimo tercera herramienta, 2026-10): sessions[id]/.get(id) sin vínculo de dueño, un identificador generado con Math.random() o un contador incremental, la combinación de ambos empeorando el puntaje, y una batería de casos negativos — comparación explícita de userId contra req.user, un token firmado y verificado con jwt.verify, la creación de una sesión nueva (escritura, no lookup riesgoso), y un identificador generado con crypto.randomBytes.
  • node test-oauth-audience.js — prueba el Escudo de Confusión de Audiencia OAuth (vigésimo cuarta herramienta, 2026-10): validación de audiencia condicionada a una bandera de configuración, una comparación que no coincide pero solo loguea sin rechazar, un catch() que silencia el error de audiencia lanzado por jwt.verify(..., {audience}), la ausencia total de chequeo de audiencia, y una batería de casos negativos — validación incondicional que rechaza con throw, la opción audience de la librería con un catch que re-lanza, y una rama que responde con res.status(403).
  • node test-unbounded-allocation.js — prueba el Escudo de Asignación sin Límite (vigésimo quinta herramienta, 2026-10): express.json() sin limit, acumulación manual de un stream sin chequeo de tamaño, fs.readFileSync con ruta dinámica sin chequeo, new Array(cantidadVariable)/Buffer.alloc(size) sin tope, un bucle for acotado por una variable externa sin tope, la combinación de ambas categorías empeorando el puntaje, y una batería de casos negativos — limit configurado, chequeo de tamaño en el stream, fs.statSync antes de leer, Math.min() en la propia reserva, un tope explícito antes del bucle, y un bucle acotado por un número fijo.
  • node test-cross-client-leak.js — prueba el Escudo de Fuga Entre Clientes (vigésimo sexta herramienta, 2026-10): una instancia de McpServer/Server declarada a nivel de módulo y reutilizada dentro de un handler junto con StreamableHTTPServerTransport (patrón CVE-2026-25536), estado mutable (let/var) a nivel de módulo referenciado dentro de un callback de registerTool, la combinación de ambas categorías empeorando el puntaje, y una batería de casos negativos — instancia/estado creados de nuevo dentro de cada handler, una declaración const a nivel de módulo que no se reutiliza dentro de ningún handler, y código sin ningún patrón riesgoso.
  • node test-sampling-hijack.js — prueba el Escudo de Secuestro de Sampling (vigésimo séptima herramienta, 2026-10): una petición de sampling (setRequestHandler(CreateMessageRequestSchema, ...) / 'sampling/createMessage') cumplida sin ningún paso de aprobación humana, invocación encubierta de una herramienta (callTool) desde el mismo handler sin aprobación, ausencia de tope de tokens (maxTokens/max_tokens) aun con aprobación presente, y una batería de casos negativos — aprobación + sin invocación de herramientas + tope de tokens configurado, código sin ningún handler de sampling, y un handler de una petición MCP distinta que no se confunde con sampling.
  • node test-output-schema-ssrf.js — prueba el Escudo de Esquema de Salida (vigésimo octava herramienta, 2026-10): un outputSchema/inputSchema no confiable validado con jsonschema.validate/Draft7Validator sin Registry (patrón CVE-2026-116686), una llamada de red síncrona (urllib.request.urlopen/requests.get) sin timeout dentro de una función async def, la combinación de ambas categorías empeorando el puntaje, y una batería de casos negativos — validación con un Registry explícito, un esquema fijo del propio desarrollador, una llamada con timeout configurado, y una llamada delegada a un hilo aparte (asyncio.to_thread).
  • node test-excessive-agency.js — prueba el Escudo de Agencia Excesiva (vigésimo novena herramienta, 2026-10): una herramienta de transferencia/retiro/borrado sin ningún campo de confirmación exigido (required), un campo de monto sin tope máximo (maximum/exclusiveMaximum) en una herramienta ya gatillada, la combinación de ambas categorías empeorando el puntaje, el control de que una herramienta separada de "pedir aprobación" en el mismo manifiesto no cuenta como mitigación real, y una batería de casos negativos — confirmación exigida + tope de monto definido, y una herramienta sin ninguna acción irreversible o de alto valor.
  • node test-call-spoofing.js — prueba el Escudo de Suplantación de Llamada (trigésima herramienta, 2026-10): código que ejecuta una herramienta (callTool/execute_tool) a partir de un patrón encontrado en el texto libre de la respuesta del modelo (TOOL_CALL:, bloque ```json) sin leer nunca el campo estructurado de la API, la misma ejecución cuando el código además sí lee el campo estructurado (sigue siendo alto riesgo por la ruta de texto), la combinación empeorando el puntaje frente a solo el patrón de ejecución, solo escaneo de texto sin disparo de ejecución ni campo estructurado (riesgo moderado), escaneo como posible respaldo junto al campo estructurado correcto sin disparo conectado (riesgo moderado), y una batería de casos negativos — solo campo estructurado sin ningún parseo de texto libre, la palabra "TOOL_CALL" suelta en un comentario sin ningún parseo cerca, y código sin relación con llamadas a herramientas.

Las cuatro rondas "2026-09" de arriba están documentadas con más detalle (hallazgo por hallazgo, con ejemplos de antes/después) en la ficha técnica que resume esa ronda de ataques. La séptima a la trigésima herramienta (check_package_authenticity, detect_memory_poisoning, detect_ssrf_risk, detect_path_traversal_risk, detect_command_injection_risk, detect_sql_injection_risk, detect_token_passthrough_risk, detect_hardcoded_secrets_risk, detect_insecure_deserialization_risk, detect_toxic_flow_risk, detect_ssti_risk, detect_dynamic_code_risk, detect_dns_rebinding_risk, detect_missing_auth_risk, detect_mcp_stdio_launch_risk, detect_redos_risk, detect_session_hijack_risk, detect_oauth_audience_confusion_risk, detect_unbounded_allocation_risk, detect_cross_client_leak_risk, detect_sampling_hijack_risk, detect_output_schema_ssrf_risk, detect_excessive_agency_risk, detect_call_spoofing_risk) son posteriores a esa ficha y no están incluidas ahí — su diseño y pruebas quedan documentados en este README y en sus propios lib/*.js/test-*.js.

Si algo se corrige más adelante en garita-mcp.html

Ojo: este servidor no comparte código en vivo con la página publicada como Artifact — son dos copias separadas del mismo motor. Si en una sesión futura se encuentra y corrige otra falla en garita-mcp.html, hay que traer ese mismo arreglo aquí, a lib/heuristics.js, y volver a publicar (basta con subir el archivo corregido a GitHub — Render vuelve a desplegar solo).

Sobre Garita Escudo

Garita Escudo ya tiene su propia herramienta dentro de este servidor (detect_poisoned_tool_descriptions, ver arriba) — no hace falta un servidor aparte. La página web (garita-escudo/tool.html) sigue existiendo también, gratis e ilimitada, como una segunda forma de usar el mismo motor sin pasar por el servidor MCP.

No installation packages available.