Aller au contenu

Liste de contrôle de sécurité pour les applications Flutter

Phase 0 : Gouvernance, environnement et CI/CD

Outillage et versions

  • Maintenir à jour Flutter, le SDK Dart, Android Studio/Xcode, ainsi que l'ensemble des plugins et dépendances.
  • Examiner les avis de sécurité pour les paquets Flutter et les SDK natifs avant chaque release.

Appliquer les contrôles CI (CI gates)

  • Sur chaque PR, exécuter :
  • dart analyze
  • flutter test --coverage
  • Android/Gradle lint
  • Les vérifications de build iOS
  • Les audits des dépendances
  • Faire échouer les builds en cas d'erreurs d'analyseur et d'avertissements configurés comme erreurs.
  • Imposer zéro erreur de lint sur les branches de release.

Établir des contrôles de sécurité (security gates)

  • Exécuter des scans SAST/SCA/DAST mobiles sur chaque PR et avant les releases.
  • Bloquer les builds en cas de résultats de sévérité Élevée/Critique (High/Critical).
  • Intégrer les scans directement dans le pipeline CI/CD afin que les vulnérabilités Élevées/Critiques fassent échouer le pipeline.

Gestion des secrets

  • S'assurer de l'absence totale de secrets dans :
  • Le code source Dart
  • Le code natif
  • AndroidManifest.xml
  • Info.plist
  • Les ressources (assets)
  • Les journaux (logs)
  • Utiliser des variables d'environnement, des coffres de secrets CI et/ou des gestionnaires de secrets.
  • Expurger les secrets dans les outils d'analytics et de journalisation.
  • Effectuer une rotation régulière des clés d'API/jetons et dès qu'une fuite est suspectée.

Preuves et traçabilité

  • Produire et archiver pour chaque artefact :
  • Les rapports de scan
  • Les SBOMs
  • Les journaux de build
  • Les rapports de tests
  • Les notes de version (release notes)

Phase 1 : Modélisation des menaces, classification des données et inventaire

  • Classifier les types de données (PII, identifiants, jetons, données de paiement, données de santé).
  • Documenter où chaque type de donnée est collecté, traité, stocké et transmis dans :
  • Le code de l'application Flutter
  • Les couches natives
  • Identifier les frontières de confiance (trust boundaries) :
  • Le code de l'application Flutter
  • Les canaux de plateforme natifs (platform channels Android/iOS)
  • Le stockage de l'appareil
  • La WebView / le navigateur
  • Les API backend
  • Les services tiers
  • Inventorier l'ensemble des paquets Dart, plugins et SDK natifs.
  • Privilégier les dépendances bien maintenues, signées et appliquant le principe du moindre privilège.
  • Minimiser le nombre total et le périmètre des dépendances.
  • Définir des critères d'acceptation de sécurité par classe de risque (ex. : « Aucune donnée sensible au repos en clair », « Tout le trafic d'authentification épinglé », « Aucun journal de débogage en release »).

Phase 2 : Durcissement du build et de la configuration (Flutter + Android + iOS)

Builds de release Flutter

  • Compiler avec obfusquation et séparation des symboles de débogage pour Android :
  • flutter build appbundle --release --obfuscate --split-debug-info=build/symbols
  • Compiler avec obfusquation et séparation des symboles de débogage pour iOS :
  • flutter build ipa --release --obfuscate --split-debug-info=build/symbols
  • Stocker build/symbols de manière sécurisée côté serveur.
  • Ne jamais inclure les symboles ou les fichiers de mappage dans le bundle de l'application.

Hygiène de journalisation (logging)

  • Protéger les journaux derrière kReleaseMode ou un équivalent.
  • Supprimer print / debugPrint / la journalisation verbeuse des chemins de code de production.
  • Ajouter des vérifications CI pour faire échouer les builds lorsque des journaux de débogage apparaissent dans du code hors tests sur les branches de release.

Android (Gradle + Manifest)

  • Activer R8/ProGuard et la réduction des ressources (resource shrinking) pour la release :
  • minifyEnabled true
  • shrinkResources true
  • Utiliser des règles ProGuard optimisées.
  • Durcir AndroidManifest.xml :
  • android:debuggable="false" en release.
  • android:allowBackup="false" sauf en cas de conception sécurisée des sauvegardes.
  • android:usesCleartextTraffic="false" ; aucun repli HTTP en production.
  • Définir explicitement android:exported sur les composants ; éviter d'exporter sans garde de permissions stricte.
  • Configurer la sécurité réseau (Network Security Config) :
  • Désactiver le trafic en clair globalement.
  • Définir des configurations par domaine.
  • Si l'épinglage (pinning) est utilisé, définir des ensembles d'épingles avec des épingles de secours (backup pins).
  • Signature et intégrité :
  • Utiliser Play App Signing le cas échéant.
  • Protéger les magasins de clés (keystores).
  • Activer la Play Integrity API et intégrer ses signaux aux décisions de risque du backend.

