Showing posts with label browsers. Show all posts
Showing posts with label browsers. Show all posts

El dilema de la divulgación coordinada

Monday, August 31, 2026

Cuando la responsabilidad es unilateral: el dilema de la divulgación coordinada

Una reflexión sobre el modelo actual de seguridad, sus asimetrías y sus consecuencias

Imagina la siguiente situación:

Has pasado semanas, quizás meses, investigando un comportamiento extraño en un sistema ampliamente utilizado. Has reproducido el problema en diferentes dispositivos. Has capturado logs, stacktraces, métricas de sistema. Has documentado cada paso con precisión. Has preparado un informe que cualquier ingeniero podría seguir para verificar el problema por sí mismo.

Envías el reporte al fabricante. Esperas. Recibes una respuesta automática. Semanas después, alguien te pide más información. La proporcionas. Vuelves a esperar.

Finalmente, recibes una respuesta:

“Hemos revisado tu informe y determinado que no cumple con los criterios para ser considerado un bug de seguridad.”

“Este problema pertenece a otro equipo.”

“Está fuera del alcance de nuestro programa de recompensas.”

“Por favor, utiliza el feedback in-product para reportarlo.”

El problema sigue existiendo. Los usuarios siguen expuestos. Pero la responsabilidad ha quedado diluida en un laberinto de equipos, programas y criterios.

Esta historia es más común de lo que muchos creen. Y revela una asimetría estructural en el modelo de divulgación coordinada que merece un análisis profundo.

Este artículo no trata sobre una vulnerabilidad concreta. Trata sobre el sistema que la gestiona o, más precisamente, sobre el sistema que a menudo no la gestiona.


1. El contrato implícito de la divulgación responsable

La divulgación responsable, también llamada coordinada, se ha establecido como el estándar ético en la seguridad informática. Su premisa es sencilla y, en apariencia, incuestionable:

“Si conocemos un problema que puede afectar a otros, debemos dar al fabricante la oportunidad de solucionarlo antes de hacerlo público.”

Esta lógica protege a los usuarios. Permite que las empresas corrijan vulnerabilidades sin exponer a sus clientes a ataques mientras el parche está en desarrollo. Es un modelo que, en teoría, beneficia a todas las partes.

En la práctica, el investigador acepta un conjunto de obligaciones que incluyen:

  • Reproducir el problema de forma fiable y documentada.
  • Proporcionar evidencia técnica suficiente (logs, trazas, código, pasos).
  • Evitar divulgar prematuramente para no poner en riesgo a los usuarios.
  • Informar al fabricante a través de los canales establecidos.
  • Facilitar la investigación con información adicional cuando se solicita.
  • Respetar los plazos de coordinación que la empresa propone.
  • Permitir que el proveedor prepare una solución antes de la publicación.
  • Documentar sus conclusiones de forma responsable y precisa.

Y, en muchos casos, el investigador hace todo esto sin ninguna garantía de reconocimiento, parche o recompensa. Lo hace porque cree en el modelo. Porque entiende que la seguridad es una responsabilidad compartida.

La lógica es impecable. Pero esa misma lógica debería funcionar en ambas direcciones.


2. El problema aparece cuando nadie es responsable y a la vez, lo son todas las partes inplicadas

Durante una investigación pueden aparecer problemas que atraviesan diferentes capas de un sistema. Un mismo comportamiento puede involucrar:

  • Aplicación (el software que el usuario ve)
  • Framework (la capa intermedia que soporta la aplicación)
  • Biblioteca nativa (código de bajo nivel, a menudo en C/C++)
  • Sistema operativo (el núcleo del sistema)
  • Fabricante / OEM (personalizaciones del sistema)

