Une clé API placée dans le front-end d'une application mobile n'est jamais réellement secrète. N'importe qui peut l'extraire en décompilant l'app, en lisant le bundle JavaScript ou en interceptant le trafic réseau, car le téléphone de l'utilisateur n'est pas un environnement de confiance. Les clés vraiment sensibles doivent donc vivre sur un backend, pas dans l'app. Les clés qui doivent rester côté client, comme une clé de cartographie, doivent être restreintes chez le fournisseur. Un fichier .env ne protège rien dans une app mobile.
Réponse rapide
Une clé exposée dans le front-end est lisible par tout le monde, car le code de l'app est livré sur l'appareil de l'utilisateur. Selon la documentation d'Expo, les variables préfixées EXPO_PUBLIC_ sont intégrées en clair dans le bundle compilé, donc un .env ne cache aucun secret. La règle est simple : les clés secrètes, comme les clés d'API serveur, les jetons admin ou les clés privées, ne doivent jamais être dans l'app, mais sur un backend. Les clés forcément publiques, comme une clé Google Maps, doivent être restreintes par identifiant d'app et par quota. En cas de fuite, révoquez et régénérez la clé immédiatement.
Pourquoi une clé API dans le front-end n'est jamais secrète
Le principe de base de la sécurité mobile est que le client n'est pas un environnement de confiance. Tout ce que vous livrez dans l'app, code et clés compris, se retrouve sur l'appareil de l'utilisateur, où il peut être inspecté. Une clé dans le binaire ou le bundle est donc extractible, quel que soit l'effort déployé pour la cacher.
Concrètement, un attaquant dispose de plusieurs chemins. Il peut décompiler l'APK ou l'IPA, lire les chaînes de caractères du bundle JavaScript, ou intercepter le trafic HTTPS avec un proxy sur un appareil qu'il contrôle. Chacune de ces méthodes révèle les clés embarquées. C'est pourquoi « cacher » une clé côté client relève de l'illusion, et non d'une véritable protection.
Le cas de React Native et Expo
React Native et Expo aggravent souvent le malentendu, car les développeurs supposent qu'un fichier .env fonctionne comme sur un serveur. Ce n'est pas le cas. Au moment du build, les variables d'environnement référencées dans le code sont intégrées directement dans le bundle JavaScript, en clair. La documentation d'Expo est explicite : ne stockez jamais d'informations sensibles dans des variables EXPO_PUBLIC_, car elles seront visibles dans l'application compilée.
Le point important est que cette intégration se fait à la compilation. Une variable comme process.env.MA_CLE est remplacée par sa valeur littérale dans le bundle livré. Le fichier .env n'accompagne pas l'app ; sa valeur, elle, y est gravée. Autrement dit, un .env organise vos secrets pendant le développement, mais ne les protège pas une fois l'app distribuée aux utilisateurs.
Clés publiques vs clés secrètes : la vraie distinction
Toutes les clés ne se valent pas, et la première décision est de classer chaque clé comme publique ou secrète. Une clé publique est conçue pour être visible, comme une clé publishable Stripe ou une configuration Firebase ; sa présence dans le client est prévue et acceptable. Une clé secrète donne un accès privilégié, comme une clé d'API serveur ou un jeton d'administration, et ne doit jamais quitter votre backend.
Le tableau suivant aide à trancher pour les cas courants.
| Type de clé | Exemple | Peut-elle être dans le front-end ? |
|---|---|---|
| Clé publiable | Clé publishable Stripe, config Firebase | Oui, elle est prévue pour être publique |
| Clé restreinte par app | Clé Google Maps restreinte par bundle ID | Oui, si elle est restreinte chez le fournisseur |
| Clé d'API serveur | Clé secrète d'un service tiers | Non, jamais |
| Clé privée ou secret | Clé privée de signature, secret OAuth | Non, jamais |
La question à se poser pour chaque clé est simple : si cette valeur devient publique, quelqu'un peut-il en abuser ? Si la réponse est oui, la clé est secrète et n'a rien à faire dans le front-end. Si la clé est de toute façon publique, le travail consiste à la restreindre, pas à la cacher.
Les dangers concrets d'une clé exposée
Une clé exposée n'est pas un risque théorique ; elle entraîne des conséquences mesurables. La plus fréquente est l'abus de quota et la facture qui explose : une clé de cartographie ou d'un service payant, laissée sans restriction, peut être utilisée par des tiers jusqu'à générer des milliers d'euros de coûts sur votre compte.
Au-delà du coût, une clé secrète exposée peut ouvrir l'accès à des données, permettre d'usurper des comptes, ou transformer votre backend en proxy gratuit pour un attaquant. Une clé d'un service tiers peut aussi servir à agir en votre nom sur ce service. Le dénominateur commun est que l'attaquant hérite des privilèges de la clé, et ces privilèges sont souvent bien plus larges que ce dont l'app avait besoin.
Comment corriger : déplacer les secrets vers un backend
La solution de fond pour une clé secrète est de ne jamais la mettre dans l'app. À la place, placez-la sur un backend que vous contrôlez, et faites appeler ce backend par l'app. L'app envoie une requête à votre serveur, le serveur ajoute la clé secrète et relaie l'appel au service tiers. La clé reste ainsi hors de portée de l'utilisateur.
Ce modèle, souvent appelé backend-for-frontend ou proxy, a un autre avantage : il vous donne un point de contrôle. Vous pouvez y appliquer une authentification, limiter les débits, journaliser les usages et révoquer un accès sans republier l'app. Pour les opérations sensibles, c'est la seule approche réellement sûre, car elle place le secret dans le seul endroit que l'utilisateur ne contrôle pas.
Comment restreindre les clés qui doivent rester côté client
Certaines clés, comme une clé Google Maps, doivent vivre dans l'app. Pour celles-là, l'objectif n'est pas de les cacher mais de les restreindre chez le fournisseur. Google recommande fortement de restreindre toutes les clés : par application (identifiant de bundle iOS, ou nom de package et empreinte SHA-1 sous Android), par API autorisée, et par quota, selon ses bonnes pratiques de sécurité.
Il faut être honnête sur la portée de ces restrictions. Une restriction par identifiant d'app est une vérification ajoutée aux requêtes, pas une preuve cryptographique, et un appel direct à l'API avec un en-tête falsifié peut parfois passer. Elle reste néanmoins une barrière utile, surtout combinée à des restrictions d'API et à des quotas qui plafonnent les dégâts. Restreindre une clé publique ne la rend pas secrète ; cela limite ce qu'un tiers peut en faire.
Secrets et CI/CD : éviter les fuites dans le pipeline
Beaucoup de fuites ne viennent pas de l'app elle-même, mais du pipeline. Un fichier .env commité dans Git, une clé écrite en dur dans un script Fastlane, ou un secret injecté dans le bundle par un build EAS mal configuré : chacun expose la clé aussi sûrement que si vous l'aviez publiée. L'historique Git est particulièrement traître, car une clé retirée dans un commit reste présente dans l'historique.
La bonne pratique est de garder les secrets dans le coffre de secrets de votre système d'intégration continue, et de ne les injecter qu'au bon endroit. Un secret serveur ne doit jamais atteindre le bundle client ; une clé publique restreinte, oui. Vérifiez aussi votre .gitignore, et si une clé a déjà été commitée, révoquez-la, car la retirer de l'historique ne suffit pas à la considérer comme sûre.
Checklist de remédiation
Si vous découvrez une clé exposée, agissez dans l'ordre, de l'urgence immédiate à la prévention continue. Le tableau ci-dessous donne une marche à suivre claire.
| Étape | Action | Priorité |
|---|---|---|
| 1 | Révoquer et régénérer toute clé secrète exposée | Immédiate |
| 2 | Déplacer les appels sensibles vers un backend proxy | Haute |
| 3 | Restreindre les clés publiques (bundle ID, API, quotas) | Haute |
| 4 | Retirer les secrets du bundle et de l'historique Git | Haute |
| 5 | Utiliser des jetons éphémères émis par le serveur | Moyenne |
| 6 | Scanner le build avant chaque publication | Continue |
La première ligne est la plus urgente : une clé secrète exposée doit être révoquée et régénérée sans attendre, car tant qu'elle est valide, elle reste exploitable. Les étapes suivantes empêchent la situation de se reproduire.
Détecter les secrets avant la publication
La meilleure défense est de repérer une clé exposée avant qu'elle n'atteigne les magasins. Il est facile de laisser passer une clé oubliée dans un module natif, un fichier de configuration ou une dépendance, surtout quand plusieurs personnes touchent au projet. Une revue manuelle ne voit pas tout.
Un scanner comme PTKD.com analyse votre .ipa ou votre .apk et renvoie des résultats classés par gravité et alignés sur l'OWASP MASVS, ce qui inclut les secrets embarqués, le stockage non sécurisé et les mauvaises configurations réseau. Il faut être clair sur ses limites : un scanner ne remplace pas le déplacement de vos secrets vers un backend, ni un audit manuel pour une app à haut risque, et il ne peut pas deviner si une clé publique est correctement restreinte chez le fournisseur. Ce qu'il fait, c'est signaler les secrets évidents avant qu'ils ne fuient.
Ce qu'il faut retenir
- Une clé dans le front-end n'est jamais secrète : le client est toujours inspectable.
- Un fichier .env ne protège rien dans une app mobile ; les variables EXPO_PUBLIC_ sont intégrées en clair.
- Les clés secrètes doivent vivre sur un backend proxy, jamais dans l'app.
- Les clés forcément publiques doivent être restreintes par identifiant d'app, API et quota chez le fournisseur.
- En cas de fuite, révoquez immédiatement, puis scannez chaque build avec PTKD.com avant publication.



