E-NO
Sécurité Expo 9 min de lecture

Renforcement de la sécurité Expo : guide d'implémentation pratique

calendar_today Publié : 2026-08-19
update Dernière mise à jour : 2026-08-19
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Renforcement de la sécurité Expo : guide d'implémentation pratique ».

Expo simplifie le développement React Native, mais son flux de travail géré peut masquer des configurations critiques pour la sécurité. Ce guide propose une approche centrée sur le praticien pour durcir les applications Expo avec des étapes concrètes, des commandes de vérification et des procédures de récupération. Que vous soyez développeur, consultant DevOps ou équipe technique d'une startup, vous apprendrez à inventorier votre environnement, appliquer des configurations sûres, vérifier les changements localement, gérer les échecs courants et maintenir des opérations de sécurité continues. L'objectif est de réduire le retravail en implémentant la sécurité de manière structurée et incrémentale, facile à inspecter et à valider.

Inventaire des versions et de l'environnement

Avant d'apporter des modifications, établissez une base de référence de votre configuration actuelle. Cela inclut la version du SDK Expo, la version de React Native, la version de Node.js et le gestionnaire de paquets. Exécutez les commandes suivantes à la racine de votre projet :

npx expo --version
npm list react-native
node --version
npm --version

Inspectez votre app.json ou app.config.js pour les paramètres actuels. Consignez tout dans un tableau d'inventaire simple :

ComposantVersionSource
Expo SDK51.0.0package.json
React Native0.74.1package.json
Node.js20.11.0.nvmrc
npm10.2.4npm -v

Mettez à jour ce tableau chaque mois. Un inventaire précis identifie les dépendances obsolètes, les SDK non supportés et la dérive de configuration avant qu'ils ne deviennent des vulnérabilités.

Chemin de configuration sécurisée

Appliquez le durcissement par petits incréments vérifiables. Chaque changement doit être testable localement avant d'être validé.

Gestion des secrets

Ne codez jamais en dur les clés API, jetons ou secrets dans le code source. Utilisez des variables d'environnement avec le champ de configuration extra d'Expo.

Créez un fichier .env à la racine du projet (ajoutez-le au .gitignore) :

API_KEY=votre_cle_api_production
ANALYTICS_TOKEN=votre_jeton_analytics

Configurez app.config.js pour charger ces valeurs :

require('dotenv').config();

export default {
  expo: {
    name: 'MonApp',
    slug: 'mon-app',
    extra: {
      apiKey: process.env.API_KEY,
      analyticsToken: process.env.ANALYTICS_TOKEN,
    },
  },
};

Accédez aux secrets dans votre code d'application :

import Constants from 'expo-constants';

const apiKey = Constants.expoConfig?.extra?.apiKey;

Pour EAS Build, stockez les secrets dans le tableau de bord Expo sous Projet > Secrets plutôt que de les commiter. Cela sépare la configuration au moment de la construction du contrôle de source.

Minimisation des permissions

Ne demandez que les permissions que votre application utilise activement. Chaque permission inutile élargit la surface d'attaque et déclenche un examen supplémentaire des magasins d'applications.

Dans app.json, déclarez explicitement l'ensemble minimal de permissions Android :

{
  "expo": {
    "android": {
      "permissions": [
        "android.permission.INTERNET",
        "android.permission.ACCESS_NETWORK_STATE"
      ]
    }
  }
}

Pour iOS, configurez les chaînes de permission via les plugins de configuration Expo appropriés. Exemple pour l'accès à la caméra :

{
  "expo": {
    "plugins": [
      ["expo-camera", {
        "cameraPermission": "Autoriser $(PRODUCT_NAME) à accéder à votre caméra pour la numérisation de documents"
      }]
    ]
  }
}

Auditez les permissions chaque trimestre. Supprimez toute permission non liée à une fonctionnalité livrée.

Configuration de la sécurité réseau

Appliquez HTTPS et la validation des certificats sur les deux plateformes.

Android : Créez resources/xml/network_security_config.xml :

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="false">
    <trust-anchors>
      <certificates src="system" />
    </trust-anchors>
  </base-config>
  <domain-config>
    <domain includeSubdomains="true">api.votredomaine.com</domain>
    <pin-set expiration="2026-01-01">
      <pin algorithm="SHA-256">pin_spki_encodé_base64_ici</pin>
      <pin algorithm="SHA-256">pin_sauvegarde_encodé_base64_ici</pin>
    </pin-set>
  </domain-config>
</network-security-config>

Référencez-le dans app.json :