iOS (Xcode + Info.plist au sein du projet Flutter)

  • App Transport Security (ATS) :
  • NSAllowsArbitraryLoads = false.
  • Utiliser des NSExceptionDomains stricts uniquement pour des exceptions nécessaires et limitées dans le temps.
  • Paramètres de build de release :
  • Éliminer les symboles (strip symbols).
  • Activer l'élimination du code mort (dead code stripping).
  • Activer l'optimisation globale du module (whole-module optimization).
  • S'assurer de l'absence d'indicateurs DEBUG ou de bibliothèques de test dans les builds de release.
  • Valeurs par défaut du Keychain pour le stockage natif/plugin :
  • Privilégier les classes ThisDeviceOnly lorsque cela est possible.
  • Masquer les instantanés (snapshots) lors du passage en arrière-plan (via du code natif ou des plugins Flutter) afin que le sélecteur d'applications n'affiche jamais de données sensibles.

Phase 3 : Sécurité réseau et TLS/épinglage (pinning)

Application stricte de HTTPS/TLS

  • S'assurer que tout le trafic d'API utilise HTTPS/TLS 1.2+.
  • Rejeter les certificats invalides, les certificats auto-signés (s'ils ne sont pas explicitement approuvés) et les points de terminaison dont le nom d'hôte ne correspond pas.
  • Configurer des délais d'attente (timeouts) raisonnables.
  • Implémenter des réessais avec gigue (retry with jitter) le cas échéant.
  • Toujours adopter un comportement de fermeture par défaut (fail closed) en cas d'erreur TLS (aucun déclassement vers HTTP).

Épinglage de certificat (certificate pinning)

  • Pour les domaines critiques, implémenter l'épinglage de certificat ou de clé publique SPKI SHA-256 dans :
  • Le client HTTP utilisé par Flutter.
  • Tout réseau natif utilisé par les plugins.
  • Maintenir au moins une épingle de secours (backup pin) par hôte.
  • Concevoir et tester des scénarios de rotation d'épingles.
  • Valider le comportement de l'épinglage face à :
  • Des tentatives de MITM.
  • Des certificats expirés.
  • Des autorités de certification (CA) non approuvées.
  • Journaliser les échecs d'épinglage et remonter la télémétrie.

Sécurité côté serveur

  • Imposer HSTS sur les points de terminaison backend.
  • Utiliser des suites de chiffrement robustes et des versions de protocole modernes.
  • Utiliser des cookies sécurisés, HttpOnly et SameSite pour les points de terminaison web consultés via WebView ou des navigateurs intégrés.
  • Éviter les jetons porteurs (bearer tokens) à longue durée de vie sur le client.

Phase 4 : Stockage local et gestion des secrets

Secrets et jetons

  • Ne jamais stocker de secrets/jetons dans :
  • SharedPreferences
  • Les fichiers plist
  • SQLite non chiffré
  • Des fichiers en texte clair depuis Dart
  • Ne pas intégrer de secrets dans :
  • Les valeurs const
  • Les ressources (assets)
  • Le code généré

Stockage sécurisé

  • Utiliser un stockage sécurisé lié aux magasins de clés de la plateforme pour les jetons et les clés (ex. : Android Keystore, Keychain iOS via des plugins Flutter).
  • Lorsque l'expérience utilisateur le permet, conditionner le déchiffrement/l'utilisation des clés à haut risque à la biométrie ou au code de déverrouillage du système.
  • Privilégier les clés liées à l'appareil (ThisDeviceOnly / adossées au matériel) pour les jetons de grande valeur.

Stockage chiffré (fichiers/bases de données)

  • Utiliser SQLite chiffré ou un chiffrement de fichiers équivalent pour les enregistrements sensibles.
  • S'assurer que les couches de cache (ex. : cache HTTP, persistance locale) ne stockent pas de PII ou de secrets en clair.

Cycle de vie des données

  • Effacer :
  • Les caches
  • Les entrées du stockage sécurisé
  • Les objets sensibles en mémoire
    lors de la déconnexion et de la suppression du compte.
  • Nettoyer les données de WebView ou du navigateur in-app après les flux d'authentification ou les sessions à haut risque.
  • Configurer les règles de sauvegarde Android/iOS pour empêcher la sauvegarde de données applicatives sensibles sous forme non chiffrée.

Phase 5 : Protections de la vie privée (interface, presse-papiers, captures d'écran)

  • Masquer les écrans Flutter sensibles lorsque l'application est en arrière-plan ou dans le sélecteur de tâches :
  • FLAG_SECURE sur Android.
  • Masquage d'instantané (snapshot masking) sur iOS.
  • Pour les vues extrêmement sensibles (ex. : numéros de carte complets, secrets), utiliser un modèle d'« écran sécurisé » dédié avec :
  • Masquage renforcé.
  • Aucune prise en charge des captures d'écran ou des enregistrements d'écran.
  • Éviter de lire le presse-papiers au lancement de l'application.
  • Ne jamais placer de mots de passe, de jetons ou de liens de réinitialisation dans le presse-papiers.
  • S'assurer que les captures d'écran ou exportations intégrées à l'application omettent les secrets/PII, sauf si cela est explicitement requis et clairement communiqué à l'utilisateur.

Phase 6 : Authentification, autorisation et session

Flux d'authentification

  • Utiliser OAuth2/OIDC avec PKCE pour les clients Flutter publics.
  • Ne pas intégrer de secrets client (client secrets) dans l'application.
  • Préférer le navigateur système / les flux d'authentification de la plateforme :
  • Chrome Custom Tabs sur Android.
  • SFSafariViewController / ASWebAuthenticationSession sur iOS via des plugins.
  • Éviter la connexion au sein d'une WebView lorsque cela est possible.

Jetons

  • Utiliser des jetons d'accès (access tokens) à courte durée de vie.
  • Stocker les jetons d'actualisation (refresh tokens) uniquement dans un stockage sécurisé lié aux magasins de clés de la plateforme.
  • Effectuer une rotation régulière des jetons.
  • Invalider les jetons lors de :
  • La déconnexion.
  • Un changement d'appareil.
  • Comportements suspects.
  • Envisager la liaison à l'appareil (device binding) et des contrôles basés sur le risque pour les actions hautement sensibles, à l'aide des signaux d'appareil d'Android et d'iOS.

Autorisation

  • Appliquer le contrôle d'accès sur le serveur.
  • Ne pas se fier à la logique Dart/UI pour protéger les ressources.
  • Tester l'absence de :
  • IDOR/BOLA.
  • Assignation de masse (mass assignment).
  • Élévation de privilèges verticale et horizontale
    sur l'ensemble des points de terminaison d'API utilisés par l'application Flutter.

Phase 7 : Durcissement des WebViews et flux basés sur le navigateur

Modèle recommandé

  • Utiliser le navigateur système / les vues web sécurisées fournies par la plateforme pour l'authentification et les paiements lorsque cela est possible :
  • Custom Tabs.
  • SFSafariViewController.

Si une WebView est requise (WebView Flutter ou native)

  • Désactiver JavaScript par défaut.
  • N'activer JavaScript que si explicitement requis, puis en limiter les capacités.
  • Restreindre la navigation à une liste d'autorisation (allowlist) d'hôtes et de schémas de confiance.
  • Bloquer file://, javascript: et les autres URL dangereuses.
  • Désactiver le débogage de contenu web dans les builds de release sur Android et iOS.
  • Effacer les cookies, le cache et le stockage de la WebView après les sessions sensibles (authentification, paiements, modification de PII).
  • S'assurer que le contenu web interne (first-party) :
  • Applique une CSP.
  • Utilise exclusivement HTTPS.
  • Ne comporte aucun contenu mixte (mixed content).

Phase 8 : Communication entre applications, liens profonds et canaux de plateforme

  • Privilégier les Android App Links et les Universal Links iOS pour les liens profonds.
  • Valider l'origine des liens avant d'agir.
  • Valider et assainir les paramètres des liens avant toute action.
  • Éviter les schémas d'URL personnalisés non sécurisés.
  • Si des schémas personnalisés sont utilisés :
  • Choisir des schémas uniques.
  • Valider de manière robuste tous les paramètres et redirections.

Canaux de plateforme (MethodChannel / EventChannel)

  • Traiter toutes les données transitant de Flutter vers le natif et inversement comme non fiables jusqu'à validation.
  • Valider les noms de méthodes et les paramètres du côté natif.
  • Éviter d'exposer des API natives puissantes directement via les canaux.
  • Ne jamais transmettre de données brutes non fiables provenant de Flutter directement à des appels natifs privilégiés (système de fichiers, paramètres système, télécoms, etc.) sans validation ni assainissement.
  • Tester par fuzzing les entrées des canaux de plateforme pendant les tests.
  • Journaliser et gérer de manière sécurisée les appels de méthodes inattendus ou les données malformées.

Phase 9 : Rétro-ingénierie et résistance à la falsification (tamper resilience)

Réduire les fuites statiques

  • Obfusquer le code Dart.
  • Activer R8/ProGuard/la réduction des ressources pour Android.
  • Retirer les symboles et les informations de débogage des binaires distribués sur les deux plateformes.
  • Supprimer les journaux verbeux, les menus de débogage, les points de terminaison de test, les feature flags masqués et les portes dérobées dans les builds de release.
  • Éviter d'intégrer des secrets ou de la logique métier sensible sous une forme facilement extractible (ex. : chaînes en clair dans les assets).

Vérifications de l'environnement

  • Ajouter une détection de root/jailbreak/hooking/débogeur sur Android et iOS (via des plugins ou du code natif).
  • Journaliser les signaux détectés pour la surveillance de la sécurité.
  • Réagir proportionnellement :
  • Dégrader les fonctionnalités.
  • Ajouter une vérification supplémentaire.
  • Bloquer les opérations à haut risque
    au lieu de poursuivre silencieusement comme si de rien n'était.

Tests de falsification et intégrité

  • Valider que les applications Flutter réempaquetées ou resignées sont détectées via des vérifications d'intégrité ou une attestation côté serveur :
  • Play Integrity (Android).
  • Contrôles d'appareil sur iOS (DeviceCheck / App Attest).
  • Traiter les contrôles anti-falsification côté client comme des signaux transmis au backend.
  • Ne jamais utiliser les contrôles anti-falsification côté client comme unique contrôle de sécurité.

Phase 10 : Cryptographie et aléa

  • Utiliser des bibliothèques cryptographiques reconnues et approuvées par la plateforme (ex. : plugins encapsulant Android Keystore/iOS Keychain ou bibliothèques cryptographiques rigoureusement auditées).
  • Ne pas implémenter d'algorithmes cryptographiques personnalisés en Dart.
  • Pour le chiffrement, utiliser des modes AEAD modernes :
  • AES-GCM.
  • ChaCha20-Poly1305.
  • Pour les KDFs, utiliser :
  • PBKDF2.
  • HKDF
    avec des paramètres appropriés et des sels uniques par valeur.
  • Générer les clés, les IV et les nonces à l'aide d'un générateur d'aléa sécurisé (SecureRandom ou générateurs de nombres aléatoires de la plateforme via des plugins).
  • Ne jamais réutiliser d'IV/nonces.
  • Conserver les clés cryptographiques dans un stockage protégé par Keystore/Keychain ou chiffré au repos, et non en mémoire ou dans la configuration plus longtemps que nécessaire.

Phase 11 : Permissions, notifications et identifiants

Permissions

  • Demander le strict minimum de permissions nécessaires.
  • Ne demander les permissions qu'au moment opportun de leur utilisation (point-of-use).
  • Fournir une expérience utilisateur (UX) claire expliquant pourquoi chaque permission est requise.
  • Implémenter des parcours de refus et de révocation sans plantage (fonctionnalités limitées au lieu de crashs ou d'invites répétées en boucle).

Confidentialité et identifiants

  • N'utiliser les identifiants publicitaires et d'analytics (ex. : GAID/IDFA) que conformément aux politiques des plateformes, avec des flux de consentement appropriés.
  • Éviter de mettre en place une empreinte persistante inter-applications (fingerprinting) avec :
  • Des identifiants matériels.
  • Des adresses MAC.
  • D'autres identifiants interdits.

Notifications

  • Minimiser le contenu sensible dans les notifications push et locales.
  • Utiliser des titres et descriptions génériques pour les notifications affichées sur l'écran de verrouillage.
  • Permettre aux utilisateurs de configurer les catégories et la sensibilité des notifications.
  • Ne jamais inclure de secrets ou de PII complètes dans les charges utiles (payloads) de notification.

Phase 12 : Journalisation, analytics et rapports de crash

  • Standardiser sur une journalisation structurée.
  • Désactiver la journalisation verbeuse/de débogage dans les builds de release.
  • Expurger les PII et les secrets des :
  • Journaux
  • Événements d'analytics
  • Rapports de crash
  • Privilégier l'agrégation et l'échantillonnage pour les analytics.
  • Stocker les fichiers de symboles/mappage (Flutter split debug info, correspondances R8, dSYMs) de manière sécurisée côté serveur pour la désobfuscation des crashs.
  • Ne jamais inclure les fichiers de symboles/mappage dans le bundle de l'application.
  • Examiner régulièrement les événements d'analytics et les journaux pour détecter d'éventuelles données inattendues (champs sensibles, paramètres d'URL, en-têtes, payloads).

Phase 13 : Tests, DAST et vérification à l'exécution

Tests d'interception du trafic

  • Vérifier que la validation TLS rejette :
  • Les certificats invalides.
  • Les certificats expirés.
  • Les certificats auto-signés (sauf s'ils sont explicitement approuvés).
  • Les non-concordances de nom d'hôte.
  • Confirmer que l'épinglage de certificat (lorsqu'il est activé) bloque les outils d'interception MITM.

Inspection à l'exécution (runtime)

  • Pendant les tests, inspecter :
  • Le stockage de l'application (SharedPreferences, fichiers, bases de données).
  • Le stockage WebView.
  • Les journaux
    à la recherche de secrets/PII.
  • Confirmer que le stockage sécurisé et le chiffrement sont correctement appliqués.
  • Confirmer que le nettoyage lors de la déconnexion et de la suppression du compte est effectif.

Tests d'abus d'API

  • Valider :
  • Les limitations de débit (rate limits).
  • Les protections contre le rejeu (replay protections).
  • Les limites de pagination.
  • La validation des entrées
    pour toutes les API utilisées par l'application Flutter.
  • Vérifier que les messages d'erreur du serveur ne sont pas excessivement verbeux et ne font pas fuiter de détails d'implémentation.

Analyse dynamique et DAST

  • Exécuter des outils DAST mobiles tout en parcourant les flux fondamentaux de Flutter (authentification, paiements, profil, paramètres).
  • Utiliser le DAST pour révéler :
  • Les problèmes de transport.
  • Les problèmes de stockage.
  • Les problèmes de WebView.
  • Exporter les preuves pour le triage.
  • Corriger les vulnérabilités découvertes et re-tester avant de promouvoir les builds.

Phase 14 : SBOM et preuves

SBOM et dépendances

  • Générer et archiver des SBOMs pour :
  • Flutter (pubspec.lock).
  • Les modules natifs (Gradle/CocoaPods).
  • Suivre les CVE et les avis de sécurité pour l'ensemble de vos paquets au fil du temps.
  • Planifier des actualisations de dépendances dans le cadre de la préparation des releases.

Dossier de preuves (evidence bundle)

  • Joindre à chaque dossier de release :
  • Les rapports SAST/SCA/DAST.
  • Les SBOMs.
  • Les configurations de build (obfusquation, épinglage, ATS/networkSecurityConfig).
  • Les rapports de tests (automatisés et manuels).

Phase 15 : Rapports et alignement sur les normes

Rapports

  • Produire pour les applications Flutter :
  • Résumé managérial (executive summary).
  • Périmètre et méthodologie.
  • Résultats détaillés avec PoC et captures d'écran.
  • Évaluations des risques.
  • Plans de remédiation.
  • Résultats des retests.

Correspondance OWASP MASVS

  • PLATFORM : Phases 2, 7–8, 11.
  • STORAGE : Phases 3–4.
  • CRYPTO : Phase 10.
  • AUTH : Phase 6.
  • NETWORK : Phase 5.
  • CODE : Phases 2, 8, 12.
  • RESILIENCE : Phase 9.

Référence rapide pour les praticiens

  • Builds : --obfuscate --split-debug-info, R8 minifyEnabled true, shrinkResources true ; aucun symbole de débogage dans les artefacts distribués.
  • Réseau : HTTPS uniquement ; épinglage de certificat/SPKI (avec épingles de secours) pour les API critiques ; vérifier l'échec des attaques MITM.
  • Stockage : Stockage sécurisé pour les jetons ; base de données/fichiers chiffrés pour les données sensibles ; purge à la déconnexion ; prévention des sauvegardes sensibles.
  • Auth : OIDC + PKCE ; jetons à courte durée de vie ; jetons de rafraîchissement dans un stockage sécurisé ; autorisation côté serveur ; tester l'absence d'IDOR/BOLA.
  • WebView : Préférer le navigateur système pour l'authentification ; si une WebView est utilisée, désactiver JS par défaut, appliquer une allowlist de navigation, purger les données après les flux sensibles.
  • Confidentialité : Masquer les instantanés d'arrière-plan via les indicateurs de plateforme ; éviter les secrets dans le presse-papiers ; permissions minimales avec une UX claire.
  • Contrôles CI : Bloquer en cas de vulnérabilité Élevée/Critique en SAST/SCA ; exiger « zéro vulnérabilité Élevée » en DAST ; zéro erreur d'analyseur/linter pour la release.