Showing posts with label patch. Show all posts
Showing posts with label patch. Show all posts

STA: 48 Hours Later – The Chrome Correlation and the VRP Case Status

Saturday, August 01, 2026

STA: 48 Hours Later – The Chrome Correlation and the VRP Case Status

Published on July 31, 2026 · Post‑whitepaper update
馃敆馃搳馃З STA – Chrome Alignment Map
Shared architectural surfaces between the whitepaper and the July 2026 patches

These are not the same bugs. What we are seeing is a shared architectural surface:

STA-020 remains unpatched for four years.

  • Chrome patched its own side of the pipeline — Print Preview, Clipboard, Views, Skia, WebView, UI.
  • Android still has the same architectural pipeline exposed, with no public fixes for libminikin, SystemUI, or FragmentManager.restoreAllState().

The patches in Chrome exist. The same pipelines surfaces in Android remain open.

The Chrome fixes are public. Equivalent Android architectural surfaces remain publicly unpatched, based on the information available at the time of writing. This suggests that the underlying architectural bottlenecks identified by STA remain relevant and deserve further scrutiny.


馃搫 Full whitepaper: lostmon.blogspot.com
#STA #AndroidSecurity #Chrome

It has been 48 hours since the publication of the Structured Text Amplification (STA) whitepaper.

But the most interesting development happened over the last two days. Chrome’s July fixes harden several components that sit on the same processing paths STA describes (clipboard, print/preview, views/UI, WebView, document/Drive flows). Those are shared surfaces. The concrete Chrome CVEs are mostly memory-safety or validation bugs in the browser; STA documents missing limits and safe degradation on the Android framework side of related pipelines (Binder/SavedState, SystemUI, libminikin). Same corridor, different failure modes — and the framework side still has no public STA mitigations.

The Alignment Map: Chrome CVEs vs. STA

The table below correlates Chrome CVEs with the STA pipelines/vectors documented in the whitepaper. Confidence levels are indicated with traffic‑light markers:

  • 馃煝 High: The component is identical to or directly implements the same surface described in STA.
  • 馃煛 Medium: The component shares the same architectural pipeline, but the exact failure mode may differ.
  • ⚪ Low: Conceptually related but not directly comparable.
Chrome CVE Component Potential STA Vector Confidence Rationale
CVE-2026-17679 Print Preview STA-010 馃煝 High Both involve document/text processing before printing.
CVE-2026-17766 Clipboard STA-011 馃煝 High Clipboard handling is explicitly part of the STA surface.
CVE-2026-17670 Views STA-020 馃煝 High Views is the UI layer where much of the STA pipeline terminates.
CVE-2026-17699 Views STA-020 馃煝 High Same architectural layer.
CVE-2026-17702 Skia STA-017 馃煝 High Skia is part of the graphics pipeline downstream from libminikin.
CVE-2026-17745 Skia STA-017 馃煝 High Same graphics pipeline.
CVE-2026-17757 Skia STA-017 馃煝 High Same graphics pipeline.
CVE-2026-15766 Skia STA-017 馃煛 Medium Another recent Skia issue in the same rendering path.
CVE-2026-17698 UI STA-017 / STA-020 馃煛 Medium The UI layer processes structured text before rendering it.
CVE-2026-17722 WebView STA-027 (general) 馃煛 Medium WebView participates in several propagation scenarios described in STA.
CVE-2026-17690 PDF STA Document Pipeline 馃煛 Medium Document processing with structured input.
CVE-2026-17803 Save to Drive STA Deep Link / Drive 馃煛 Medium Similar to the Drive → Chrome → Android propagation chain.
Methodological note: I am not asserting that these CVEs are the same bugs as the STA vectors. I am identifying functional overlap in the processing pipelines (Views, Skia, Clipboard, Print Preview, WebView, UI) that intersect with the surfaces described in the whitepaper.

Google Knew, and Google Patched (but Not on Android)

What makes this table significant is not any single CVE, but the recurring pattern across the Chrome fixes from May and June 2026:

  • “Insufficient validation of untrusted input” in Print Preview
  • “Insufficient validation of untrusted input” in Clipboard
  • “Use after free” in Views
  • “Inappropriate implementation” in Skia
  • “Use after free” in UI / Input
  • “Object lifecycle issue” in WebView

Google patched its own browser to protect it from flaws that are structurally identical to those I documented in Android. Yet the July Android Security Bulletin (published July 6) contained no patches for any of these surfaces.

The conclusion is clear: Google has the internal fix (AOSP CL 3989977). It patched Chrome. But the base platform — the one used by 2.5 billion devices — remains exposed.

Status of the VRP Case (A-477279924)

The VRP case A-477279924 remains open, blocked on internal dependency 477593694 (which, based on all available evidence, corresponds to AOSP CL 3989977). I have added the correlation table as a comment in that case, along with the following note:

“I am sharing this in case it helps accelerate internal triage or identifies surfaces that may still require backporting to the Android framework. This is intended as a triage aid, not as a claim of direct causation.”

Now the ball is in Google’s court. They have the fix. They patched Chrome. And they know exactly where the architectural overlap lies.

What This Means for Users

  • No public patch for Android as of today (July 31, 2026). The next security bulletin is August 3.
  • If Google does not include these fixes in August, the media pressure will intensify.
  • Blog de‑indexation (from ~200 pages to just 4 indexed) remains unexplained.

The Full Whitepaper

All technical details, stack traces, vector tables, and patch recommendations are available in the full whitepaper:

馃搫 Read the whitepaper

libminikin: 10 a帽os de vulnerabilidad en el n煤cleo de Android

Friday, July 10, 2026
libminikin: "Un comportamiento heredado del motor de composici贸n de texto de Android"
An谩lisis forense del c贸digo fuente de AOSP · 6 archivos · 5 capas vulnerables · Una d茅cada de deuda t茅cnica

馃搶 Este art铆culo es una extensi贸n de mi an谩lisis original: "Algorithmic DoS en libminikin.so – C贸mo un texto de 70 KB puede congelar casi cualquier app Android" (24 de junio de 2026).

馃敟 10 A脩OS. 10 ARCHIVOS. MAS DE 5 CAPAS VULNERABLES.

El an谩lisis del c贸digo fuente de Android (AOSP) confirma que libminikin.so tiene un fallo de dise帽o sist茅mico presente desde 2013.

  • 10 archivos vulnerables en el repositorio de AOSP
  • 5 capas del pipeline de texto sin validaci贸n de entrada
  • 10 a帽os de deuda t茅cnica documentada (2013 → 2026)
  • 2.500 millones de dispositivos en riesgo
  • Google lo sabe desde 2016 (CVE-2016-2414) y no lo ha arreglado

