14.3 Compartir archivos de forma segura entre apps y perfiles
En un entorno de alto nivel de aislamiento como GrapheneOS, la comunicación de archivos entre aplicaciones o perfiles (personal, trabajo u otros perfiles de usuario) debe realizarse con atención rigurosa para evitar fugas de datos, vulneraciones de privacidad o conflictos de permisos. En esta sección exploraremos en detalle los mecanismos nativos de Android mejorados por GrapheneOS, las mejores prácticas para exponer recursos de forma controlada y los pasos concretos para implementar un intercambio de archivos seguro, ya sea entre aplicaciones dentro de un mismo perfil o a través de perfiles separados.
1. Fundamentos de seguridad y aislamiento en GrapheneOS
GrapheneOS refuerza la segmentación habitual de Android en:
- Sandboxes de aplicaciones: cada app reside en un contenedor Linux distinto, sin acceso directo al sistema de archivos de otra app.
- Perfiles de usuario: permiten instancias independientes (p.ej., personal vs. trabajo), con datos y aplicaciones aisladas unas de otras.
- Scoped Storage: limita el acceso de las apps a carpetas concretas, evitando la exploración indiscriminada de todo el almacenamiento.
Para compartir archivos, es imprescindible cooperar con estos controles de forma explícita, otorgando permisos acotados y precisos.
2. Mecanismos principales de intercambio
-
Intents con URIs seguras
Mediante Intent y URIs firmadas (URI Permissions), se puede enviar un recurso a otra app sin revelar rutas fijas ni otorgar permisos globales:
- Se genera un
content://
URI mediante un FileProvider o DocumentProvider. - Se configura en el manifiesto un
ltprovidergt
con atributosandroid:exported=false
ygrantUriPermissions=true
. - Al lanzar el Intent, se incluyen
FLAG_GRANT_READ_URI_PERMISSION
y/oFLAG_GRANT_WRITE_URI_PERMISSION
.
- Se genera un
-
APIs de Cross-Profile
Android for Work (y GrapheneOS con perfil de trabajo) expone la librería android.content.pm.CrossProfileApps:
- Permite invocar actividades o servicios en otro perfil bajo políticas de perfil definidas por el administrador.
- Se debe solicitar y conceder
INTERACT_ACROSS_PROFILES
o usar APIs explícitas del perfil «Work Profile Owner».
-
SAF (Storage Access Framework)
Ofrece un diálogo unificado para que el usuario seleccione archivos o carpetas, sin requerir permisos de almacenamiento generales:
- Proveedor de documentos (
DocumentProvider
) integrado en el sistema o propio de la app. - Uso de
Intent.ACTION_OPEN_DOCUMENT
oIntent.ACTION_OPEN_DOCUMENT_TREE
. - El usuario controla qué archivos son accesibles y por cuánto tiempo.
- Proveedor de documentos (
3. Configuración y ejemplos en el manifiesto
Un FileProvider típico en AndroidManifest.xml:
-
ltprovider
- android:name=androidx.core.content.FileProvider
- android:authorities={applicationId}.provider
- android:exported=false
- android:grantUriPermissions=truegt
- nbspnbspltmeta-data
- android:name=android.support.FILE_PROVIDER_PATHS
- android:resource=@xml/file_paths /gt
- lt/providergt
En @xml/file_paths
definimos rutas limitadas:
ltpathsgt
nbspnbspltexternal-files-path name=documentos path=Documentos/ /gt
lt/pathsgt
4. Proceso de compartición paso a paso
-
Generar URI segura: utilizar
FileProvider.getUriForFile(context, authority, file)
. -
Crear Intent: configurar acción (
Intent.ACTION_SEND
oACTION_SEND_MULTIPLE
), tipo MIME y extra URI. -
Conceder permisos:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
. -
Iniciar la actividad:
startActivity(Intent.createChooser(intent, Compartir archivo))
.
5. Compartición entre perfiles
-
Perfil estándar a perfil de trabajo
Utilizar CrossProfileApps:
- Obtener instancia:
CrossProfileApps crossProfileApps = context.getSystemService(CrossProfileApps.class)
- Invocar
crossProfileApps.startActivityAsUser(intent, targetUser)
- Obtener instancia:
-
Permisos de administrador
El perfil propietario de trabajo puede definir políticas que permitan o bloqueen explícitamente el intercambio de datos con el perfil personal.
6. Buenas prácticas y consideraciones
- Principio de mínimo privilegio: conceder únicamente permisos de lectura o escritura específicos y por el menor tiempo posible.
- Validación de MIME types: evite aceptar URIs con tipos vagos (p.ej.,
/
), prefieraapplication/pdf
oimage/jpeg
. - Control de caducidad: revocar permisos tras el uso con
revokeUriPermission()
. - Auditoría y registros: documentar en bitácoras cuándo, quién y qué archivos se comparten.
- Protección adicional: cifrado de archivos en reposo y verificación de firmas digitales si procede.
7. Resolución de problemas comunes
-
Error de permiso denegado: verifique
grantUriPermissions=true
y flags de Intent. - URI no reconocida: compruebe que el authority coincide exactamente con el declarado en el manifiesto.
- Fallos de compatibilidad: en Android 11 revise las restricciones de Scoped Storage y considere usar SAF para escenarios complejos.
Gracias a la robusta configuración de aislamiento de GrapheneOS, combinado con la implementación cuidadosa de FileProvider, SAF y Cross-Profile APIs, es posible compartir archivos entre apps y perfiles de forma absolutamente segura, garantizando tanto la confidencialidad como la integridad de los datos.
Profundizando sobre: 14.3 Compartir archivos de forma segura entre apps y perfiles
Libros recomendados:
- Android Security Internals – Nikolay Elenkov: cap. dedicado a IPC y mecanismos de compartición de archivos.
- Android Hacker’s Handbook – Joshua J. Drake et al.: capítulos de proveedores de contenido y almacenamiento seguro.
- Hardening Android – Santiago Fernández Mateos: sección sobre perfiles de usuario y aislamiento de datos.
Recursos en línea:
- GrapheneOS Official Documentation: apartado “Compartir archivos de forma segura entre apps y perfiles”.
- Android Developer – Secure File Sharing: guía práctica con FileProvider y URI permissions.
- Android Developer – Content Providers: fundamentos de proveedores de contenido y acceso controlado.
- GrapheneOS Blog – Private Sharing: artículo sobre flujo de datos entre perfiles con cifrado.
- Google Codelab – Android Security: hands-on de almacenamiento interno/compartido y gestión de permisos.
Deja una respuesta