Lectura arbitraria de archivos locales en mcp-memory-keeper

Se ha identificado una vulnerabilidad crítica de lectura arbitraria de archivos en el paquete mcp-memory-keeper. La función context_import pasaba el parámetro filePath suministrado por el llamante directamente a fs.readFileSync sin ningún tipo de confinamiento de ruta. Esto permitía a un cliente MCP malicioso, o a un agente LLM manipulado mediante prompt injection para invocar la herramienta, apuntar filePath a cualquier archivo legible por el proceso servidor, fuera de cualquier directorio de sesión o exportación.

Vectores de explotación

La vulnerabilidad presentaba dos modalidades de divulgación de información:

Divulgación completa (archivos JSON): un objetivo con JSON válido, como la sesión exportada de otro usuario o un archivo de credenciales *.json o de cuenta de servicio, era parseado e importado en la sesión del llamante, quedando recuperable de forma literal mediante context_get o context_export.

Divulgación parcial (cualquier archivo): para un objetivo no JSON, como /etc/passwd, una clave SSH o un archivo .env, JSON.parse lanzaba una excepción y el motor V8 incluía un fragmento de los bytes iniciales del archivo en el mensaje del SyntaxError, que era devuelto literalmente al llamante.

Tanto el traversal mediante ../ como las rutas absolutas funcionaban sin restricción alguna, ya que no existía ningún tipo de confinamiento de ruta.

Impacto

En un despliegue MCP típico, el servidor se ejecuta en la máquina del desarrollador, por lo que el conjunto de archivos alcanzables incluye sesiones de memoria exportadas de otros usuarios, archivos JSON de credenciales y configuración, y, en forma de bytes iniciales, archivos .env, claves SSH y /etc/passwd.

El vector de activación es un argumento de herramienta, por lo que el modelo de amenaza realista contempla un agente LLM con prompt injection que invoca context_import, o cualquier cliente MCP conectado al servidor.

Corrección

El problema fue corregido en la versión 0.13.0 mediante el PR #36, con las siguientes medidas:

  • Las importaciones quedan confinadas a un directorio de exportaciones propiedad del servidor (<DATA_DIR>/exports, configurable mediante la variable de entorno MEMORY_KEEPER_EXPORT_DIR), resuelto con realpathSync. El traversal ../, las rutas absolutas fuera del directorio y los escapes mediante enlaces simbólicos son rechazados en todos los casos.

  • La lectura del archivo y el parseo con JSON.parse son operaciones separadas. Los fallos de lectura o parseo devuelven un mensaje genérico y nunca exponen bytes del archivo, eliminando la filtración mediante el mensaje de SyntaxError. La ruta de escritura en base de datos es igualmente genérica.

  • Se incluye una suite de regresión de seguridad extremo a extremo que cubre los vectores de lectura arbitraria y traversal reportados, el escape mediante enlace simbólico, el límite del prefijo de directorio y una verificación de oráculo de no existencia.

Mitigación

Actualizar a la versión >= 0.13.0. No existe ninguna mitigación basada únicamente en configuración para las versiones afectadas.

Referencias

  • Reporte: GitHub issue #35
  • Corrección: PR #36
  • Reportado por Zhihao Zhang (@mcfly-zzh)