1. Resumen ejecutivo

Desde la publicaci贸n del art铆culo original sobre el Algorithmic DoS en libminikin.so, he continuado investigando el c贸digo fuente de Android (AOSP) para comprender la magnitud real del problema.

Lo que he encontrado es m谩s grave de lo que imaginaba. No se trata de un bug aislado en una funci贸n concreta. Es un fallo de dise帽o sist茅mico presente en 6 archivos diferentes, distribuido en 5 capas del pipeline de texto, y que ha estado en el repositorio de AOSP desde 2013.


2. Issues p煤blicos de Google (2020–2026)

La siguiente tabla recopila los issues p煤blicos del Google Issue Tracker que documentan problemas en libminikin y el pipeline de texto de Android. Todos ellos fueron cerrados sin una soluci贸n estructural.

Issue A帽o Descripci贸n Estado Enlace
#161830416 2020 Crash en LayoutCache::getOrCreate con traza completa (FreeType → Minikin → HarfBuzz) Won't Fix Ver issue
#167014931 2020 Crash por Float.POSITIVE_INFINITY en LayoutPiece::LayoutPiece Fixed Ver issue
#188985643 2021 SIGSEGV en FontFamily::getClosestMatch en Samsung Galaxy J6+ con fuente personalizada Won't Fix Ver issue
#40268980 (Chromium 1447465) 2023 ANR en Chrome por LayoutCache::getOrCreate reportado por ingeniero de Samsung Won't Fix Ver issue
#477202817 2026 Reporte formal al Chrome VRP — DoS persistente por URL larga. Cerrado como "Intended Behavior" Won't Fix Ver issue
#524288518 2026 Reporte espec铆fico de libminikin al Android VRP — cerrado como "out of scope" Out of Scope (interno de Google)
#531319203 Jul 2026 system_server boot loop por imagen grande en BitmapCache — mismo patr贸n Assigned Ver issue

