Informe técnico
Google Messages — hallazgos y análisis
Resumen y gravedad
Se examinó Google Messages (com.google.android.apps.messaging) en un Samsung Galaxy A26 (SM-A266B) con Android 16, compilación BP4A.251205.006, paquete messages.android_20260910_03_RC02.phone_samsung_dynamic y código de versión 323089900. El transporte probado fue RCS. El análisis estático se realizó sobre el APK instalado exacto, con SHA-256 del APK base 9e869a68…ff60b2 y firma verificada como auténtica de Google, y se combinó con observaciones en ese único dispositivo.
| ID | Hallazgo | CWE | CVSS 3.1 | Gravedad |
| F-PREVIEW | Filtración de IP y metadatos mediante vistas previas generadas en el dispositivo | 200/359 | 4.3 | Media |
| F-UA | La petición utiliza un User-Agent suplantado y configurado remotamente (incluido en F-PREVIEW) | 451 | — | Contexto |
F-PREVIEW · CWE-200 / CWE-359
Filtración de IP y metadatos mediante vistas previas generadas en el dispositivo
Media · CVSS 4.3
Descripción
Al procesar un mensaje con una URL, Google Messages genera la vista previa con una petición HTTP(S) GET enviada desde el dispositivo, sin proxy en el servidor. El servidor del enlace recibe la IP de salida actual del destinatario, el User-Agent de la vista previa, Accept-Language y la hora. Las peticiones posteriores de una og:image o un favicon pueden incluir un User-Agent Dalvik que revela la versión de Android, el modelo y el número de compilación.
Qué activa realmente la descarga
Este punto debe quedar claro, porque determina la gravedad. El proceso tiene dos etapas:
- Al recibir el mensaje, se programa el trabajo
request_link_preview después de confirmar su escritura en la base de datos (dfvl/bcnl → btlr.b()). Para un enlace nuevo, la primera ejecución puede insertar una fila deferred y terminar antes de cualquier petición de red (btln).
- Al abrirse el chat y volverse interactiva la conversación,
onMessageListInteractive inicia un observador (ahxw → aied). Este vigila las filas deferred de esa conversación y programa un segundo trabajo, con deferred=true (aieb → btlr.a()), que puede descargar el enlace tras superar las comprobaciones siguientes.
El observador se ejecuta en un ámbito de corrutinas en segundo plano, sin una cancelación visible al salir del chat. Eso explica que la descarga pueda producirse con la pantalla bloqueada y la aplicación en segundo plano después de haber abierto el chat una vez. El código revisado no demuestra que ocurra en una conversación nunca abierta, y aquí no se afirma tal cosa.
Condiciones previas
- Ajuste de vistas previas. La función automática debe estar activada (
aqck). Google Messages permite mostrar todas las vistas previas, solo las de enlaces web o desactivarlas.
- Confianza en el remitente. El remitente debe superar la condición
btez.m(). Un contacto con lookup_key definido es uno de los estados admitidos, junto a otros dos estados de participante. Una ruta alternativa, controlada por una opción de configuración, cuenta las cargas manuales de vistas previas: el umbral predeterminado del APK es 3, guardado por participante. El valor predeterminado de enable_link_preview_untrusted_senders es false. Abrir el chat o marcar un mensaje como leído no equivale a cargar manualmente una vista previa. No se leyeron los valores activos de configuración remota.
- Esquema de URL. El analizador solo admite
http/https y reescribe ws:/wss:. Rechaza file:// y content://. Las imágenes pasan por el mismo cliente limitado a HTTP.
Impacto respaldado por las pruebas
El servidor conoce la IP de salida actual, el User-Agent, el idioma y el momento de la petición. Las descargas de imagen o favicon pueden añadir modelo, versión del sistema y compilación. Como la vista previa se identifica por ID de mensaje y no por URL, el mismo enlace en un mensaje nuevo genera otra petición. Un remitente de confianza puede repetirla y construir un rastro aproximado de ubicación y red. En la prueba archivada de marzo se utilizó una VPN: la IP observada era su salida, no una IP residencial. No se demostró ni se afirma acceso a otras aplicaciones o servicios locales, toma de control de cuentas ni ejecución de código.
Quién se considera «de confianza»
Un contacto guardado puede ser más que alguien con quien chateas: una tienda, una empresa de reparto o un banco cuyo número guardaste. No se probó si los remitentes comerciales verificados, que envían SMS/RCS masivos con nombre de empresa y sin aviso de remitente desconocido, superan la misma condición. Sigue siendo una pregunta para Google. En cualquier caso, los remitentes capaces de activar una descarga automática no se limitan a tus amigos.
Desglose de CVSS 3.1
AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N → Base 4.3 (media)
El impacto consiste en revelar una IP, un User-Agent y metadatos del dispositivo, lo que corresponde a C:Low y limita la gravedad a media. UI:R refleja el código: la cadena de descarga depende de haber abierto la conversación. La descripción anterior de «crítico / sin clics» no se sostiene: presupone una ruta UI:N con el chat nunca abierto que el código no demuestra, y un impacto C:High que esta filtración no alcanza.
Cómo corregirlo
- Descargar las vistas previas mediante un proxy de Google, para que el servidor del enlace vea la infraestructura de Google y no el dispositivo del destinatario, como ya ocurre en otros servicios de vista previa.
- Si se conserva la descarga en el dispositivo, exigir una acción explícita para cada mensaje e impedir que un observador en segundo plano la reactive tras cerrar la conversación.
- Explicar claramente el flujo de datos en la ayuda de privacidad, para que «vistas previas automáticas» no se interprete como «vistas previas que nunca revelan tu IP».
Gravedad
Sobre la puntuación
El CVSS base depende del vector de ataque, la interacción necesaria y el impacto sobre la confidencialidad, integridad y disponibilidad. La divulgación de una IP y algunos metadatos es C:Low; no alcanza gravedad alta por exigir poca interacción. «Sin clics» solo modificaría la interacción, no el impacto. Aquí ni siquiera se demuestra la variante con el chat nunca abierto: el vector justificable es UI:R, con una base de 4.3.
El hallazgo es real y merece corregirse, con una gravedad media. Un borrador anterior lo calificaba de crítico, algo incompatible con su propio CVSS y con el impacto de una filtración de IP y metadatos. Prefiero publicar una puntuación defendible a una exagerada.
Alcance y límites de los hallazgos
Se revisaron también estos aspectos, pero no se afirman como parte del hallazgo:
- Sin acceso a otras aplicaciones ni salida del aislamiento. Un HTTP
GET del cliente de vistas previas no lee datos de otra aplicación. No se atraviesa el aislamiento de Android ni se demostró que pudiera hacerse.
- Sin toma de cuentas ni ejecución de código. Se revisaron posibles vías de RCE: carga dinámica de código, llamadas a
exec/ProcessBuilder, deserialización, puentes WebView y el analizador HTML. No se encontró ninguna accesible desde un mensaje entrante.
- Sin afirmaciones universales. Se probó un dispositivo, una versión de Android y una configuración RCS. No hay pruebas para afirmar que afecta a todos los usuarios de Google Messages.
- El User-Agent no identifica la versión. El valor observado,
GoogleMessages/20.2, procede de la configuración remota y no es un identificador de compilación.
- Se anotaron indicios en el manifiesto, como permisos personalizados con protección
normal y un receptor de depuración exportado sin permiso. No se probaron: son pistas, no hallazgos confirmados, y no tienen puntuación.
Cómo comprobarlo
No se publican capturas aquí. El hallazgo se basa en la ruta de código descrita y puede reproducirse con dispositivos y un endpoint propios. El procedimiento general es este:
- Utiliza una URL que controles y que registre cada petición con IP, User-Agent y hora. Sirve webhook.site, RequestBin o un servidor sencillo propio. Estos servicios ofrecen una URL única y muestran las peticiones en directo. Usa una ruta nueva y única por mensaje para relacionar cada descarga con un solo mensaje.
- Desde una segunda cuenta propia guardada como contacto, envía el enlace a una conversación que ya hayas abierto. El registro recibirá una petición desde la salida de red del teléfono destinatario, con un User-Agent de
GoogleMessages.
- Para obtener un resultado riguroso, registra el bloqueo, Doze y el estado del proceso con el mismo reloj que el servidor. Repite una vez sin VPN para observar la salida real de la conexión.
Para evitar estas peticiones, desactiva las vistas previas automáticas de enlaces web en los ajustes. La opción «Mostrar solo vistas previas de enlaces web» no impide estas descargas. Ten presente que un contacto guardado puede obtener información sobre tu red enviando un enlace.
Cronología de la divulgación
- 2026-03-14
Comunicado al Google Mobile VRP: descarga de vistas previas en el dispositivo que revela la IP y metadatos del destinatario (CWE-200/359), con registros HTTP y capturas de mi dispositivo y cuenta (issu.ee/492756092).
- 2026-03-17
Google evaluó y cerró el informe. No hubo un compromiso posterior de corrección.
- 2026-10-29
Se volvió a analizar de forma estática el APK exacto de la versión instalada. La descarga en el dispositivo y su activación en dos etapas no habían cambiado; el comportamiento seguía presente.
Qué consideraría una corrección
Prefiero actualizar esta página a defenderla. Indicaré que está corregido cuando la versión distribuida descargue las vistas previas desde la infraestructura de Google, ocultando la IP del destinatario al servidor del enlace, o exija una acción explícita en el dispositivo sin reactivación en segundo plano tras cerrar el chat. Un cambio limitado a una compilación interna no basta.
Todas las pruebas se realizaron en mis dispositivos y cuentas, contra endpoints que controlo. No se utilizaron dispositivos, cuentas ni datos ajenos. El informe no contiene malware ni herramientas de ataque: la reproducción consiste en enviar un enlace normal a un endpoint propio. Los identificadores están abreviados.