Y también:

  • Producto A (ej. Chrome, Firefox, Edge)
  • Producto B (ej. Android)
  • Componente compartido (ej. libminikin)
  • Infraestructura común (ej. Binder, IPC)
  • Servicio en la nube (ej. Llm's API)

Entonces aparece el fenómeno conocido por muchos investigadores:

“No es nuestro problema.”

Un equipo o vendor, puede indicar: “Esto es un problema de Android.”
Android puede responder: “No está dentro del alcance de nuestro programa.”
Otro equipo puede añadir: “Debe reportarse al producto correspondiente.”

Y el investigador vuelve al punto de partida.

El atacante no necesita saber qué equipo es responsable. El investigador tampoco debería tener que resolver el organigrama interno de una multinacional para encontrar al responsable. Si el problema atraviesa capas, el atacante ve un sistema. El investigador ve un sistema. La organización, sin embargo, puede verlo como tres equipos o más distintos.


3. El caso STA: una investigación transversal

Mi investigación sobre Structured Text Amplification (STA) comenzó en 2022, estudiando comportamientos relacionados con texto estructurado y agotamiento de recursos en Android. Lo que parecía un problema aislado en una biblioteca fue revelando un patrón más amplio.

Con el tiempo, aparecieron diferentes manifestaciones en distintos componentes:

Componente Síntoma Mecanismo
libminikin.so ANR, bloqueo del hilo principal Knuth-Plass O(n²)
Binder / SavedState TransactionTooLargeException, crash loops Serialización O(n²)
Llm's (modelo) Instruction Drift, generación de contenido sin contexto Atención O(n²)
Llm's (cliente) ANR, UI freeze libminikin O(n²)
Navegadores Bloqueo de renderizado Algoritmos de layout O(n²)

Lo interesante no era cada fallo individual, sino la posibilidad de que existiera un patrón común:

Entrada estructurada (texto repetitivo, baja entropía)
              ↓
    Transformación (tokenización, layout, serialización)
              ↓
    Amplificación del coste (algoritmo O(n²))
              ↓
    Agotamiento de recursos (CPU, memoria, tiempo)
              ↓
    Pérdida de disponibilidad (ANR, crash, DoS)

Este patrón aparecía en el cliente Android (la apps de Google, Mozilla, Meta, Microsoft, Xiaomi, entre otros). Aparecía en el sistema operativo (libminikin, Binder). Y, más tarde, apareció también en los Llm's, tanto en el modelo (pérdida de contexto) como en el cliente (ANR al renderizar respuestas largas o tareas simples como contar caracteres ).

El problema era real, reproducible y estaba documentado con stacktraces, métricas de sistema y pasos concretos. Pero al intentar reportarlo siguiendo los cauces establecidos, ocurrió lo que muchos investigadores han vivido:

  • VRP's: “Fuera de alcance.”
  • llm's VRP: “Bypass de guardrail de seguridad. Fuera de alcance.”
  • Feedback in-product: Canal adecuado, pero sin garantía de respuesta o mitigación.

El patrón STA existía. Las evidencias eran sólidas. Pero la responsabilidad quedaba diluida entre equipos, programas y criterios.


4. La anatomía de una derivación

Para entender el problema, es útil analizar qué ocurre cuando un reporte atraviesa el sistema de gestión de vulnerabilidades de una gran organización.

Fase 1: Recepción
El investigador envía un informe detallado. Recibe un acuse de recibo automático. El reporte entra en una cola de triaje.

Fase 2: Triaje inicial
Un revisor, a menudo con poco tiempo y muchos reportes, clasifica el problema. Si encaja en un patrón conocido, puede ser asignado a un equipo. Si no, puede ser rechazado por “falta de información” o “no reproducible”.

Fase 3: Análisis técnico
El equipo asignado analiza el problema. Si el equipo es el correcto, la investigación avanza. Si el problema cruza fronteras, aparece la pregunta: “¿Es realmente nuestro?”

Fase 4: Derivación
El problema se traslada a otro equipo. Ese equipo, a su vez, puede derivarlo a otro. Cada derivación reinicia parcialmente el proceso. Cada equipo aplica sus propios criterios.

Fase 5: Decisión final
En algún punto, el problema es clasificado como “fuera de alcance”, “no elegible para recompensa” o “no reproducible”. El investigador recibe una respuesta. El problema sigue existiendo.

Lo paradójico es que cada decisión individual puede ser razonable. Cada equipo puede tener argumentos válidos para no asumir la responsabilidad. Pero el resultado final es que el problema no se soluciona.

Y el investigador, que empezó con la intención de ayudar, se encuentra con un muro de silencio.


5. “Out of scope” no significa “el problema no existe”

Hay una confusión conceptual que conviene aclarar.

Un programa de recompensas puede establecer legítimamente qué tipos de problemas son elegibles para recompensa. Esa es una decisión de alcance. Es razonable que una empresa defina los límites de su programa.

Pero:

No elegible para recompensa ≠ inexistente.

Un problema puede quedar fuera de un VRP y seguir siendo:

  • Reproducible.
  • Técnicamente relevante.
  • Peligroso para determinados usuarios.
  • Digno de una mitigación.
  • Digno de una investigación interna.
  • Digno de ser documentado públicamente.

Esta distinción es fundamental. Un programa de recompensas puede rechazar un reporte por alcance, pero eso no significa que el equipo de producto deba ignorarlo.

El problema ocurre cuando “fuera de alcance” se convierte en un sinónimo de “no es responsabilidad nuestra” y cuando esa falta de responsabilidad impide que el problema se solucione.


6. El coste de la investigación independiente

Para entender la asimetría, hay que considerar los recursos de cada parte.

Una gran organización puede disponer de:

  • Equipos especializados en diferentes áreas.
  • Acceso al código fuente completo.
  • Infraestructura de reproducción a gran escala.
  • Telemetría para identificar la prevalencia del problema.
  • Ingenieros dedicados a tiempo completo.
  • Herramientas internas de análisis y depuración.
  • Capacidad para parchear millones de dispositivos en días o semanas.
  • Departamento legal para gestionar riesgos.
  • Presupuesto para recompensas y reconocimiento.

El investigador independiente, en cambio, puede disponer de:

  • Un ordenador (a menudo personal).
  • Un teléfono (a menudo personal).
  • Unos bugreport (obtenidos con esfuerzo).
  • Una conexión a Internet.
  • Y muchas horas de trabajo no remunerado.

En mi caso, buena parte de esta investigación se ha realizado desde un entorno doméstico. No hay un laboratorio detrás, ni un departamento legal, ni un equipo de ingeniería esperando para validar cada hipótesis. La validación de las evidencias recae enteramente en el investigador.

Y, sin embargo, el investigador debe proporcionar evidencia suficientemente sólida para que una organización pueda tomar una decisión. La exigencia es legítima. La reciprocidad debería serlo también.


7. Cuando la evidencia contradice la respuesta inicial

Una de las situaciones más reveladoras ocurre cuando la primera conclusión de la organización es:

“No reproducible.”

Pero posteriormente aparecen:

  • Nuevos dispositivos donde el problema se manifiesta.
  • Nuevos dumps con stacktraces adicionales.
  • Nuevos ANR traces en el mismo componente.
  • Nuevas aplicaciones afectadas por el mismo patrón.
  • Nuevas reproducciones que confirman la hipótesis.
  • Evidencia del mismo componente en diferentes contextos.
  • Comportamiento consistente entre productos.

Entonces la pregunta ya no debería ser:

“¿Por qué el investigador insiste?”

La pregunta debería ser:

“¿Qué hemos aprendido desde la primera evaluación?”

La seguridad no debería funcionar como un juicio que termina con la primera decisión. Debería funcionar como un proceso iterativo:

Hipótesis inicial
        ↓
Evidencia recopilada
        ↓
Reproducción en condiciones controladas
        ↓
Análisis técnico
        ↓
Nueva evidencia (más dispositivos, más contextos)
        ↓
Reevaluación de la hipótesis
        ↓
Actualización de la decisión

Este ciclo es común en la investigación científica. En la seguridad, sin embargo, tiende a ser lineal: una decisión inicial, sin espacio para la reevaluación.


8. La paradoja de la coordinación

Cuando una organización solicita coordinación, el mensaje es claro:

“Danos tiempo para investigar y solucionar el problema.”

El investigador acepta. Pero la coordinación implica una segunda obligación: utilizar ese tiempo de forma efectiva.

La coordinación no debería significar:

Investigador
    ↓
Reporte (con evidencia)
    ↓
Espera (semanas o meses)
    ↓
"No reproducible"
    ↓
Investigador aporta más evidencia
    ↓
Espera
    ↓
"Out of scope"
    ↓
Investigador apela
    ↓
Espera
    ↓
"Pertenece a otro equipo"
    ↓
Investigador reporta al otro equipo
    ↓
El ciclo se reinicia

Eso no es coordinación. Es derivación de responsabilidad. Es un laberinto donde el investigador es el único que recorre todas las salas, mientras la organización mantiene sus puertas cerradas.


9. Una contradicción evidente

Al investigador se le dice:

“No publiques todavía.”

Perfecto. Es razonable.

Pero si después de meses o años la respuesta continúa siendo:

“No es nuestro problema.”

¿Durante cuánto tiempo debe permanecer el investigador en silencio?

  • ¿Quién protege al usuario durante ese periodo?
  • ¿Quién asume el riesgo de que el problema sea explotado?
  • ¿Quién decide que el problema merece atención?
  • ¿Quién determina si el problema es “suficientemente grave”?
  • ¿Dónde termina la responsabilidad del investigador y empieza la responsabilidad del fabricante?

El modelo actual responde a estas preguntas de forma implícita:

“El investigador es responsable de no divulgar. El fabricante es responsable de decidir si el problema existe.”

Pero la decisión de “si el problema existe” no debería ser una decisión unilateral, especialmente cuando el investigador ha aportado evidencia sólida y reproducible.


10. La responsabilidad no puede viajar solo en una dirección

El modelo actual puede resumirse así:

Investigador Organización
Reproducir el problema Investigar técnicamente
Documentar con evidencias Validar la información
Reportar a través de los canales Responder en tiempo razonable
Coordinar la divulgación Coordinar la corrección
Esperar el tiempo necesario Actuar sobre el problema
No divulgar prematuramente Mitigar el riesgo
Facilitar información adicional Asumir responsabilidad

El problema aparece cuando la segunda columna se convierte en:

“No corresponde a nuestro programa.”

“No es elegible para recompensa.”

“Pertenece a otro equipo.”

Entonces la primera columna sigue teniendo todas las obligaciones, mientras que la segunda conserva únicamente la posibilidad de rechazar el caso.

Eso es una asimetría estructural. No es un fallo de una empresa concreta. Es un fallo del modelo.


11. La recompensa tampoco debería ser el centro

Hay una cuestión especialmente importante que suele pasarse por alto.

La investigación de seguridad no debería reducirse a:

Bug → CVE → recompensa

Hay investigadores que buscan dinero. Otros buscan reconocimiento. Otros simplemente quieren que el problema se arregle. Algunos investigan porque quieren comprender cómo funcionan los sistemas y compartir ese conocimiento.

Por eso una respuesta como:

“No es elegible para recompensa”

no debería cerrar necesariamente la conversación técnica.

Podría existir otra respuesta:

“No podemos recompensarlo según las reglas del programa, pero hemos identificado el problema y vamos a mitigarlo.”

“Hemos derivado el problema al equipo de producto para que lo evalúe en futuras versiones.”

Esa sería una respuesta mucho más saludable para el ecosistema.


12. El silencio como estrategia

Hay una realidad incómoda que pocos investigadores mencionan abiertamente.

En algunos casos, el silencio —o la derivación, no es un fallo del sistema, sino una estrategia deliberada.

Si un problema no se clasifica como vulnerabilidad, no hay obligación de parchearlo.
Si el problema se deriva a otro equipo, la responsabilidad queda en suspenso.
Si el investigador se cansa y desiste, el problema desaparece del radar.

Esta estrategia no requiere mala fe. Puede ser simplemente el resultado de equipos que trabajan bajo presión, con recursos limitados, y que priorizan los problemas que encajan en sus métricas.

Pero el efecto es el mismo: el problema no se soluciona.


13. El investigador independiente no tiene voz en la decisión

Una de las asimetrías más profundas es la siguiente:

El investigador aporta el descubrimiento. Aporta la evidencia. Aporta el tiempo. Aporta la paciencia. Aporta la buena fe.

Pero no tiene voz en la decisión final.

  • No decide si el problema es “suficientemente grave”.
  • No decide si merece un parche.
  • No decide cuándo se solucionará.
  • No decide si se reconocerá su trabajo.
  • No decide si se comunicará públicamente.

La organización tiene todas esas decisiones. El investigador tiene solo la decisión de publicar o no publicar.

Y esa decisión, publicar, está cargada de riesgos: legales, reputacionales, y de relación con futuros reportes.


14. Divulgación coordinada no es silencio coordinado

Existe una diferencia esencial entre ambas cosas:

Divulgación coordinada:

“Tenemos un problema. Trabajemos juntos para entenderlo, mitigarlo y comunicarlo de forma responsable.”

Silencio coordinado:

“El problema está reportado, pero nadie quiere asumir la responsabilidad. El investigador espera. El problema sigue existiendo.”

La primera protege a los usuarios. La segunda protege principalmente al proceso.

La primera es colaboración. La segunda es inacción.

Y la seguridad debería estar diseñada para proteger a los usuarios, no los procesos internos.


15. El caso STA como ejemplo de un problema más amplio

STA no es una excepción. Es un ejemplo de lo que ocurre cuando un comportamiento atraviesa diferentes capas de un ecosistema y la responsabilidad queda fragmentada.

En mi investigación, el mismo patrón apareció en:

  • Android (libminikin, Binder, SavedState).
  • Llm's (modelo y cliente).
  • Aplicaciones de terceros (WhatsApp, navegadores).
  • Componentes compartidos (StaticLayout, LineBreaker).

Cada uno de estos dominios tiene sus propios equipos, sus propios programas de recompensas, sus propios criterios y sus propias prioridades.

Pero el patrón subyacente es el mismo. Es la misma entrada estructurada, la misma amplificación de coste, el mismo agotamiento de recursos.

Sin embargo, cuando intenté reportarlo de forma transversal, me encontré con que:

  • VRP's lo consideraron “fuera de alcance”.
  • llm's VRP lo consideraron “safety guardrail bypass”.
  • El feedback in-product no garantiza respuesta ni mitigación.
  • El problema sigue existiendo.

STA no es un problema de un equipo. Es un problema de arquitectura. Y los problemas de arquitectura no se solucionan derivando responsabilidades.


16. Lo que debería cambiar

Para que la divulgación coordinada funcione de forma efectiva, se necesitan algunos cambios en el modelo actual:

a. Puntos de entrada transversales
Las grandes organizaciones deberían tener puntos de entrada para problemas que cruzan equipos. Un equipo central de triaje que pueda evaluar un problema técnico sin necesidad de que el investigador conozca el organigrama interno.

b. Distinción clara entre “alcance” y “existencia”
Que un problema no sea elegible para recompensa no debería impedir que el equipo de producto lo evalúe y, si es necesario, lo mitigue.

c. Procesos de reevaluación
Si el investigador aporta evidencia adicional que contradice una decisión inicial, debería existir un proceso para reabrir la investigación sin necesidad de reiniciar todo el ciclo.

d. Comunicación transparente
Si el problema se deriva a otro equipo, el investigador debería ser informado de forma clara, con un punto de contacto o un identificador de seguimiento.

e. Reconocimiento sin recompensa
Si el problema no cumple los criterios de recompensa, pero es técnicamente relevante, la organización debería poder ofrecer un reconocimiento simbólico (mención en los agradecimientos, nota en las release notes, etc.).


17. Una pregunta incómoda (y su respuesta)

Después de años investigando vulnerabilidades, con mas de 400 descubiertas y documentadas y mas de 80 CVE, observando este patrón, hay una pregunta que considero inevitable:

¿Qué debe hacer un investigador cuando ha cumplido con todas las reglas de la divulgación responsable, pero ninguna organización acepta la responsabilidad de solucionar el problema?

No tengo una respuesta sencilla. Pero sí tengo una conclusión:

La responsabilidad no puede exigirse unilateralmente.

Si se espera que el investigador actúe responsablemente para proteger a los usuarios, las organizaciones deben hacer lo mismo. La seguridad no es un juego de trileros donde la responsabilidad se pasa de una mano a otra hasta que el investigador se cansa.

El investigador debe asumir su parte. Pero la organización también.


18. El objetivo final

No se trata de ganar una discusión. No se trata de conseguir una recompensa. No se trata de demostrar que una empresa se equivocó.

Se trata de algo mucho más sencillo:

Que el problema deje de existir.
  • Si una vulnerabilidad puede solucionarse, solucionémosla.
  • Si no es vulnerable, demostremos por qué.
  • Si está fuera del alcance de un programa, derivémosla al equipo adecuado.
  • Si el impacto no alcanza el umbral de una recompensa, eso no impide investigarla.

Pero no deberíamos permitir que el último paso sea:

“Este problema pertenece a otro.”

Porque entonces el problema sigue perteneciendo a todos. Y, al final, a nadie.


19. Una llamada a la responsabilidad compartida

La divulgación responsable nació como un pacto de confianza entre investigadores y fabricantes. Ese pacto sigue siendo necesario. Pero la confianza funciona en ambas direcciones.

El investigador debe asumir responsabilidad por lo que descubre.

  • Investigar con rigor.
  • Documentar con precisión.
  • Reportar con buena fe.
  • Coordinar con paciencia.
  • Divulgar con responsabilidad.

Las empresas deben asumir responsabilidad por lo que construyen.

  • Responder con seriedad.
  • Investigar cuando exista evidencia suficiente.
  • Distinguir entre “fuera de alcance” y “no existe”.
  • Evitar derivaciones infinitas.
  • Proporcionar puntos de contacto adecuados.
  • Informar cuando la investigación continúa.
  • Mitigar cuando sea necesario.

Cuando un investigador entrega evidencia reproducible, concede tiempo y respeta los mecanismos de coordinación, la respuesta no debería ser una cadena infinita de derivaciones.

Debería existir una puerta de entrada.

Alguien que diga:

“Entendido. Nosotros nos encargamos de averiguar quién debe solucionarlo.”

Porque esa es precisamente la diferencia entre gestionar un reporte y gestionar un riesgo de seguridad.


Conclusión: la seguridad no es un juego de trileros

La seguridad informática es un campo que se basa en la confianza. Confiamos en que los fabricantes corrigen los problemas que les reportamos. Confiamos en que los investigadores no explotan las vulnerabilidades antes de que se solucionen.

Pero la confianza no es un recurso infinito. Se agota cuando una de las partes no cumple su parte.

La divulgación coordinada no debería ser una excusa para que las empresas trasladen todo el riesgo al investigador. No debería ser un mecanismo para silenciar problemas incómodos. No debería ser un laberinto del que el investigador no pueda salir.

Debería ser un proceso colaborativo donde ambas partes asumen sus responsabilidades para proteger a los usuarios.

El investigador descubre. El fabricante corrige.

Y el usuario, al final, está protegido.

Ese es el objetivo. No deberíamos perderlo de vista.


Como final del artículo diré: si clicar en un enlace causa el crash wn una aplicación y esta aplicación hace caer SystemUI y a su vez causa un loop de reinicios y se la interfaz y obliga al sistema a borrar sus propios datos de estado etc y de la que un usuario normal no sabe recuperarse, no es un problema de seguridad entonces que es?

Manuel García Peña (Lostmon)Independent Security Researcher
Agosto de 2026

STA-003 When sharing an oversized link breaks the browser (Binder Share Intent)

Friday, August 21, 2026

STA-003 Binder Share Intent TransactionTooLargeException

Structured Text Amplification — Vector 003

This post documents STA-003, a denial-of-service vector in Android browsers where an oversized URL shared via the context menu triggers a TransactionTooLargeException during Binder serialization of the ACTION_SEND Intent, causing an immediate browser crash.

⚠️ Severity: STA-003 is an interactive DoS vector. A single long-press on a crafted link followed by "Share" can crash the browser immediately. No special permissions or privileges are required.


1. Summary

STA-003 describes a denial-of-service condition in Android web browsers when an excessively large URL is shared via the context menu of a link.

The vector is triggered when the user performs a long-press on a link and selects "Share". The browser constructs an ACTION_SEND Intent containing the URL as EXTRA_TEXT. During serialization of the Intent for transfer via Binder, the data size may exceed the Binder transaction limit (approximately 1 MiB). This can result in an unhandled TransactionTooLargeException, causing an immediate browser process termination.

Type: Denial of Service (DoS)
Class: Resource Exhaustion / IPC Serialization Boundary
CWE: CWE-20 — Improper Input Validation; CWE-400 — Uncontrolled Resource Consumption
CVSS v4.0 estimated: 6.5 (Medium)


2. Attack chain

The observed chain can be represented as:

Malicious web page
       ↓
Excessively large URL
       ↓
Long-press on the link
       ↓
Context menu
       ↓
"Share"
       ↓
Intent ACTION_SEND
       ↓
EXTRA_TEXT = URL
       ↓
Intent serialization
       ↓
Binder IPC
       ↓
Parcel > transaction limit
       ↓
TransactionTooLargeException
       ↓
Browser crash
       ↓
Denial of Service

The fundamental characteristic of STA-003 is that a legitimate-looking input — a URL — acquires a disproportionate cost when crossing a serialization/IPC boundary.


3. Difference from STA-001

STA-003 must be kept separate from STA-001.

Vector Mechanism Failure
STA-001 Context menu processing Prolonged processing / freeze before crash
STA-003 ACTION_SEND Intent → Binder serialization Immediate crash during Intent serialization

STA-001 is associated with prolonged processing during context menu construction, with a noticeable freeze before the crash.

STA-003 fails during the Share operation itself:

Long URL
       ↓
ACTION_SEND
       ↓
Intent serialization
       ↓
Binder
       ↓
TransactionTooLargeException
       ↓
Immediate crash

4. Required conditions

The attack requires:

  • An Android browser that exposes the Share operation for the affected link.
  • A page containing a link with a sufficiently large URL to exceed the effective Binder transaction limit.
  • The victim performs a long-press on the link.
  • The victim selects "Share".

Not required:

  • Special Android permissions
  • Local access to the device
  • Application privileges
  • Prior code execution on the device

The URL can be distributed via any channel capable of delivering a link, including web pages, messaging, email, social networks, QR codes, or other URL distribution mechanisms.


5. Browser-specific observations

A relevant observation during the investigation is that the availability of the vector depends on how each browser handles excessively large URLs.

Browser Behaviour Mitigation level
Google Chrome Does not present Share option for extremely large URLs Application-level
Microsoft Edge Equivalent mitigation behaviour Application-level
Opera Browser Share operation available → TransactionTooLargeException → crash No mitigation

This difference is important because it demonstrates two levels of mitigation:

Application-level mitigation:
    Avoid generating/sending an excessively large Intent

Framework-level:
    Accept an oversized operation
    ↓
    TransactionTooLargeException
    ↓
    Safe fallback / degradation

The existence of application-level mitigations does not eliminate the underlying condition in the IPC mechanism.


6. Stack trace and evidence

The following stack trace was captured during a Share operation with an oversized URL. The excerpt is abbreviated; irrelevant frames and build-specific details have been omitted.

Share Intent crash

java.lang.RuntimeException: android.os.TransactionTooLargeException:
data parcel size 1662976 bytes
at android.app.ActivityClient.activityStopped(ActivityClient.java:101)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run()
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(...)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)

Key metric: Parcel size 1,662,976 bytes — exceeds the Binder transaction limit (1,048,576 bytes) by approximately 58%. The crash is immediate, with no observable delay.

Vulnerable code pattern

The following pattern is present in many browsers and apps that implement sharing functionality:

// Browser code (simplified)
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, url); // ← No size check!
startActivity(Intent.createChooser(shareIntent, "Share via"));

The Android framework provides no guardrails for Intent.putExtra() size, and no automatic truncation or validation is performed before the Intent is serialized for Binder transmission.


7. Impact

The observed impact is a denial of service of the browser:

  • Immediate browser crash during the Share operation
  • Loss of browsing session
  • Interruption of user activity
  • Potential repetition of the crash if the operation is re-executed

Unlike STA-001 (which may show a 10-17 second freeze before crash), STA-003 crashes immediately during Intent serialization.

Any application implementing share functionality is potentially vulnerable:

  • Web browsers (all vendors)
  • Email clients
  • Social media apps
  • Messaging apps
  • Document viewers
  • File managers
  • Any app with a "Share" button for text/URLs

Estimated affected apps: 10,000+ on Play Store


8. Relationship to Structured Text Amplification

STA-003 belongs to the class of vectors where a legitimate-looking data item crosses a transformation or serialization boundary without a sufficiently early limit.