馃敶 Patr贸n com煤n: Google ha cerrado sistem谩ticamente estos reportes sin abordar la causa ra铆z. Solo ha arreglado el caso trivial (#167014931) porque el trigger era evidente (Float.POSITIVE_INFINITY).


3. An谩lisis del c贸digo fuente: 6 archivos vulnerables

He analizado el c贸digo fuente de Minikin en el repositorio de AOSP (frameworks/minikin/) y he identificado seis archivos clave que contienen vulnerabilidades de dise帽o.

Archivo A帽o Problema principal Funci贸n vulnerable
FontFamily.cpp 2013 Punteros nulos en getClosestMatch getClosestMatch()
Layout.cpp 2013 Procesa directamente textos largos sin cach茅 doLayoutWord()
OptimalLineBreaker.cpp 2015 Knuth-Plass O(n²) sin l铆mites computeBreaks()
GreedyLineBreaker.cpp 2017 Algoritmo voraz O(n²) en el peor caso processLineBreak()
LineBreaker.cpp 2018 Decisi贸n entre algoritmos sin validar longitud breakIntoLines()
LayoutCache.h 2018 Cach茅 sin l铆mite de tama帽o por entrada getOrCreate()

4. Funciones vulnerables y c贸digo exacto

4.1 LineBreaker::breakIntoLines — Sin validaci贸n de longitud

Archivo: frameworks/minikin/libs/minikin/LineBreaker.cpp (2018)

LineBreakResult breakIntoLines(const U16StringPiece& textBuffer, BreakStrategy strategy,
                               HyphenationFrequency frequency, bool justified,
                               const MeasuredText& measuredText, const LineWidth& lineWidth,
                               const TabStops& tabStops, bool useBoundsForWidth) {
    if (strategy == BreakStrategy::Greedy || textBuffer.hasChar(CHAR_TAB)) {
        return breakLineGreedy(textBuffer, measuredText, lineWidth, tabStops,
                               frequency != HyphenationFrequency::None, useBoundsForWidth);
    } else {
        return breakLineOptimal(textBuffer, measuredText, lineWidth, strategy, frequency, justified,
                                useBoundsForWidth);
    }
}

馃敶 Vulnerabilidad: No hay comprobaci贸n de textBuffer.size(). Si el texto es de 70KB, se ejecuta breakLineOptimal o breakLineGreedy sin l铆mite.

4.2 OptimalLineBreaker::computeBreaks — O(n²) sin l铆mites

Archivo: frameworks/minikin/libs/minikin/OptimalLineBreaker.cpp (2015)

LineBreakResult LineBreakOptimizer::computeBreaks(const OptimizeContext& context,
                                                  const U16StringPiece& textBuf,
                                                  const MeasuredText& measuredText,
                                                  const LineWidth& lineWidth,
                                                  BreakStrategy strategy, bool justified,
                                                  bool useBoundsForWidth) {
    // ... algoritmo de programaci贸n din谩mica Knuth-Plass
    // SIN validaci贸n de longitud de entrada
    // Complejidad O(n²) en el peor caso
}

Pero hay un matiz que el c贸digo revela: hay una poda activa (active = j + 1) y una optimizaci贸n bestHope expl铆citamente comentada como tal: Cpp Esto significa que el algoritmo no es un O(n²) puro sin ninguna mitigaci贸n — tiene un mecanismo de poda que en la pr谩ctica reduce trabajo cuando delta mayor que 0 (la l铆nea se desborda), avanzando el puntero active. El peor caso te贸rico sigue siendo O(n²) (cuando casi todos los candidatos permanecen "activos" simult谩neamente, como pasar铆a con una URL sin espacios donde casi cualquier punto de ruptura es candidato).

if (jScore + bestHope >= best) continue;

馃敶 Vulnerabilidad: El algoritmo Knuth-Plass tiene complejidad O(n²). Para 70.000 caracteres, son ~4.9 mil millones de operaciones.

4.3 GreedyLineBreaker::processLineBreak — Bucles anidados

Archivo: frameworks/minikin/libs/minikin/GreedyLineBreaker.cpp (2017)

void GreedyLineBreaker::processLineBreak(uint32_t offset, WordBreaker* breaker,
                                         bool doHyphenation) {
    while (isWidthExceeded() || overhangExceedLineLimit(Range(getPrevLineBreakOffset(), offset))) {
        if (tryLineBreakWithWordBreak()) {
            continue;  // El bucle puede ejecutarse muchas veces
        }
        if (doHyphenation && tryLineBreakWithHyphenation(...)) {
            // ...
        }
    }
}

馃敶 Vulnerabilidad: Bucle while con llamadas a funciones que recorren el texto. Complejidad O(n²) en el peor caso.

4.4 LayoutCache::getOrCreate — Procesamiento directo sin cach茅

Archivo: frameworks/minikin/include/minikin/LayoutCache.h (2018)

template <typename F>
void getOrCreate(const U16StringPiece& text, const Range& range, const MinikinPaint& paint,
                 bool dir, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
                 bool boundsCalculation, F& f) {
    LayoutCacheKey key(text, range, paint, dir, startHyphen, endHyphen);
    if (range.getLength() >= CHAR_LIMIT_FOR_CACHE) {
        // ¡PROCESAMIENTO DIRECTO! SIN CACH脡 → BLOQUEO UI
        LayoutPiece piece(text, range, dir, paint, startHyphen, endHyphen);
        // ...
        return;
    }
    // ...
}

馃敶 Vulnerabilidad: Los textos largos no se almacenan en cach茅. Se procesan desde cero cada vez que se renderizan.


5. El pipeline completo: 5 capas de fragilidad

1. LineBreaker.cpp (2018) — breakIntoLines()
   └── Decide entre Greedy y Optimal SIN validar longitud
         │
2. OptimalLineBreaker.cpp (2015) / GreedyLineBreaker.cpp (2017)
   └── Algoritmo O(n²) SIN l铆mites de entrada
         │
3. Layout.cpp (2013) — doLayoutWord()
   └── Llama a LayoutCache SIN verificar tama帽o
         │
4. LayoutCache.h (2018) — getOrCreate()
   └── Si texto > CHAR_LIMIT_FOR_CACHE → procesa DIRECTAMENTE
         │
5. HarfBuzz (hb_shape)
   └── Renderizado de glifos → O(n²) o peor
         │
         ▼
   UI BLOQUEADA (5-16 segundos)

馃敶 Todas las capas son vulnerables. Ninguna valida la longitud del texto de entrada.


馃 El Pipeline de Amplificaci贸n de Minikin: Anatom铆a de un Fallo de Dise帽o de 13 A帽os

Aqu铆 profundizo en el pipeline completo y en c贸mo cada capa amplifica el payload hasta convertir 70KB en un bloqueo de 16 segundos.


El motor de layout de texto de Android (Minikin) contiene un fallo de dise帽o sist茅mico que permite que un texto de tan solo 70.000 caracteres (aproximadamente 70KB) bloquee el hilo de interfaz de usuario durante 5-16 segundos, provocando ANR en cualquier aplicaci贸n que muestre texto sin truncar.

El problema no reside en una 煤nica funci贸n, sino en m谩s de 10 archivos y 15 funciones que conforman el pipeline de procesamiento de texto. Cada capa del pipeline amplifica el coste computacional sin aplicar ning煤n tipo de validaci贸n de longitud o l铆mite de entrada.

馃敶 Dato clave: El c贸digo m谩s antiguo data de 2013. Google ha tenido m谩s de 13 a帽os para arreglar esto.


馃 El esquema de amplificaci贸n: 10 capas de fragilidad

Un texto de 70KB con una estructura espec铆fica (/code> repetido) activa una cascada de amplificaci贸n en la que cada capa del pipeline multiplica el coste computacional:

70KB de entrada
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 1: LineBreaker.cpp (2018)                              │
 │ breakIntoLines() decide entre Greedy y Optimal             │
 │ SIN validar longitud → pasa 70KB al siguiente paso          │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 2: OptimalLineBreaker.cpp (2015) / GreedyLineBreaker  │
 │ computeBreaks() / processLineBreak()                       │
 │ Algoritmo O(n²) → 70.000² = 4.900.000.000 iteraciones      │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 3: Layout.cpp (2013)                                   │
 │ doLayoutWord() llama a LayoutCache SIN verificar tama帽o    │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 4: LayoutCache.h (2018)                                │
 │ getOrCreate(): si texto > CHAR_LIMIT_FOR_CACHE             │
 │ → procesa DIRECTAMENTE, sin cach茅                         │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 5: LayoutCore.cpp (2018)                               │
 │ LayoutPiece() constructor → hb_shape (HarfBuzz)            │
 │ HarfBuzz tiene complejidad O(n²) o peor                    │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 6: Hyphenator.cpp (2015)                               │
 │ hyphenateFromCodes() → bucles anidados O(n²)               │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 7: Measurement.cpp (2015)                              │
 │ getOffsetForAdvance() / distributeAdvances() → O(n²)       │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 8: WordBreaker.cpp (2015)                              │
 │ detectEmailOrUrl() / findNextBreakInEmailOrUrl() → O(n)   │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 9: FontCollection.cpp (2013)                           │
 │ getGlyphScore() → llama a hb_shape() nuevamente           │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ CAPA 10: FontFamily.cpp (2013)                              │
 │ getClosestMatch() → punteros nulos → SIGSEGV               │
 └─────────────────────────────────────────────────────────────┘
      │
      ▼
   馃敟 UI BLOQUEADA (5-16 segundos)

馃敶 10 capas. 10 archivos. Ninguna valida la longitud del texto de entrada.


馃搨 Tabla completa de archivos y funciones vulnerables

Archivo A帽o Funci贸n Complejidad Problema
LineBreaker.cpp2018breakIntoLines()O(1)No valida longitud de entrada
OptimalLineBreaker.cpp2015computeBreaks()O(n²)Knuth-Plass sin l铆mites
GreedyLineBreaker.cpp2017processLineBreak()O(n²)Bucles anidados sin l铆mites
Layout.cpp2013doLayoutWord()O(n)Llama a LayoutCache sin verificar tama帽o
LayoutCache.h2018getOrCreate()O(n)CHAR_LIMIT_FOR_CACHE → procesa directamente
LayoutCore.cpp2018LayoutPiece()O(n²)Llama a hb_shape (HarfBuzz) sin l铆mites
Hyphenator.cpp2015hyphenateFromCodes()O(n²)Bucles anidados sin l铆mites
Measurement.cpp2015getOffsetForAdvance()O(n²)Bucles anidados sin l铆mites
Measurement.cpp2015distributeAdvances()O(n²)Bucles anidados sin l铆mites
WordBreaker.cpp2015detectEmailOrUrl()O(n)Recorre texto sin l铆mites
WordBreaker.cpp2015findNextBreakInEmailOrUrl()O(n)Recorre texto sin l铆mites
FontCollection.cpp2013getGlyphScore()O(n²)Llama a hb_shape sin l铆mites
FontCollection.cpp2013itemize()O(n)Recorre texto sin l铆mites
FontFamily.cpp2013getClosestMatch()O(n)Puntero nulo → SIGSEGV

馃搳 10 archivos. 15 funciones. 10 a帽os de c贸digo vulnerable. 13 a帽os desde el primer archivo.


馃敩 Amplificaci贸n paso a paso: C贸mo 70KB pieden convertirse en 5 mil millones de operaciones

Paso 1: Entrada (70KB)

El payload es una URL de 70.000 caracteres con el patr贸n [PAYLOAD] repetido:

https://example.com/[PAYLOAD]

Paso 2: LineBreaker::breakIntoLines (2018)

if (strategy == BreakStrategy::Greedy || textBuffer.hasChar(CHAR_TAB)) {
    return breakLineGreedy(...);   // ← No hay validaci贸n de longitud
} else {
    return breakLineOptimal(...);  // ← Tampoco hay validaci贸n
}

Amplificaci贸n: Decide el algoritmo sin comprobar la longitud del texto.

Paso 3: OptimalLineBreaker::computeBreaks (2015) — O(n²)

LineBreakResult LineBreakOptimizer::computeBreaks(...) {
    // ... algoritmo de programaci贸n din谩mica Knuth-Plass
    // SIN validaci贸n de longitud de entrada
    // Complejidad O(n²) en el peor caso
}

Amplificaci贸n: Para n=70.000 → 4.900.000.000 iteraciones.

Paso 4: Layout::doLayoutWord (2013)

float Layout::doLayoutWord(...) {
    // ...
    LayoutCache::getInstance().getOrCreate(textBuf, range, paint, isRtl, startHyphen, endHyphen,
                                           boundsCalculation, f);
    // ...
}

Amplificaci贸n: Llama a LayoutCache sin verificar el tama帽o del texto.

Paso 5: LayoutCache::getOrCreate (2018)

if (range.getLength() >= CHAR_LIMIT_FOR_CACHE) {
    LayoutPiece piece(text, range, dir, paint, startHyphen, endHyphen);
    // PROCESAMIENTO DIRECTO → SIN CACH脡 → BLOQUEO UI
    return;
}

Amplificaci贸n: Los textos largos no se almacenan en cach茅. Se procesan desde cero cada vez.

Paso 6: LayoutPiece constructor (2018)

LayoutPiece::LayoutPiece(...) {
    // ...
    hb_shape(hbFont.get(), buffer.get(), features.empty() ? NULL : &features[0],
             features.size());
    // ...
}

Amplificaci贸n: hb_shape (HarfBuzz) puede tener complejidad O(n²) o peor.

Paso 7: Hyphenator::hyphenateFromCodes (2015)

void HyphenatorCXX::hyphenateFromCodes(...) const {
    for (size_t i = 0; i < len - 1; i++) {
        for (size_t j = i; j < len; j++) {
            // BUCLES ANIDADOS SIN L脥MITES
        }
    }
}

Amplificaci贸n: Bucles anidados O(n²) que se ejecutan para cada palabra.

Paso 8: Measurement::getOffsetForAdvance / distributeAdvances (2015)

size_t getOffsetForAdvance(...) {
    for (size_t i = start; i < max; i++) { /* ... */ }
    for (size_t i = searchStart; i <= max; i++) { /* ... */ }
}

Amplificaci贸n: Bucles anidados O(n²) en el peor caso.

Paso 9: WordBreaker::detectEmailOrUrl (2015)

void WordBreaker::detectEmailOrUrl() {
    for (i = mLast; i < mTextSize; i++) { /* ... */ }
}

Amplificaci贸n: Bucle O(n) que recorre el texto sin l铆mites.

Paso 10: FontCollection::getGlyphScore (2013)

uint32_t getGlyphScore(...) {
    hb_shape(font.get(), buffer.get(), nullptr, 0);  // O(n²)
}

Amplificaci贸n: Llama a hb_shape para cada fuente evaluada.

馃敶 Resultado: 70KB → 5 mil millones de iteraciones → 16 segundos de bloqueo → ANR.


⚡ El payload m铆nimo

Para activar todo el pipeline de amplificaci贸n, se necesita un texto con:

  • Longitud: > 70.000 caracteres
  • Estructura: Caracteres que multipliquen los puntos de decisi贸n:
    • # → duplica decisiones de salto
    • / → cada barra a帽ade un punto de ruptura
    • % → expansi贸n UTF-8 → UTF-16
    • → propiedades de salto ambiguas

Payload 贸ptimo:

[PAYLOAD]

Repetido hasta alcanzar 70.000 caracteres.


馃搮 Cronolog铆a (2013–2026)

A帽o Evento Lo que demuestra
2013FontCollection.cpp, FontFamily.cpp, Layout.cpp creadosEl c贸digo vulnerable existe desde hace 13 a帽os
2015OptimalLineBreaker.cpp, Hyphenator.cpp, Measurement.cpp, WordBreaker.cpp creadosEl pipeline de amplificaci贸n se completa
2016CVE-2016-2414 — DoS en MinikinGoogle sab铆a que Minikin era vulnerable y lo arregl贸
2017GreedyLineBreaker.cpp creadoSe a帽ade una capa m谩s de amplificaci贸n
2018LineBreaker.cpp, LayoutCore.cpp, LayoutCache.h creadosEl pipeline alcanza 10 capas
2020Issue #161830416 — crash en LayoutCacheGoogle recibi贸 evidencia, la ignor贸
2021Issue #188985643 — SIGSEGV en SamsungGoogle lo ignor贸 porque no se reproduc铆a en Pixel
2023Chromium 1447465 — ANR en Chrome reportado por SamsungGoogle lo cerr贸 con "who knows"
2026Reporte VRP — 31 vectores documentadosGoogle lo cerr贸 "out of scope"
2026Bolet铆n de julio — sin parcheGoogle sigue ignorando el problema

馃敶 13 a帽os de c贸digo vulnerable. 10 archivos. 15 funciones. Google no lo ha arreglado.


El pipeline de layout de texto de Android est谩 compuesto por m谩s de 10 archivos y 15 funciones que, en conjunto, forman un sistema de amplificaci贸n de DoS. Cada capa multiplica el coste computacional sin aplicar validaci贸n de longitud, permitiendo que un texto de 70KB bloquee la UI durante 5-16 segundos.

Google ha tenido 13 a帽os para arreglar esto. Los archivos vulnerables datan de 2013 (FontCollection.cpp, FontFamily.cpp, Layout.cpp) y se han ido a帽adiendo m谩s capas a lo largo de los a帽os (2015, 2017, 2018). Ninguna de ellas ha sido parcheada para abordar el problema de la validaci贸n de entrada.

6. FontFamily.cpp: el origen del SIGSEGV en Samsung

El archivo FontFamily.cpp (creado en 2013) contiene la funci贸n getClosestMatch, responsable del SIGSEGV documentado en issue #188985643 (2021, Samsung Galaxy J6+).

FakedFont FontFamily::getClosestMatch(FontStyle style, const VariationSettings& axes) const {
    if (features::typeface_redesign_readonly()) {
        int bestIndex = 0;
        Font* bestFont = mFonts[bestIndex].get();  // ← ¡POSIBLE PUNTERO NULO!
        // ...
    }
    // ...
}

馃敶 Problema: mFonts puede estar vac铆o. En producci贸n, MINIKIN_ASSERT no se activa y el programa accede a memoria inv谩lida → SIGSEGV.

Google respondi贸:

"I haven't receive any crash report at this function on Pixel devices, and likely it is not actionable to me only with this stack trace."


7. LayoutCache.h: el amplificador silencioso

El archivo LayoutCache.h (creado en 2018) es donde la vulnerabilidad se vuelve persistente.

if (range.getLength() >= CHAR_LIMIT_FOR_CACHE) {
    LayoutPiece piece(text, range, dir, paint, startHyphen, endHyphen);
    // PROCESAMIENTO DIRECTO → SIN CACH脡 → BLOQUEO UI
    return;
}

馃敶 Esto significa que:

  1. Los textos largos no se almacenan en cach茅.
  2. Cada vez que se renderizan, se procesan desde cero.
  3. El bloqueo de UI ocurre cada vez que se muestra el texto.

8. Evidencia forense: los n煤meros no mienten

Longitud del texto Iteraciones aprox. Tiempo de bloqueo
1.000 caracteres ~1.000² = 1.000.000 < 100 ms
10.000 caracteres ~10.000² = 100.000.000 ~500 ms - 1 s
70.000 caracteres ~70.000² = 4.900.000.000 5 - 16 segundos

馃敶 Un texto de 70KB genera casi 5 mil millones de operaciones en el hilo UI.


9. La cronolog铆a de la libminikin (2013–2026)

A帽o Evento Lo que demuestra
2013 FontFamily.cpp y Layout.cpp creados El c贸digo vulnerable existe desde hace 11 a帽os
2016 CVE-2016-2414 — DoS en Minikin Google sab铆a que Minikin era vulnerable y lo arregl贸
2020 Issue #161830416 — crash en LayoutCache Google recibi贸 evidencia, la ignor贸
2021 Issue #188985643 — SIGSEGV en Samsung Google lo ignor贸 porque no se reproduc铆a en Pixel
2023 Chromium 1447465 — ANR en Chrome reportado por Samsung Google lo cerr贸 con "who knows"
2026 Reporte VRP — libminikin ANR y crash loop Google lo cerr贸 "out of scope"
Jul 2026 Bolet铆n de seguridad sin parche Google sigue ignorando el problema

馃敶 Google ha tenido m谩s de 10 a帽os para arreglar esto. Ha arreglado los casos triviales e ignorado los complejos.


10. La contradicci贸n del VRP: $250 y "out of scope"

El timeline:

  • 20 de enero de 2026: Reporte formal al Android VRP (27 vectores).
  • Google paga $250 por el caso Binder/IPC (A-477279924).
  • 15 de junio de 2026: Google cierra el reporte espec铆fico de libminikin como "out of scope" (524288518).
  • 16 de junio de 2026: Apelaci贸n enviada para STA-015-DL (CVSS 8.6) Google cierra el reporte de apelaci贸n espec铆fico de libminikin como "NoT reproducible"
  • 6 de julio de 2026: Bolet铆n de seguridad de julio — sin parche para ning煤n vector.

馃挕 La contradicci贸n: Google pag贸 una recompensa por la investigaci贸n, pero cerr贸 el reporte m谩s grave como "out of scope". Si est谩 fuera de alcance, ¿por qu茅 pagan?

Por primera vez, despu茅s de m谩s de 400 vulnerabilidades descubiertas y documentadas a lo largo de estos a帽os, he sido recompensado con 250 d贸lares por la primera parte de mi trabajo. Ni la cantidad, ni la forma en que se ha gestionado la segunda parte de la investigaci贸n reflejan el alcance ni la gravedad de las vulnerabilidades documentadas

Matem谩ticamente, teniendo en cuenta que pueden ser 2.500 millones de dispositivos afectados, eso es 0,0000001 d贸lares por dispositivo. Es decir, menos de una diezmil茅sima parte de un c茅ntimo por cada tel茅fono vulnerable.


11. Conclusi贸n: 10 a帽os de c贸digo vulnerable

El an谩lisis del c贸digo fuente de AOSP confirma que la vulnerabilidad en libminikin no es un bug aislado, sino un fallo de dise帽o sist茅mico presente en el n煤cleo de Android desde 2013.

馃敶 Lo que sabemos ahora:

  • 6 archivos vulnerables en AOSP.
  • 5 capas del pipeline de texto sin validaci贸n.
  • 10 a帽os de evidencia documentada (2013 → 2026).
  • Google ha tenido m谩s de 10 a帽os para arreglar esto.
  • Ha arreglado los casos triviales (CVE-2016-2414) e ignorado los complejos.

El 30 de julio de 2026 publicar茅 el whitepaper completo con los 31 vectores documentados, las trazas nativas completas y el an谩lisis forense del c贸digo fuente. Si tu aplicaci贸n usa TextView, ya est谩s avisado.

馃搶 Para desarrolladores (mitigaci贸n inmediata):

private static final int MAX_SAFE_LENGTH = 8192;
String safe = text.length() > MAX_SAFE_LENGTH 
    ? text.substring(0, MAX_SAFE_LENGTH) + "…" 
    : text;
textView.setText(safe);

12. Referencias y enlaces

Art铆culos del investigador

Issues p煤blicos de Google

C贸digo fuente de AOSP

馃敟 1.6 Minikin es un s铆ntoma de una brecha de resiliencia sist茅mica

La vulnerabilidad de libminikin no es un bug aislado. Es un s铆ntoma de una brecha de resiliencia sist茅mica en el framework de Android: la ausencia de un mecanismo estandarizado de "safe fallback" para manejar datos que superan los l铆mites del sistema.

El mismo patr贸n aparece en al menos diez componentes distintos del sistema operativo Android:

Componente Modo de fallo Impacto
FragmentManager No captura TransactionTooLargeException Bucle de crash permanente
TaskPersister Persiste el estado corrupto en disco El bucle de crash sobrevive a reinicios
SystemUI Lee TaskPersister sin validaci贸n Bucle de crash → pantalla de bloqueo
Print Service Sin validaci贸n del tama帽o del documento SystemUI crash
ClipboardManager Serializa todo el contenido del portapapeles sin l铆mites SystemUI crash
Binder L铆mite de 1MB sin safe fallback Crash de la app
libminikin.so Sin validaci贸n de longitud de entrada ANR (5–16s)
LayoutCache CHAR_LIMIT_FOR_CACHE fuerza el procesamiento directo Amplifica el DoS
BitmapCache Sin validaci贸n del tama帽o de imagen (issue #531319203) Crash de system_server → bucle de arranque
MediaSession Sin validaci贸n del tama帽o de la car谩tula Crash de system_server → bucle de arranque

馃敶 Diez componentes. Diez modos de fallo diferentes. El mismo patr贸n subyacente: sin validaci贸n de entrada antes del procesamiento, y sin safe fallback cuando se superan los l铆mites.

Esto no es un bug de Minikin. Es un fallo de dise帽o del framework de Android que ha estado presente durante m谩s de una d茅cada, afectando a componentes que van desde la capa de aplicaci贸n hasta el servidor central del sistema. Google ha a帽adido capas de complejidad a Minikin sin abordar la causa ra铆z, y ha descartado los informes de estos problemas como "fuera de alcance" o "comportamiento intencionado" durante a帽os.

Minikin no es la enfermedad. Es un s铆ntoma.



#Lostmon #Android #AOSP #Ciberseguridad #MobileSecurity #SystemUI #libminikin #STA #StructuredTextAmplification #BugBounty #GoogleVRP #Xiaomi #HackerOne #SaludMental #Investigaci贸nIndependiente #BojosXtu
Manuel Garcia Pe帽a (Lostmon) · lostmon@gmail.com · lostmon.blogspot.com
Whitepaper completo: 30 de julio de 2026

Algorithmic DoS en libminikin.so

Wednesday, June 24, 2026
Algorithmic DoS en libminikin.so – C贸mo un texto de 70 KB puede congelar casi cualquier app Android 
 

Un texto de 70.000 caracteres puede congelar casi cualquier app de  Android durante 10–16 segundos. No es corrupci贸n de memoria. Es un ataque algor铆tmico que explota la complejidad O(n²) del motor de dise帽o de texto nativo de Android. Y lo peor: cualquier aplicaci贸n con un TextView es vulnerable.

A diferencia de muchas vulnerabilidades que requieren aplicaciones de prueba espec铆ficas para su reproducci贸n, varios de los vectores documentados pueden activarse simplemente mediante enlaces especialmente construidos que son procesados por componentes est谩ndar del sistema Android. Esto ampl铆a significativamente la superficie de exposici贸n potencial

He documentado 31 vectores en 9 empresas, incluyendo Google, Meta, Microsoft, Mozilla, Opera, DuckDuckGo, Brave, Tor Project y Xiaomi. El fallo reside en libminikin.so, el motor de dise帽o de texto de Android, y afecta a todos los dispositivos con Android 9 a 16.


1. El problema: Algoritmos que se vuelven en tu contra

libminikin.so implementa el algoritmo de salto de l铆nea 贸ptimo (Knuth-Plass) en la funci贸n LineBreakOptimizer::computeBreaks. Este algoritmo tiene complejidad O(n²) en el peor caso: si duplicas la longitud del texto, el tiempo de procesamiento se multiplica por cuatro.

Para un texto normal de 200 caracteres, el tiempo es imperceptible. Pero para uno de 70.000 caracteres con la estructura adecuada, el algoritmo ejecuta millones de operaciones y bloquea el hilo de la interfaz durante m谩s de 10 segundos.

El vector documentado en libminikin no requiere una aplicaci贸n de demostraci贸n espec铆fica. En los escenarios analizados, basta con que un componente del sistema represente una URL especialmente construida en un TextView para activar el c谩lculo intensivo del algoritmo de composici贸n de texto.

馃搶 Idea clave: No es la longitud, es la estructura. Una URL con caracteres como #, /, % y multiplica el n煤mero de "candidatos a salto de l铆nea", y el algoritmo se dispara.

2. La estructura del ataque: Caracteres que multiplican el caos

Car谩cter Funci贸n en la URL Efecto en libminikin
# Fragmento (separador l贸gico) Duplica las decisiones de salto de l铆nea
/ Separador de rutas Cada barra es un punto de ruptura → O(n²) con el n煤mero de barras
% Codificaci贸n porcentual Expansi贸n UTF-8 → UTF-16, fragmenta la cadena
Car谩cter multibyte Propiedades de salto de l铆nea ambiguas → el algoritmo explora ambas opciones

El patr贸n 贸ptimo repite miles de veces. Cada 9 bytes generan m煤ltiples puntos de decisi贸n y el algoritmo explota.

Resultado: La UI se congela durante 10–16 segundos. El stack trace nativo confirma que libminikin es el 煤nico responsable.

4. Vectores de ataque: M谩s all谩 de los navegadores

El fallo no se limita a los navegadores. Cualquier aplicaci贸n que muestre texto en un TextView sin truncar es un vector de ataque:

Componente / Aplicaci贸n ¿Muestra URL larga? Vulnerabilidad observada
Chrome (men煤 contextual) S铆 ✅ ANR de 5+ segundos
Firefox (di谩logo externo) S铆 ✅ ANR de 16 segundos (enlace real de Google Drive)
Opera / Opera Mini S铆 ✅ Crash con TransactionTooLargeException
DuckDuckGo S铆 (historial) ✅ Bucle de cierre permanente
Google drive S铆 ⚠️ Potencial
WhatsApp (vista previa de enlace) S铆 ⚠️ Potencial
Cualquier app con TextView S铆 ✅ Confirmado con PoC

5. El vector cr铆tico: STA-015-DL (SystemUI crash loop)

馃敟 CVSS 8.6 (CR脥TICO) – Un solo clic en un enlace de Google Drive puede provocar un bucle de cierre de SystemUI que requiere reinicio forzado.

La cadena de ataque STA-015-DL demuestra que el problema trasciende las aplicaciones y afecta a SystemUI, la interfaz del sistema:

  1. La v铆ctima hace clic en un archivo HTML alojado en Google Drive.
  2. Google Drive lanza un Intent.ACTION_VIEW con una URL malformada.
  3. La URL bypasea todas las validaciones del navegador porque llega a trav茅s de callingPackage=com.google.android.apps.docs (certificado por Android).
  4. La URL corrompe el estado de TaskPersister en disco.
  5. SystemUI intenta leer el estado → DeadObjectExceptionbucle de cierre.
  6. Recuperaci贸n: reinicio forzado del dispositivo.

Evidencia de campo: Un dispositivo en producci贸n (Xiaomi Redmi Note 14 5G, Android 16) registr贸 85 SystemUI crashes en 4 d铆as, con un tiempo m铆nimo de supervivencia de 374ms.

// SystemUI crash en el arranque – bugreport 2026-05-26 // Process-Runtime: 374ms – crashea antes de renderizar cualquier UI android.os.BadParcelableException: Failure retrieving array; only received 1 of 4 at android.content.pm.BaseParceledListSlice.<init>(...) at com.android.wm.shell.sysui.ShellInit.init(...) ← crash en el arranque Caused by: android.os.DeadObjectException: Transaction failed on small parcel

6. Stack traces nativos (evidencia forense)

Chrome – Men煤 contextual (24 de mayo de 2026)

// ANR — Chrome PID 3533 "main" prio=5 tid=1 Native ← UI THREAD BLOCKED native: minikin::getPrevWordBreakForCache libminikin.so native: minikin::LayoutCacheKey::LayoutCacheKey libminikin.so native: minikin::LayoutCache::getOrCreate libminikin.so native: minikin::StyleRun::getLineMetrics libminikin.so native: minikin::MeasuredText::getLineMetrics libminikin.so native: minikin::LineBreakOptimizer::computeBreaks ← O(n²) en URL larga native: minikin::breakLineOptimal libminikin.so native: android::nComputeLineBreaks libhwui.so at android.widget.TextView.onMeasure (TextView.java:11486) at org.chromium.chrome.browser.contextmenu.ContextMenuListView.onMeasure ↑ MEN脷 CONTEXTUAL DE CHROME — long-press en URL sobredimensionada

Firefox – Di谩logo de aplicaci贸n externa (10 de junio de 2026)

// org.mozilla.firefox PID 3506 — ANR 2026-06-10 — 16.006 ms "main" prio=5 tid=1 Native ← UI THREAD BLOCKED 16.006 ms native: minikin::LayoutCacheKey::LayoutCacheKey+120 libminikin.so native: minikin::LayoutCache::getOrCreate libminikin.so native: minikin::LayoutPieces::getOrCreate libminikin.so native: minikin::StyleRun::getLineMetrics libminikin.so native: minikin::MeasuredText::getLineMetrics libminikin.so native: minikin::LineBreakOptimizer::computeBreaks+1752 ← O(n²) en URL larga native: minikin::breakLineOptimal+476 libminikin.so native: android::nComputeLineBreaks+356 libhwui.so at org.mozilla.fenix.customtabs.ExternalAppBrowserActivity URL rendering // Trigger: Enlace REAL de Google.Drive — NO una prueba controlada

7. Mitigaci贸n

7.1 A nivel de framework (Google/AOSP)

Google deber铆a implementar un l铆mite de entrada antes de ejecutar el algoritmo O(n²):

// En LineBreakOptimizer.cpp if (textLength > MAX_SAFE_TEXT_LENGTH_FOR_OPTIMIZER) { return computeBreaksGreedy(measured, start, end, constraints); // O(n) }

7.2 A nivel de aplicaci贸n (inmediato)

Los desarrolladores pueden truncar el texto antes de mostrarlo en un TextView:

private static final int MAX_SAFE_LENGTH = 8_192; String safe = text.length() > MAX_SAFE_LENGTH ? text.substring(0, MAX_SAFE_LENGTH) + "…" : text; textView.setText(safe);

8. Conclusi贸n

La complejidad O(n²) en libminikin convierte una URL de 70 KB en un arma de denegaci贸n de servicio que puede congelar cualquier app Android que la muestre en un TextView sin truncar. No es corrupci贸n de memoria, es explotaci贸n algor铆tmica — usar la propia complejidad del sistema en su contra.

Google ha empezado a moverse (LargePayloadSupport, savedstate 1.5.0), pero no hay parche p煤blico para libminikin a fecha de junio de 2026. La comunidad y los desarrolladores pueden aplicar mitigaciones inmediatas truncando el texto antes de mostrarlo.

Nota sobre el proceso de divulgaci贸n Esta vulnerabilidad fue notificada inicialmente al Android Vulnerability Rewards Program (VRP) el 20 de enero de 2026, como parte de una investigaci贸n m谩s amplia. El reporte espec铆fico sobre la vulnerabilidad de complejidad algor铆tmica en libminikin.so fue presentado el 15 de junio de 2026. El reporte fue cerrado con la clasificaci贸n "Out of Scope". Posteriormente, el 21 de junio de 2026, se present贸 una apelaci贸n acompa帽ada de evidencia adicional, incluyendo informes ANR, trazas de pila nativas y resultados obtenidos durante la investigaci贸n. La apelaci贸n fue finalmente cerrada con la clasificaci贸n "Not Reproducible". El an谩lisis t茅cnico y la evidencia presentada en este art铆culo reflejan los resultados obtenidos durante la investigaci贸n independiente realizada por el autor y se publican con fines de investigaci贸n, documentaci贸n y mejora de la seguridad.

Ap茅ndice: Nuevo caso reproducible (28 de junio de 2026) – Google App / Android Translate

Desde la publicaci贸n inicial de este an谩lisis, he seguido monitorizando el comportamiento del sistema. El pasado 28 de junio de 2026 apareci贸 un segundo caso, completamente independiente del anterior, que no hace sino reforzar la hip贸tesis planteada.

Mientras que el primer vector documentado en la secci贸n 4 utilizaba StaticLayout y breakLineOptimal(), este nuevo caso utiliza DynamicLayout y breakLineGreedy() durante el procesamiento de texto iniciado por Android System Intelligence mediante un android.intent.action.TRANSLATE.

Secuencia observada

Usuario selecciona texto
  ▼
Android System Intelligence
  ▼
Google App (ImplicitTranslateSearchEntrypointInternal)
  ▼
SpannableStringBuilder.replace()
  ▼
DynamicLayout.reflow()
  ▼
libminikin::breakLineGreedy()
  ▼
getPrevWordBreakForCache()
  ▼
ANR (Application Not Responding)

Cinco ANR consecutivos

El mismo texto produjo cinco ANR consecutivos en aproximadamente catorce minutos. Todos compart铆an el mismo patr贸n:

  • Main thread bloqueado durante m谩s de 6 segundos.
  • Entrada por DynamicLayout.
  • Ejecuci贸n dentro de libminikin.
  • Funciones getPrevWordBreakForCache() o getNextWordBreakForCache().

Despu茅s de varios ANR, el proceso tambi茅n comenz贸 a finalizar con TransactionTooLargeException durante la restauraci贸n del estado de la actividad, un efecto secundario posterior al bloqueo del hilo principal que conecta directamente con el fen贸meno de amplificaci贸n estructural descrito en la secci贸n 5.

Comparaci贸n con el caso de Edge

Aspecto Microsoft Edge Google App
Layout StaticLayout DynamicLayout
Algoritmo breakLineOptimal() breakLineGreedy()
Desencadenante Re‑layout tras cambio del sistema Reflow tras modificar texto
Entrada Omnibox Traductor integrado
ANR 1 ANR 5 ANR consecutivos

Aunque las rutas son diferentes, ambas convergen en el mismo componente del framework:

          StaticLayout
              │
              ├──► breakLineOptimal()
              │
          DynamicLayout
              │
              ├──► breakLineGreedy()
              │
              ▼
         libminikin
              │
              ├──► getPrevWordBreakForCache()
              └──► getNextWordBreakForCache()

Implicaciones

Este segundo caso reduce significativamente la probabilidad de que el problema sea espec铆fico de una aplicaci贸n concreta. Ahora existen al menos dos aplicaciones independientes, con dos flujos de ejecuci贸n distintos y dos algoritmos de line breaking diferentes, que terminan bloqueando el hilo principal dentro de libminikin sobre la misma versi贸n de Android 16 (BuildId 4fabe53671b5ead88314c00a1fd6d67d).

En otras palabras, la evidencia ya no apunta 煤nicamente a un problema asociado a Microsoft Edge, sino a un comportamiento com煤n del framework de composici贸n de texto de Android cuando procesa determinadas entradas.

Este segundo caso demuestra que la Amplificaci贸n de Texto Estructurado no es un fen贸meno limitado a un flujo de ejecuci贸n concreto, sino que puede manifestarse en distintos puntos del framework siempre que el texto pase por las capas de composici贸n y medida de libminikin.

— A帽adido el 28 de junio de 2026

An谩lisis interno del pipeline de layout de Minikin

Tras correlacionar los m煤ltiples ANR obtenidos con el c贸digo fuente de AOSP, la investigaci贸n apunta a que las funciones getPrevWordBreakForCache() y getNextWordBreakForCache() probablemente no constituyen la causa ra铆z del problema, sino que forman parte de un pipeline de composici贸n de texto mucho m谩s amplio.


DynamicLayout / StaticLayout
            │
            ▼
      MeasuredText
            │
            ▼
     LayoutSplitter
            │
   ┌────────┴────────┐
   ▼                 ▼
getPrevWordBreakForCache()
getNextWordBreakForCache()
            │
            ▼
       LayoutCache
            │
            ▼
       LayoutPiece
            │
            ▼
 WordBreaker / Hyphenation
            │
            ▼
breakLineGreedy() / breakLineOptimal()

El an谩lisis del c贸digo fuente de AOSP muestra que LayoutSplitter utiliza getPrevWordBreakForCache() y getNextWordBreakForCache() para determinar los l铆mites del fragmento de texto que ser谩 almacenado dentro de LayoutCache.

Adem谩s, la implementaci贸n de LayoutCache indica que cuando el texto supera un determinado tama帽o (CHAR_LIMIT_FOR_CACHE), la cach茅 deja de reutilizarse y el sistema debe reconstruir un nuevo LayoutPiece, recalculando el layout completo.


LayoutCache::getOrCreate()

        │

        ├── Cache hit
        │       │
        │       ▼
        │  Reutiliza LayoutPiece
        │
        └── Cache miss
                │
                ▼
      Construcci贸n de LayoutPiece
                │
                ▼
        Glyph shaping
                │
                ▼
         Word breaking
                │
                ▼
      C谩lculo del layout

Esto conduce a una nueva hip贸tesis de trabajo. M谩s que encontrarnos ante un fallo localizado en getPrevWordBreakForCache(), es posible que los ANR sean consecuencia de la reconstrucci贸n repetitiva del pipeline completo de composici贸n de texto cuando la reutilizaci贸n de la cach茅 deja de ser efectiva.

Esta hip贸tesis encaja con los casos observados durante la investigaci贸n:

  • Microsoft Edge alcanza este pipeline mediante StaticLayout y breakLineOptimal().
  • Google Translate lo hace mediante DynamicLayout y breakLineGreedy().
  • Ambas rutas convergen finalmente en la misma infraestructura interna de Minikin encargada de la cach茅 y del c谩lculo de l铆mites de palabra.

Un aspecto especialmente relevante es que Google ha realizado m煤ltiples modificaciones en esta parte del c贸digo fuente de Minikin a lo largo de los 煤ltimos a帽os, incluyendo optimizaciones espec铆ficas del sistema de cach茅 y del rendimiento del motor de layout. Esto sugiere que se trata de una zona considerada cr铆tica desde el punto de vista del rendimiento.

En el momento de redactar este art铆culo, esta explicaci贸n constituye una hip贸tesis fundamentada en la correlaci贸n entre los stack traces de los ANR y el an谩lisis del c贸digo fuente de AOSP. Ser谩 necesario un an谩lisis m谩s profundo —mediante perfilado o reproducci贸n controlada— para determinar si la causa ra铆z corresponde a una invalidaci贸n de la cach茅, un problema de complejidad algor铆tmica o cualquier otro cuello de botella interno del motor de composici贸n de texto de Minikin.


馃敶 Conclusi贸n: Esta evidencia independiente refuerza el argumento de que la vulnerabilidad en libminikin no es un problema espec铆fico de navegadores, sino un fallo fundamental del framework de layout de texto de Android que afecta a todo el ecosistema de aplicaciones Android.

El 30 de julio de 2026 publicar茅 el whitepaper completo con los 31 vectores documentados y la evidencia forense completa. Si tu aplicaci贸n usa TextView, ya est谩s avisado.

#Lostmon #Android #AOSP #Ciberseguridad #MobileSecurity #SystemUI #libminikin #STA #StructuredTextAmplification #BugBounty #GoogleVRP #Xiaomi #HackerOne #SaludMental #Investigaci贸nIndependiente #BojosXtu
Manuel Garcia Pe帽a (Lostmon)
Investigador independiente · lostmon@gmail.com
Blog: 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