El portapapeles del sistema es un canal global entre apps, y una página WebView puede leer todo lo que copió tu usuario: tarjetas, contraseñas, códigos de un solo uso. En Android el portapapeles era legible por cualquier app en segundo plano antes de Android 10 y solo ganó un aviso y una marca de datos sensibles en Android 12. En iOS, el portapapeles general es del sistema, persiste tras reinicios y se sincroniza entre dispositivos vía Universal Clipboard; iOS 14 añadió aviso de lectura e iOS 16 un aviso de pegado. Pero la ruta de lectura web dentro de un WebView queda fuera de esas mitigaciones nativas: una página con acceso al portapapeles y un gesto del usuario puede cosechar las credenciales que la app acaba de copiar. Un runtime propio del host media el portapapeles en la capa nativa: marca los elementos sensibles como localOnly con expiración y condiciona las lecturas web a la intención explícita del usuario.

El portapapeles era una escucha global

El portapapeles de Android es un framework para copiar y pegar datos entre aplicaciones, y una implementación pobre expone los datos del usuario a otras apps (Android Developers, OWASP MASVS-CODE). La exposición varía según la versión: antes de Android 10, las apps en segundo plano podían leer en silencio el portapapeles de la app en primer plano —cualquier contraseña, código OTP o número de tarjeta copiado quedaba disponible para una app maliciosa. Desde Android 12, el sistema muestra un aviso cada vez que una app accede al portapapeles, y los desarrolladores pueden marcar datos sensibles con EXTRA_IS_SENSITIVE para ofuscar la vista previa en el teclado. Eso ayuda a las escrituras nativas, pero no hace nada contra lo que lee una página web.

iOS lo hace persistente y sincronizado

En iOS, el portapapeles general se comparte entre todas las apps en primer plano y, desde iOS 10, se sincroniza con dispositivos Apple cercanos mediante Universal Clipboard; persiste tras reinicios y reinstalaciones salvo que se borre (OWASP MASTG-KNOW-0083). Desde iOS 14 el sistema avisa cuando una app lee contenido escrito por otra app, y desde iOS 16 pide confirmación de pegado. Los portapapeles con nombre tienen alcance por app o equipo, pero la mayoría de las apps usan el general. El aviso de permiso también es un impuesto: las apps de comercio que leen el portapapeles al iniciar para detectar enlaces copiados ahora bombardean al usuario con avisos de pegado —y detectPatterns aún puede revelar que el portapapeles se parece a una URL, número o teléfono sin devolver su valor.

Dentro de un WebView, la web también lo lee

Aquí está la parte que las mitigaciones del sistema operativo pasan por alto. Una página WebView puede invocar la Clipboard API o execCommand('paste') con un gesto del usuario y leer lo que este copió. Suma eso a los patrones de autocompletado y lectura automática de OTP ya comunes en apps híbridas, y una página de catálogo maliciosa o comprometida se vuelve un cosechador de credenciales: el usuario copia un código de un solo uso para iniciar sesión, la página lo lee y la sesión desaparece. La marca nativa EXTRA_IS_SENSITIVE protege lo que tu app escribe, pero la lectura de la página web sigue las mismas reglas de portapapeles del navegador —y un WebView no aplica la intención del host como lo haría una pantalla nativa. El portapapeles, pensado como comodidad, se vuelve una puerta trasera que los propios controles de privacidad de la plataforma no cierran.

La solución del runtime

Un runtime propio del host media el acceso al portapapeles en la capa nativa en lugar de dejarlo a la página. Los elementos sensibles se escriben como localOnly con una expirationDate para que nunca lleguen a Universal Clipboard ni sobrevivan a un reinicio. Las lecturas web del portapapeles se condicionan a la intención explícita del usuario —un control de pegado visible, no una lectura silenciosa— y las entradas de catálogo no confiables se les niega el acceso por completo. La comodidad se queda; la puerta trasera se cierra.

DimensiónWebViewRuntime propio del host
Alcance del portapapelesGlobal, entre apps, en iOS sincronizado y persistenteMediado en capa nativa, localOnly + expiración
Lectura en segundo planoSilenciosa antes de Android 10; aviso desde 12El host controla cada lectura web
Exposición 2FA / OTPEl código copiado legible por cualquier páginaEntradas no confiables denegadas; por intención
Ruta de lectura webClipboard API con gesto, sin controlControl de pegado visible, sin lectura silenciosa
Hueco de mitigación nativaEXTRA_IS_SENSITIVE solo ayuda a escriturasCubre escrituras y lecturas web

El hilo de esta serie vuelve siempre a la misma lección: un WebView hereda las superficies más débiles de la plataforma y añade una con forma de web. El portapapeles es una comodidad que, en un WebView, se vuelve una escucha entre apps y entre páginas que el sistema operativo no puede cerrar del todo. Un runtime pone al host entre la página y el portapapeles —así la comodidad es de la app, y la exposición no.

Fuentes