{
  "expo": {
    "android": {
      "networkSecurityConfig": "./resources/xml/network_security_config.xml"
    }
  }
}

Cette configuration bloque le trafic HTTP en clair, épingle les certificats pour votre domaine API et inclut une épingle de sauvegarde pour la sécurité de la rotation.

iOS : App Transport Security (ATS) est activé par défaut. Configurez-le explicitement dans app.json pour éviter tout affaiblissement accidentel :

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSAppTransportSecurity": {
          "NSAllowsArbitraryLoads": false,
          "NSExceptionDomains": {
            "api.votredomaine.com": {
              "NSExceptionMinimumTLSVersion": "TLSv1.2",
              "NSRequiresCertificateTransparency": true
            }
          }
        }
      }
    }
  }
}

Stockage sécurisé

Utilisez expo-secure-store pour les jetons, clés de chiffrement et autres petites valeurs sensibles. N'utilisez jamais AsyncStorage pour les secrets.

npx expo install expo-secure-store

Schéma d'implémentation :

import * as SecureStore from 'expo-secure-store';

const TOKEN_KEY = 'auth_token';

export async function saveToken(token: string) {
  await SecureStore.setItemAsync(TOKEN_KEY, token, {
    keychainService: 'com.votreentreprise.monapp',
    keychainAccessible: SecureStore.WHEN_UNLOCKED,
  });
}

export async function getToken(): Promise<string | null> {
  return SecureStore.getItemAsync(TOKEN_KEY, {
    keychainService: 'com.votreentreprise.monapp',
  });
}

export async function clearToken() {
  await SecureStore.deleteItemAsync(TOKEN_KEY, {
    keychainService: 'com.votreentreprise.monapp',
  });
}

Le paramètre keychainService isole les éléments de trousseau de votre application. WHEN_UNLOCKED garantit que les données sont inaccessibles lorsque l'appareil est verrouillé.

Vérification et diagnostics

Après chaque changement de configuration, vérifiez le comportement localement avant de fusionner.

Vérifier le chargement des secrets

Ajoutez une vérification temporaire en mode développement uniquement :

if (__DEV__) {
  console.log('Clé API chargée:', Constants.expoConfig?.extra?.apiKey ? 'PRÉSENTE' : 'MANQUANTE');
}

Exécutez npx expo start et confirmez que la clé se charge sans afficher sa valeur.

Vérifier les permissions

Android : Construisez un client de développement et inspectez les permissions accordées :

adb shell dumpsys package com.votreentreprise.monapp | grep -E "permission.*granted"

La sortie doit afficher uniquement android.permission.INTERNET et android.permission.ACCESS_NETWORK_STATE (plus toute permission d'exécution accordée par l'utilisateur).

iOS : Utilisez l'application Réglages sur l'appareil ou le simulateur pour examiner la liste des permissions de l'application. Confirmez qu'aucune permission inutilisée n'apparaît.

Vérifier la sécurité réseau

Testez le blocage du texte en clair avec un point de terminaison HTTP local :

# Démarrez un serveur HTTP simple dans un autre terminal
python3 -m http.server 8080

Dans l'application :

fetch('http://localhost:8080')
  .then(() => console.log('INATTENDU : Texte en clair réussi'))
  .catch(err => console.log('ATTENDU : Texte en clair bloqué', err.message));

Sur Android avec la configuration de sécurité réseau, la requête échoue avec « Cleartext HTTP traffic not permitted ». Sur iOS, ATS la bloque avec « App Transport Security has blocked a cleartext HTTP resource load ».

Testez l'épinglage de certificat en modifiant temporairement l'épingle dans network_security_config.xml et en confirmant que les requêtes échouent.

Vérifier le stockage sécurisé

// Testez la persistance à travers les redémarrages de l'application
await saveToken('test-token-123');
const retrieved = await getToken();
console.log('Jeton récupéré:', retrieved === 'test-token-123' ? 'SUCCÈS' : 'ÉCHEC');
// Redémarrez l'application, puis :
const afterRestart = await getToken();
console.log('Jeton après redémarrage:', afterRestart === 'test-token-123' ? 'SUCCÈS' : 'ÉCHEC');

Les deux vérifications doivent réussir.

Modes de défaillance et récupération

Prévoyez les scénarios d'échec courants pour minimiser les temps d'arrêt.

Échecs réseau dus à l'application d'HTTPS

Symptôme : Les appels API échouent après l'activation de la configuration de sécurité réseau ou d'ATS.

Récupération immédiate : Ajoutez une exception de domaine temporaire pour le point de terminaison en échec.

