Un écran de confidentialité Capacitor masque le contenu de votre app quand l'utilisateur ouvre le sélecteur d'applications et, sur Android, bloque les captures d'écran et l'enregistrement d'écran. Sans cela, iOS et Android prennent une capture de votre dernier écran : un solde bancaire, un dossier médical ou un code à usage unique reste alors visible dans la liste des applications récentes. @capgo/capacitor-privacy-screen ajoutez cela via un seul appel ou un simple flag de configuration, et protégez uniquement les écrans qui en ont besoin.
Ce que le sélecteur d’applications expose
Lorsqu’un utilisateur quitte votre application, les deux systèmes capturent une image de l’écran actuel :
- iOS prend une capture lorsque l’application n’est plus active et l’affiche dans le sélecteur d’applications, ainsi que brièvement lors de sa relance.
- Android affiche un aperçu en direct ou en cache dans Récents.
Toute personne qui jette un coup d’œil au téléphone voit cette capture. C’est aussi le cas de quelqu’un qui partage son écran pendant un appel, ou d’un utilisateur qui enregistre son écran pour un ticket de support. Les captures d’écran sont aussi synchronisées vers les bibliothèques de photos cloud, et c’est là que les données sensibles fuient vraiment.
Quelles applications en ont besoin
| App type | Ce qui peut fuiter |
|---|---|
| Banque, fintech, crypto | Soldes, numéros de carte, IBAN, transactions |
| Gestionnaires de mots de passe, authentificateurs | Mots de passe, codes TOTP, clés de récupération |
| Santé et médical | Diagnostics, ordonnances, résultats d'analyses |
| Messagerie | Conversations privées |
| RH, paie, juridique | Salaires, contrats |
| Rencontres, médias privés | Photos et matchs |
Les revues de sécurité et les tests d'intrusion menés sur ces catégories signalent régulièrement l'absence de protection du sélecteur d'applications. OWASP MASVS prévoit des contrôles sur les données sensibles exposées via l'interface, et les auditeurs testent exactement cela.
Installer
bun add @capgo/capacitor-privacy-screen
bunx cap sync
Le plugin prend en charge Capacitor 8 avec la version 8.x.
Option 1 : protéger toute l'application dès le lancement
Set it in capacitor.config.ts. Le plugin natif lit cette valeur au chargement, avant l’exécution de votre JavaScript, ce qui protège même la première capture d’écran :
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.bank',
appName: 'Example Bank',
webDir: 'dist',
plugins: {
PrivacyScreen: {
enabled: true,
android: {
dimBackground: false,
privacyModeOnActivityHidden: 'splash',
},
ios: {
blurEffect: 'dark',
},
},
},
};
export default config;
Exécutez bunx cap sync après avoir modifié la configuration. L' enabled option est lue uniquement depuis la configuration Capacitor, ce n'est pas une option d'exécution.
Option 2 : protéger certains écrans
import { PrivacyScreen } from '@capgo/capacitor-privacy-screen';
export async function enterSensitiveScreen() {
await PrivacyScreen.enable({
android: { dimBackground: true },
ios: { blurEffect: 'light' },
});
}
export async function leaveSensitiveScreen() {
await PrivacyScreen.disable();
}
const { enabled } = await PrivacyScreen.isEnabled();
Intégrez-les à votre routeur pour couvrir tous les chemins entrants et sortants. Avec Vue Router, par exemple :
router.afterEach(async (to) => {
if (to.meta.sensitive) {
await PrivacyScreen.enable();
} else {
await PrivacyScreen.disable();
}
});
Avec Angular, utilisez un guard ou un NavigationEnd abonnement. Avec React Router, un hook dans votre composant de layout fonctionne. L’essentiel est que la navigation arrière, les deep links et les changements d’onglet passent par la même logique, sinon un écran sensible peut rester non protégé.
Ce que fait chaque option
Android
- La protection utilise
WindowManager.LayoutParams.FLAG_SECURE. Une fois activé, les captures d’écran et les enregistrements d’écran sont bloqués et l’aperçu dans les applications récentes est masqué. dimBackground: trueaffiche un voile sombre dans le sélecteur d'applications. Avecfalse, le plugin affiche votre splash drawable si disponible, sinon il applique un voile sombre.privacyModeOnActivityHiddencontrôle ce qui s'affiche lorsque votre activité est masquée par un autre élément, par exemple le prompt biométrique du système :'none'(par défaut),'dim'ou'splash'.- L'ancienne
preventScreenshotsoption est dépréciée et ignorée.FLAG_SECUREest toujours appliquée lorsque la protection est activée. Pour autoriser une capture d'écran sur un seul écran, appelezdisable()avant cela etenable()après.
iOS
- Lorsque l'application devient inactive, le plugin ajoute un overlay pour que l'aperçu dans le sélecteur d'applications ne montre pas votre contenu.
blurEffect: 'light'ou'dark'utilise le flou natif.'none'(par défaut) affiche votre écran de lancement s'il est disponible, sinon un arrière-plan système.- Lorsqu'elle est activée, le contenu de l'application est également placé dans une couche de rendu sécurisée. Considérez le blocage des captures d'écran sur iOS comme du best effort : Apple ne propose pas de API officiel pour bloquer les captures d'écran, et le comportement peut changer d'une version d'iOS à l'autre.
Le Web
L'implémentation web ne suit que le flag d'activation pour que votre code s'exécute partout. Les navigateurs ne peuvent pas masquer l'aperçu des onglets ni bloquer les captures d'écran.
Combinez-l’avec la biométrie
Un schéma courant pour les applications bancaires : flouter dans le sélecteur d'applications, puis exiger Face ID ou l'empreinte digitale lorsque l'application revient après un certain temps. Le plugin privacyModeOnActivityHidden maintient le contenu masqué tant que le prompt biométrique Android est affiché.
import { App } from '@capacitor/app';
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
// null until the app has really gone to the background
let backgroundedAt: number | null = null;
App.addListener('appStateChange', async ({ isActive }) => {
if (!isActive) {
backgroundedAt = Date.now();
return;
}
const away = backgroundedAt === null ? 0 : Date.now() - backgroundedAt;
backgroundedAt = null;
if (away > 60_000) {
await NativeBiometric.verifyIdentity({ reason: 'Confirm it is you' });
}
});
Consultez le plugin biométrique natif pour la configuration et la gestion des erreurs.
Le plugin officiel et le plugin Capgo
L'équipe Capacitor publie également @capacitor/privacy-screen avec un API très similaire (enable, disable, isEnabled et les mêmes options de plateforme). Le plugin Capgo conserve ce API et ajoute :
enabled: truedans la config Capacitor, afin que la protection soit active avant l'exécution de tout JavaScript. Le plugin officiel ne s'active que via JavaScript.- le rendu sécurisé du contenu sur iOS lorsqu'il est activé, documenté comme faisant partie du comportement du plugin, en plus de l'overlay de l'app switcher.
getPluginVersion()pour le diagnostic.- Une implémentation web qui conserve le flag d'activation, afin que le même code s'exécute dans un aperçu navigateur.
Si vous utilisez déjà le plugin officiel, la transition se résume principalement à un changement d'import.
Les détails UX qui comptent
- Ne bloquez pas les captures d'écran partout sans raison. Les utilisateurs capturent des reçus, des numéros de confirmation ou des réglages. Protégez les écrans contenant des données sensibles, pas toute l'application, sauf si votre politique de sécurité l'exige.
- Expliquez aux utilisateurs pourquoi. Si quelqu'un tente une capture d'écran sur Android et obtient une image noire, une courte note dans votre centre d'aide évite des tickets de support.
- Testez le partage d'écran. Les appels vidéo et le casting sont bloqués sur Android lorsque
FLAG_SECUREest configuré. Si votre application propose un flux « partager l'écran avec le support », désactivez la protection pour celui-ci. - Vérifiez l'accessibilité. Les lecteurs d'écran fonctionnent toujours avec
FLAG_SECURE, mais testez tout de même avec TalkBack et VoiceOver.
Checklist de test
- Ouvrez un écran sensible, puis accédez au sélecteur d’applications. Le contenu doit être masqué sur les deux plateformes.
- Sur Android, essayez une capture d’écran et un enregistrement de l’écran. Les deux doivent être noirs ou bloqués.
- Déclenchez une invite biométrique et vérifiez l’arrière-plan.
- Revenez d’un écran sensible vers un écran normal. La protection doit se désactiver si vous utilisez le mode par écran.
- Fermez et relancez l’application. Avec
enabled: truedans la config, la première capture doit être protégée. - Testez sur un iPad avec Split View et Slide Over. L’application peut rester visible lorsqu’elle n’est pas active.
Troubleshooting
Snapshot still shows content on iOS. Vous avez activé la protection après que l'application est passée en arrière-plan, ou uniquement sur certaines routes. Utilisez l'option de configuration pour une protection de toute l'application.
Écran noir dans les applications récentes sur Android au lieu du splash. Définissez dimBackground: false et assurez-vous que votre drawable de splash existe, sinon le plugin bascule sur l'assombrissement.
Screenshots still work on Android. Vérifier isEnabled(). Une autre partie de votre application peut appeler disable() à la navigation.
Protection perdue après une mise à jour OTA. Config values are native. If you change plugins.PrivacyScreen dans capacitor.config.ts, déployez une nouvelle build store. Runtime enable() et disable() dans votre JavaScript peuvent être modifiés avec les live updates Capgo.
Travaux de sécurité associés
Un écran de confidentialité n'est qu'un élément de la checklist sécurité mobile. Pensez aussi au stockage sécurisé, au certificate pinning et à la détection de root. Capgo propose des plugins pour Le SSL pinning et la détection de root et de jailbreak, et notre article sur Apple’s privacy rules for Capacitor apps couvre la partie revue. Les options complètes du plugin sont dans la documentation privacy screen.