The pattern can be expressed as:

Small / legitimate input
        ↓
Transformation / serialization
        ↓
Structured representation
        ↓
IPC boundary
        ↓
Resource limit exceeded
        ↓
Failure / DoS

In STA-003:

URL
 ↓
String / EXTRA_TEXT
 ↓
Intent
 ↓
Parcel
 ↓
Binder
 ↓
TransactionTooLargeException
 ↓
Browser crash

The vector therefore does not depend solely on the logical size of the URL. The relevant cost is the size of the representation that must ultimately cross the IPC boundary.


9. Proof of Concept

The PoC consists of an HTML page containing a link with an extremely large URL:

<a href="https://example.com/[STA Pattern]">
    Test link
</a>

During the investigation, character patterns were used to produce an especially large representation after encoding/serialization transformations. The full payload is not included in this public documentation to reduce the potential for abuse.

Conceptual reproduction:

  1. Open an affected Android browser (e.g., Opera).
  2. Access a page containing the prepared link.
  3. Long-press the link.
  4. Select "Share".
  5. Observe the immediate browser crash.
  6. Logs may show TransactionTooLargeException with a parcel size exceeding 1 MB.

10. Evidence and background

The research relates STA-003 to the following background:

  • Chromium Issue 40879254 (2022): Issue related to sharing an excessively large URL for Binder.
  • Mozilla Bugzilla #1802594: Incidents related to TransactionTooLargeException / DeadSystemException in Firefox.
  • Chromium: Changes intended to truncate visible URLs and reduce the size of certain data before subsequent operations.
  • Android TransactionTooLargeException: Official documentation of the failure mechanism associated with excessively large Binder transactions.
  • Android Intent.ACTION_SEND: Surface used to transfer content that subsequently crosses IPC.