Android (network_security_config.xml) :

<domain-config cleartextTrafficPermitted="true">
  <domain>legacy-api.example.com</domain>
</domain-config>

iOS (app.json) :

"NSExceptionDomains": {
  "legacy-api.example.com": {
    "NSExceptionAllowsInsecureHTTPLoads": true
  }
}

Correctif permanent : Migrez le point de terminaison vers HTTPS avec un certificat valide. Supprimez l'exception une fois la migration terminée.

Plantages liés aux permissions

Symptôme : L'application plante lors de l'accès à une fonctionnalité après la suppression d'une permission.

Récupération : Réajoutez la permission dans app.json, reconstruisez le client de développement et examinez si la fonctionnalité nécessite la permission ou peut être refactorisée pour fonctionner sans.

Pour les tests locaux uniquement, accordez les permissions via ADB :

adb shell pm grant com.votreentreprise.monapp android.permission.CAMERA

Cela n'affecte pas les builds de production.

Secrets non chargés

Symptôme : Constants.expoConfig.extra.apiKey est indéfini.

Liste de contrôle de diagnostic :

  1. Confirmez que .env existe et contient API_KEY=valeur
  2. Vérifiez que dotenv est installé : npm list dotenv
  3. Vérifiez que app.config.js importe dotenv avant d'accéder à process.env
  4. Exécutez npx expo config --type public et inspectez l'objet extra résolu
  5. Assurez-vous que le client de développement a été reconstruit après les changements de configuration

Récupération : Corrigez la configuration, reconstruisez le client de développement (npx expo run:android ou npx expo run:ios), et redémarrez le bundler Metro avec --reset-cache.

Annulation de configuration

Si un changement casse l'application :

git checkout -- app.json app.config.js resources/xml/network_security_config.xml
npx expo run:android  # ou run:ios

Gardez les commits atomiques (un changement de sécurité par commit) pour rendre l'annulation précise.

Liste de contrôle des opérations

Intégrez ces vérifications dans votre flux de travail récurrent.

VérificationFréquenceOutil/CommandeRésultat attendu
Vérifier la version du SDK ExpoMensuellenpx expo --versionLa version actuelle est supportée (pas EOL)
Vérifier les dépendances obsolètesHebdomadairenpm outdatedAucune vulnérabilité critique ; seules des mises à jour mineures/patch en attente
Scanner les secrets commitésHebdomadairegit secrets --scan ou trufflehog git file://. --since-commit HEAD~10Zéro découverte
Réviser les permissions de l'applicationMensuelleInspecter app.json et app.config.jsSeules les permissions nécessaires déclarées
Tester l'application d'HTTPSMensuelleRécupération HTTP dans le build de développementLa requête échoue avec une erreur réseau
Vérifier l'utilisation du stockage sécuriséMensuelleRevue de code des appels de stockageTous les jetons/clés utilisent expo-secure-store
Exécuter l'audit de dépendancesHebdomadairenpm audit --audit-level=highZéro vulnérabilité haute/critique
Valider les secrets EAS BuildMensuelleTableau de bord Expo > Projet > SecretsAucun secret obsolète ou inutilisé

Routine de validation post-changement

Après chaque changement lié à la sécurité :

  1. Exécutez l'application en mode développement et exercez les flux utilisateur principaux
  2. Vérifiez le chargement des secrets avec le journal de débogage temporaire
  3. Testez les appels réseau pour confirmer l'application d'HTTPS et la validation des certificats
  4. Examinez les changements de permission du point de vue utilisateur (clarté des invites, nécessité)
  5. Documentez le changement dans CHANGELOG.md avec la date, la justification et les étapes de vérification

Conclusion

Sécuriser une application Expo est une discipline continue, pas une configuration unique. En maintenant un inventaire d'environnement précis, en appliquant les mesures de durcissement de manière incrémentale, en vérifiant chaque changement avec des tests concrets et en préparant des procédures de récupération pour les échecs courants, vous réduisez significativement la surface d'attaque de votre application. Les motifs couverts ici — gestion des secrets via les variables d'environnement et les secrets EAS, minimisation des permissions, configuration de la sécurité réseau avec épinglage de certificat, et stockage sécurisé pour les données sensibles — forment une base pratique pour toute application Expo en production. Commencez par l'étape d'inventaire aujourd'hui, identifiez votre lacune à plus haut risque, implémentez le correctif et vérifiez qu'il fonctionne. Continuez ce cycle chaque sprint pour construire une posture de sécurité durable qui protège vos utilisateurs et votre réputation.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO