sistema: OPERATIVO
← volver a todos los hacks
AGENTS MEDIUM NEW

Cuando un argumento de herramienta MCP se convierte en un intent de Android: los sinks de mobile-mcp

CVE-2026-35394 permite que una URL controlada por el modelo dispare intents de Android arbitrarios mediante la herramienta mobile_open_url de mobile-mcp. Junto a una CVE gemela de path traversal, revela un patrón: argumentos de herramientas MCP que llegan a sinks sin validación.

2026-06-05 // 7 min affects: mobile-mcp, mobile-mcp-lt-0.0.50, model-agnostic-mcp-clients

En resumen mobile-mcp es un servidor MCP de desarrollo y automatización móvil. CVE-2026-35394, publicada en abril de 2026 (CWE-939, vector CNA de GitHub AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:H, alta), permite que una URL entregada a la herramienta mobile_open_url dispare intents de Android arbitrariostel:, sms:, códigos USSD, content: — porque la herramienta nunca valida el esquema del URI. Corregida en 0.0.50. Un fallo gemelo, CVE-2026-33989 (path traversal, corregido en 0.0.49), pertenece a la misma clase a través de otro sink. La lección no se limita a un paquete: los argumentos de herramientas MCP son accesibles para un atacante, y todo sink al que lleguen debe validarlos.

¿Qué es esto?

El servidor @mobilenext/mobile-mcp de Mobile Next expone un teléfono o un emulador a un agente LLM como un conjunto de herramientas MCP: tocar, escribir, capturar pantalla, abrir una URL. Según el aviso de seguridad de GitHub GHSA-5qhv-x9j4-c3vm, las versiones anteriores a 0.0.50 pasan la cadena entregada a la herramienta mobile_open_url directamente al sistema de intents de Android, sin ninguna lista de esquemas permitidos. Android resuelve mucho más que http(s): tel: realiza una llamada, sms: abre un mensaje, content: alcanza un content provider y los códigos del marcador pueden disparar acciones USSD. Así, un valor que el modelo podía elegir libremente se convierte en una acción sobre el dispositivo.

El mismo proyecto publicó CVE-2026-33989 unos días antes (publicación en NVD el 2026-03-27, corregida en 0.0.49): los parámetros saveTo y output de las herramientas de captura y grabación de pantalla se escribían en disco sin validación, permitiendo un path traversal fuera del espacio de trabajo. Dos CVE, dos herramientas, una sola causa raíz: argumentos de herramienta no validados que llegan a un sink potente.

Cómo funciona

Un argumento de herramienta MCP no es una «entrada de confianza». Es lo que el modelo emitió, y el contexto del modelo contiene habitualmente texto no confiable: una página web visitada, un correo resumido, un ticket clasificado. Esa es la superficie de inyección de prompt indirecta — texto del atacante aguas arriba, llamada a herramienta aguas abajo. Cuando la herramienta reenvía ese argumento a un sink sin verificarlo, la inyección se materializa en una acción real.

Para mobile_open_url, el paso peligroso es la falta de comprobación del esquema antes del despacho:

// Forma vulnerable (< 0.0.50): el esquema nunca se restringe
async function mobile_open_url(url) {
  // url puede ser tel:, sms:, content: o una cadena del marcador/USSD —
  // resuelta tal cual por el sistema de intents de Android.
  await device.openUrl(url);   // sink: intent arbitrario
}

// Forma corregida (0.0.50): primero se permite el esquema
function assertWebScheme(url) {
  const ok = ["http:", "https:"];
  if (!ok.includes(new URL(url).protocol)) throw new Error("scheme not allowed");
}

El vector CVSS (UI:R) refleja que un humano todavía debe ejecutar el agente en el dispositivo conectado, pero no se requieren privilegios de atacante (PR:N) y la solicitud es accesible por red (AV:N). El impacto en integridad y disponibilidad es alto: la acción se ejecuta en un teléfono real. No publicamos una cadena funcional; el objetivo es la forma del fallo, no un payload.

Por qué importa

El valor de MCP es que un mismo agente puede operar muchas herramientas. Su riesgo es que cada herramienta decide por sí sola si confía en sus argumentos — no existe un mediador central que diga «esta cadena proviene de la salida del modelo, trátala como no confiable». mobile-mcp se sitúa frente a un sink especialmente potente (el resolutor de intents de un teléfono), pero el patrón está en todas partes: un MCP de base de datos que interpola un argumento en SQL, un MCP de shell que lo reenvía a un comando, un MCP de sistema de archivos que lo concatena en una ruta. Cada nueva herramienta es otra oportunidad de reintroducir la clase, lo que explica precisamente dos CVE en dos semanas.

El peligro práctico es una frontera ilusoria. Los equipos razonan sobre «el agente» como aquello que hay que asegurar y pasan por alto que el servidor MCP es un diputado confundido (confused deputy): posee los privilegios del dispositivo o del host y los usará sobre instrucciones que, en última instancia, provienen de contenido no confiable.

Defensas

  1. Actualizar. mobile-mcp ≥ 0.0.50 corrige el sink de intent; ≥ 0.0.49 corrige el sink de path traversal. Fije la versión y verifique con npm list @mobilenext/mobile-mcp.
  2. Lista de permitidos en cada sink, no solo en este. Valide el esquema de los sinks de URL (http/https únicamente), canonicalice y confine las rutas de los sinks de archivos, parametrice los sinks de consultas. Trate cada argumento de herramienta como salida no confiable del modelo.
  3. Ejecutar los servidores MCP con privilegio mínimo. Opere un emulador desechable en lugar de un dispositivo personal; deniegue los permisos de telefonía/SMS que el flujo no necesite; aísle el sistema de archivos y la red para que un argumento malicioso no alcance datos sensibles.
  4. Auditar su superficie de herramientas en busca del patrón. Busque, en sus servidores MCP y los de terceros, argumentos que fluyan hacia openUrl, exec, escrituras de archivos o constructores de consultas sin validación, y fije esa comprobación en CI para que una futura herramienta no pueda reintroducirla.
  5. Registrar y alertar sobre esquemas fuera de banda. Un valor tel:, sms:, content: o no-http(s) que llegue a una herramienta de URL — o una escritura fuera del espacio de trabajo — es una señal de caza útil de que un argumento fue influido por un atacante.

Estado

ElementoReferenciaFechaNotas
CVE-2026-35394GHSA-5qhv-x9j4-c3vm2026-04Inyección de intent en mobile_open_url, CWE-939, vector C:L/I:H/A:H
Versión corregidamobile-mcp 0.0.50Validación de esquema añadida
CVE-2026-33989GHSA-3p2m-h2v6-g9mx2026-03-27 (NVD)Path traversal en herramientas de captura/grabación, CWE-22/73
Versión corregidamobile-mcp 0.0.49Validación de ruta añadida

El encuadre correcto no es «parchear mobile-mcp». Es que cada argumento de herramienta MCP es accesible para lo que haya en el contexto del modelo, y que una herramienta que lo reenvía a un sink privilegiado sin validación convierte una inyección de prompt aguas arriba en una acción aguas abajo — en un teléfono, un sistema de archivos o una base de datos.

Sources