These references constitute independent background that helps establish that the attack surface is not limited to a specific browser implementation.

A relevant observation during the investigationis that Chrome and Edge hide the Share option for extremely large URLs, while Opera does not. This suggests that Chrome's behaviour is a deliberate application-level mitigation rather than a framework-level protection. The difference is important: it demonstrates that application-level mitigations can prevent the crash, but they do not address the underlying framework condition. A malicious payload delivered through an app that lacks such a mitigation (like Opera) still triggers the TransactionTooLargeException and crash. This aligns with Google's documented position that TransactionTooLargeException is a framework constraint, not a security vulnerability. However, the availability of application-level mitigations does not eliminate the underlying risk for apps that do not implement them.


11. Proposed mitigation

11.1. Application-level mitigation

The browser should check the URL size before constructing the Intent that will be transferred via Binder.

URL
 ↓
Size validation
 ↓
Does it exceed the limit?
 ├── Yes → truncate / reject / safe alternative
 └── No → build ACTION_SEND

This is the preferred defense because it prevents the oversized object from reaching the IPC boundary. Browsers that already hide the Share option for excessively large URLs (Chrome, Edge) provide an example of this approach.

11.2. Framework-level mitigation

Android could provide additional protection mechanisms so that a transaction exceeding the limit does not necessarily result in an unrecoverable crash of the consuming process.

Oversized transaction
        ↓
Detect before / during IPC
        ↓
Controlled failure
        ↓
Fallback
        ↓
Application remains operational

Late detection of a size condition should not automatically become a process termination condition when a safe alternative exists.

11.3. SavedState / FragmentManager (related surface)

In related SavedState surfaces, the research additionally proposes controlled fallback against errors occurring during restoration of excessively large state.

try {
    restoreStateInternal(state);
} catch (TransactionTooLargeException e) {
    Log.e(TAG, "SavedState restore failed. Restarting without state.", e);
}

The goal would be to degrade to a clean state when it is safe to do so, rather than propagating the exception to cause a crash.


12. Classification

STA-003 can be classified as:

Binder Serialization Boundary Resource Exhaustion

Within the STA model:

"Uncontrolled amplification / expansion across a serialization and IPC boundary leading to resource exhaustion."

The vector also has an important characteristic: the initial data can be completely valid from a semantic point of view — a URL — and become dangerous solely due to its size and the cost of transporting it between components.


13. Scope of the claim

STA-003 does not demonstrate that Binder is inherently vulnerable or that all Android browsers are exploitable.

The research demonstrates a more specific condition:

"When an application allows excessively large data to reach an ACTION_SEND operation and subsequently cross Binder without sufficient prior validation, the transaction size limit can become a denial-of-service mechanism."

Successful exploitation depends on the specific browser implementation and whether it incorporates validation, truncation, or fallback before constructing or sending the Intent.


14. Research status

Field Value
Vector STA-003
First formal communication 20 January 2026
Researcher Manuel García Peña (Lostmon)
Nature Independent research
Platform Android
Primary surface Browser → Intent.ACTION_SEND → Binder
Impact DoS
Interaction required Yes
Privileges None
Special permissions None

STA-003 is part of the broader Structured Text Amplification (STA) research, which studies a recurring pattern of resource exhaustion produced when input data crosses serialization, transformation, IPC, or persistence boundaries without sufficiently early resource limits.


15. Conclusion

STA-003 demonstrates how an ordinary operation — sharing a link — can become a denial-of-service condition when an oversized input crosses multiple representation layers:

URL
 → Intent
 → Parcel
 → Binder
 → transaction limit
 → TransactionTooLargeException
 → crash

The most robust mitigation is to measure and limit the size before reaching the amplification or IPC boundary, complemented by fallback mechanisms that prevent an oversize condition from unnecessarily becoming a process crash.

In the context of STA, this vector constitutes an example of how a legitimate-looking structured input can become a resource exhaustion condition when crossing a serialization boundary.


Complete whitepaper: Resilience Gaps in Android IPC, SavedState and Text Layout — v6 (August 2026)


📌 About this series
This post is part of a series documenting the 32 vectors of Structured Text Amplification (STA).

Published:
STA-005 — WhatsApp
STA-003 — Binder Share Intent (this post)

Whitepaper: Resilience Gaps in Android IPC, SavedState and Text Layout v5


Lostmon · lostmon.blogspot.com

STA - UTF-16 Serialization Density Experiment v0.2 Structured Text Amplification

Friday, August 14, 2026

STA — UTF-16 Serialization Density Experiment v0.2

Structured Text Amplification

This post is part of the series documenting the 32 vectors of Structured Text Amplification (STA). The experiment presented here explores a fundamental property of Android: how the choice of characters in a string affects its in-memory size and, consequently, its ability to exhaust Binder limits and saturate the libminikin text engine.

The complete whitepaper, version v6, covers the research, methodology, evidence, and full vector catalog.


The experiment

Android stores strings internally in UTF-16. This means that the in-memory size of a string does not directly correlate with the number of characters (code points) or its UTF-8 size. The same number of characters can have very different UTF-16 footprints.

For example:

  • 70,000 ASCII characters (/) occupy 140,000 bytes in UTF-16 (×2).
  • 70,000 emojis (non-BMP, 😀) occupy 280,000 bytes in UTF-16 (×4).

This raises a key question for STA:

Can an attacker choose characters that maximize the UTF-16 footprint to reach the Binder limit (1 MB) with less input, or to saturate libminikin with more UTF-16 units?

The experiment I present here answers this question. The interactive tool I developed (v0.3) allows you to measure the UTF-16 density of any character, estimate Parcel/Binder size, and systematically explore thresholds.


The interactive tool

The following tool (PoC) measures the encoding properties of different characters and estimates the size they would occupy in a Binder transaction.

STA — UTF-16 Serialization Density Experiment
Experimental v0.3 — Measuring encoding + Parcel size
⏳ Status: Experimental

This tool measures encoding density and estimates Android Parcel / Binder size. It does not assert that these differences cause resource amplification. The goal is to quantify differences and explore correlation with STA behaviour.

🔬 Hypothesis under investigation:

Differences in UTF-16 representation (especially non-BMP characters) may shift the effective thresholds for Binder transaction limits, FragmentManager, libminikin and TaskPersister.

Character:
Code points:
(or click a character)

Generated string (70,000 code points):

📦 Estimated Parcel / Binder size

📐 Code-point equivalence:

Number of code points of another character needed to match the current UTF-16 footprint.

📊 Comparison at same code-point length

Character Code points UTF-16 units UTF-16 bytes UTF-8 bytes Ratio Bytes / CP Est. Parcel

🔍 Threshold exploration (Binder)

Current test:

ASCII baseline (code points): (70k ASCII ≈ 140 KB UTF-16)

Equivalent code points of current character to match baseline UTF-16:

📈 UTF-16 units vs code points

BMP  |  Non-BMP  |  dashed line = 1:1 identity

📘 About this tool (v0.3 improvements):

  • Added estimated Parcel size (writeString + Bundle overhead + 4-byte padding).
  • Clear Binder risk levels: Safe (<100 KB), Warning (100-500 KB), Danger (>500 KB practical limit).
  • Custom character support + dark mode.
  • Export observations as JSON for collaborative #STAresearch.
  • More accurate equivalence and threshold calculations.
  • This remains a measurement tool. Security conclusions belong to the full STA research.

⬆ Back to the experiment


Key results

1. Different characters, different footprints

The following table shows the UTF-16 footprint of different characters for the same number of code points (70,000):

Character Code points UTF-16 bytes UTF-8 bytes UTF-16 / UTF-8 ratio
/ (ASCII)70,000140,00070,0002.00×
(Euro)70,000140,000210,0000.67×
(CJK)70,000140,000210,0000.67×
😀 (Emoji)70,000280,000280,0001.00×
𝄞 (Musical)70,000280,000280,0001.00×

Key observation: ASCII characters double in size when converted to UTF-16. Non-BMP characters (emojis) are more compact in UTF-16 relative to UTF-8, but they occupy 4 bytes per character in memory.

2. Code-point equivalence

To match the UTF-16 footprint of 70,000 ASCII characters (140,000 bytes):

  • You need 35,000 emojis (😀) to reach the same 140,000 bytes.
  • You need 70,000 Euro characters () to reach the same 140,000 bytes.

This means the attacker can choose characters to control the relationship between code points and UTF-16 footprint.

3. Parcel / Binder estimation

The v0.3 tool estimates the actual size the string would occupy in a Binder transaction, including:

  • writeString() size (4-byte length + UTF-16 data + padding)
  • Bundle.putString() overhead (~44 additional bytes)

Binder risk is classified as:

  • SAFE (<100 KB)
  • WARNING (100-500 KB) — practical risk zone
  • DANGER (>500 KB) — very likely TransactionTooLargeException

The practical limit on many devices is around 500-520 KB, although the theoretical limit is 1 MB.


Implications for STA

This experiment demonstrates that an attacker can control the amplification by choosing specific characters. This affects:

Class A — Binder / SavedState / FragmentManager

  • STA-005 (WhatsApp): ASCII payload doubles in UTF-16, accelerating the Binder limit.
  • STA-012 (Threads): The attacker can choose ASCII to maximize Bundle size.
  • STA-015-DL (SystemUI): Corrupted state persists; UTF-16 size determines whether the limit is exceeded.
  • STA-022 (DuckDuckGo): 920 KB URL → 965 KB Parcel; with ASCII, the limit is reached faster.

Class B — libminikin / UI thread

  • STA-017 (Chrome/Firefox): More UTF-16 units → more O(n²) work for the line breaker.
  • STA-019 (Firefox address bar): The attacker controls the layout workload.

The ×20.6 factor in STA-005

The amplification factor observed in WhatsApp (×20.6) includes:

  • Encoding amplification: ASCII → UTF-16 (×2)
  • Structural amplification: FragmentManager adds metadata and overhead (×10+)

Key thresholds

Metric Value Notes
Theoretical Binder limit1,048,576 bytesDocumented in AOSP
Practical limit on many devices~500-520 KBBefore TransactionTooLargeException
ASCII characters to reach 1 MB524,288≈ half a million
Non-BMP characters to reach 1 MB262,144≈ a quarter million

Collaboration

The experiment includes an observation logger that allows you to save results with device, Android version, and observed STA behaviour. Observations can be exported as JSON for collaborative analysis.

If you have access to a device running a different Android version or OEM skin, run the experiment and share your results with the hashtag #STAresearch.


Methodological note

This experiment is a measurement tool, not a vulnerability in itself. It measures encoding properties that may correlate with STA behaviour observed in other vectors. The security impact is evaluated in the Class A and Class B vectors, not in the PoC itself.

Parcel/Binder estimates are approximate and may vary across devices, Android versions, and framework implementations. The PoC provides a quantitative basis for experimental exploration.


📌 Published:
STA — UTF-16 Serialization Density Experiment

📌 Coming next:
⬜ STA — Finding the Binder threshold
⬜ STA-005 — WhatsApp
⬜ STA-015-DL — Google Drive → SystemUI
⬜ STA-017 — Cross-engine ANR


Lostmon · lostmon.blogspot.com


Lostmon · lostmon.blogspot.com

 

Browse

About:Me

My blog:http://lostmon.blogspot.com
Mail:Lostmon@gmail.com
Lostmon Google group
Lostmon@googlegroups.com

La curiosidad es lo que hace
mover la mente...

Friends