Aller au contenu

Bases de la sécurité

Clé API exposée dans le frontend : ce que 30 998 applis livrent

Une clé API exposée dans votre frontend est le plus souvent une clé Google Maps. Nous avons scanné 30 998 applis vibe-codées et compté ce qui fuit vraiment.

Vlad Tkachenko8 min de lecture
Une page de code d'appli avec huit valeurs en forme de clé mises en évidence, la plupart ordinaires et une dessinée en rouge.

En bref

  • Une clé API exposée dans votre frontend est presque toujours du genre inoffensif. Nous avons trouvé une clé digne d'être signalée dans 1 332 applis sur 30 998, et 1 080 d'entre elles ne portaient qu'une clé API Google.
  • La clé Supabase service_role, celle contre laquelle chaque tutoriel met en garde, est apparue dans 3 applis sur 30 998. Une clé secrète Stripe aussi, dans 3.
  • Les clés qui dépensent de l’argent ou lisent des données par leur seule forme sont apparues dans 54 applis. Une table Supabase ouverte est apparue dans 2 096.

Quelqu'un ouvre votre appli, appuie sur F12 et vous annonce qu'une clé API est exposée dans votre frontend. Le mot employé est en général « fuite ». On vous dit rarement de quelle clé il s'agit, et les conseils que vous trouvez ensuite traitent toutes les clés comme la même urgence.

Ce n'est pas la même urgence, et nous pouvons désormais chiffrer l'écart. Entre le 12 et le 14 août 2026, nous avons passé neuf vérifications externes sur 30 998 applis en ligne créées avec Lovable, Bolt, v0, Replit et Base44, et lu le JavaScript que chacune envoie à un navigateur. Voici ce qu'il y avait dedans.

Une clé API exposée dans le frontend est-elle vraiment un problème ?

En général non, et la forme de ce « en général » est plus déséquilibrée que nous ne le pensions.

Nous avons trouvé une clé digne d'être signalée dans 1 332 des 30 998 applis. Dans 1 080 d'entre elles, la seule chose trouvée était une clé API Google, c'est à dire précisément le justificatif censé se trouver dans votre page. Ce qui protège celle-là, c'est un réglage conservé du côté de Google, et la cacher n'a jamais fait partie de l'arrangement.

Les 29 666 autres applis ne livraient rien que notre vérification des secrets traite comme un problème. Ce chiffre demande une précision pour rester honnête : les clés publiables en sont exclues. Une clé anon Supabase ou une clé pk_ Stripe a sa place dans le navigateur, nous la marquons donc comme quelque chose que vous avez bien fait et elle n'entre jamais dans ces comptes.

Ce que nous avons compté, et ce que nous n'avons pas pu compter

Nous avons chargé chaque appli comme le fait un visiteur, dans un vrai navigateur, et lu le JavaScript téléchargé. Tout ce qui suit est une forme trouvée dans ce code.

Nous reconnaissons les formats de clé que nous connaissons. Stripe, OpenAI, Anthropic, AWS, Google et Supabase ont des préfixes identifiables, et un JWT Supabase indique son propre rôle en texte lisible dans sa section centrale. Un justificatif dans un format que nous ne connaissons pas n'est pas dans ces chiffres, lisez-les donc comme un plancher.

Nous n'avons utilisé aucune clé trouvée. Pas une seule fois, sur aucune appli. Nous avons noté le type et un indice masqué de la forme sk_live_…a1b2, et la valeur réelle n'a été écrite nulle part.

Aucune appli n'est nommée. Ni ici, ni dans le jeu de données, ni nulle part où nous publions.

Presque toutes sont des applis publiées sur le domaine d'un builder. La méthode complète, l'échantillon et chaque chiffre derrière cet article sont dans notre rapport de scan, y compris ce que nous n'avons pas pu mesurer.

Ce que les 30 998 applis livraient réellement

Un tableau, trié par fréquence d'apparition. La vérification des secrets a abouti sur chacune des 30 998 applis, chaque compte ci-dessous porte donc sur toutes.

Ce que nous avons trouvé dans le code du navigateurApplis
Clé API Google1 142
Une valeur à forte entropie près d'un nom « secret » ou « password »204
Clé OpenAI33
Clé d'accès AWS9
Clé Anthropic5
Clé Supabase service_role3
Clé secrète Stripe3
Clé restreinte Stripe2

Le total des lignes dépasse 1 332 parce qu'une appli peut en porter deux. Triez ces mêmes 1 332 applis en groupes qui ne se recouvrent pas et l'image devient plus nette encore : 1 080 avaient une clé Google et rien d'autre, 198 avaient une valeur à forte entropie qui peut être ou non un vrai justificatif, et 54 avaient une clé qui est un véritable secret par sa forme même.

Chaque appli où nous avons trouvé une clé, triée en trois groupes qui ne se recouvrent pas. La section rouge est celle dont parlent les avertissements.

Le deuxième groupe mérite d'être décrit avec soin. Une valeur à forte entropie posée à côté d'un mot comme secret ou password peut être un justificatif vivant, ou bien un identifiant de session, une empreinte de build ou un jeton public au nom malheureux. Nous le signalons comme méritant un coup d'œil, et de l'extérieur personne ne peut vous dire lequel c'est.

Les 54 du troisième groupe sont la vraie affaire. Toutes sauf deux ont obtenu la note D ou F, parce qu'un seul constat critique plafonne la note à D quoi que l'appli ait fait de bien par ailleurs. Le plus gros groupe à l'intérieur est la clé OpenAI, à 33, et celle-là n'a aucun réglage qui la rendrait sûre dans un navigateur.

La clé contre laquelle tout le monde met en garde était la plus rare

Trois applis. C'est le nombre de celles qui livraient une clé Supabase service_role, celle qui passe outre chaque règle de table que vous avez écrite. Une clé secrète Stripe est apparue trois fois elle aussi.

Mettez cela en regard de l'autre moitié du même balayage. Parmi les applis scannées, 8 429 nommaient un projet Supabase, et les deux constats se situent à l'intérieur de ce même groupe. Trois d'entre elles livraient la clé service_role. Dans 2 096 d'entre elles, au moins une table a répondu à une requête sans aucune connexion, et dans 394 cette table portait un nom de personnes : users, profiles, customers, orders.

Les deux comptes viennent des mêmes 8 429 applis Supabase. La ligne du haut est le constat contre lequel on met les gens en garde.

Les 2 096 sont un plancher. 4 749 des 8 429 n'ont jamais répondu à notre vérification de base de données, pour des raisons que nous ne voyons pas de l'extérieur, et celles-là sont enregistrées comme inconnues plutôt que comme saines. Les trois clés service_role sont un compte exact, parce qu'une clé se lit dans du code que chaque appli remet.

Pourquoi les avertissements visent la mauvaise clé

Nous ne voyons que l'extérieur de ces applis, nous ne pouvons donc pas vous dire pourquoi. Ce que nous pouvons montrer, c'est quelle erreur survit.

Copier la mauvaise clé Supabase est vraiment facile. Dans un projet plus ancien, anon et service_role se trouvent côte à côte dans le même panneau du tableau de bord, elles ont la même longueur et la même forme, et rien ne casse si vous prenez la mauvaise. Cela n'est pourtant arrivé que trois fois sur 30 998 applis, parce que rien ne vous y pousse. Coller l'une ou l'autre fait fonctionner l'appli.

La table ouverte, elle, a une force derrière elle. Row Level Security est activée, l'appli cesse d'afficher des données, une politique qui autorise tout le monde est écrite pour que cela remarche, et à partir de cet instant le tableau de bord signale la table comme protégée. L'activer n'est pas la même chose qu'être protégé. Notre scan classe cette table en constat critique un jour où votre tableau de bord vous montre l'interrupteur activé et une politique en place.

Comment trouver gratuitement une clé API exposée dans votre appli

Commencez à la main, cela coûte cinq minutes et ne demande rien à installer. Ouvrez votre site en ligne, affichez le code source de la page et cherchez quatre chaînes : AIza pour une clé Google, sk_ pour un secret Stripe ou de fournisseur de modèle, service_role pour la clé Supabase qui ignore vos règles, et eyJ pour tout jeton Supabase. Tout ce qui remonte est déjà entre les mains de chacun de vos visiteurs.

Cela vous donne la page elle-même. Ce qui échappe à cette méthode, c'est le JavaScript que la page charge ensuite, et c'est précisément pour cela que notre propre scanner ouvre une appli dans un vrai navigateur et lit les bundles au lieu du HTML. Chercher à la main ne peut pas non plus vous dire si le jeton eyJ trouvé est la clé anon ou la secrète, car les deux ont la même longueur et la même forme.

Notre scan gratuit couvre les deux. Il charge votre appli dans un vrai navigateur, lit le code qui arrive vraiment, décode chaque jeton Supabase et rapporte le rôle qui y est écrit, si bien qu'une clé publiable revient marquée comme correcte au lieu d'être noyée dans un mur de rouge. Vous obtenez une note, un score et les comptes à l'écran en une vingtaine de secondes sans compte. Donnez une adresse e-mail et vous obtenez en plus la liste détaillée, avec une correction écrite pour votre builder que vous pouvez coller directement.

Trois choses qu'il ne fera pas, et ce sont les raisons pour lesquelles il est sûr sur une appli en ligne : il ne se connecte jamais, il n'écrit jamais rien, et il ne garde jamais une clé qu'il trouve. Un secret exposé est conservé sous forme d'indice masqué comme sk_live_…a1b2, et la valeur réelle est jetée. Scannez votre appli, ou lisez d'abord ce que regarde chacune des neuf vérifications.

Quoi faire, dans l'ordre que les chiffres suggèrent

Que faire

  • Identifiez la clé avant d'y réagir. Le préfixe répond pour Stripe et pour les clés Supabase récentes ; pour une clé Supabase plus ancienne, c'est le champ role à l'intérieur du jeton qui tranche.
  • Si c'est une clé Google, restreignez-la au lieu de la cacher. Restriction Sites web, votre domaine, uniquement les API que vous utilisez, plus un plafond de quota quotidien. Gratuit, environ cinq minutes, aucun changement de code.
  • Si c'est une vraie clé secrète, faites-la tourner en premier. La supprimer de votre code ne ferme rien, car l'ancienne valeur est toujours dans votre historique de versions et dans les copies en cache de votre site.
  • Allez ensuite lire les règles de vos tables, car c'est là que les chiffres situent l'exposition réelle. Commencez par les tables qui contiennent des personnes.
  • Vérifiez la facturation et les journaux après toute exposition de clé secrète. Faire tourner la clé arrête ce qui vient ensuite, et ne dit rien de ce qui s'est déjà produit.

Parcourez toute la liste en une seule fois avec la checklist de sécurité en 10 minutes, qui couvre la clé et les règles de tables à côté des autres choses à fermer dans une appli fraîchement lancée. Et si c'est la moitié base de données de cet article qui vous inquiète, elle a son propre relevé : qui peut lire votre base de données Supabase.

FAQ

Comment savoir si ma clé API a fuité ?

Ouvrez votre site en ligne, affichez le code source de la page et cherchez les formes : AIza pour une clé Google, sk_ pour un secret Stripe ou de fournisseur de modèle, et eyJ pour un JWT Supabase. Tout ce qui ressort est déjà entre les mains de chacun de vos visiteurs. Notre scan gratuit fait la même lecture depuis l'extérieur et rapporte ce qu'il voit en une vingtaine de secondes, sans compte pour obtenir la note.

Une clé API écrite en dur est-elle toujours un problème de sécurité ?

Non, et croire le contraire est exactement ce qui apprend aux gens à ignorer l'avertissement. Certaines clés sont publiées volontairement : une clé anon Supabase, une clé pk_ Stripe et une clé de configuration web Firebase sont toutes conçues pour vivre dans le navigateur, et ce qui protège vos données, ce sont les règles derrière elles. Une clé secrète est le cas inverse et sa place est sur un serveur. Le préfixe vous dit laquelle des deux vous avez sous les yeux.

On me dit que ma clé Supabase est exposée. Est-ce la mauvaise ?

Presque certainement non. Les deux clés Supabase se ressemblent, alors lisez le rôle inscrit dans le jeton ou vérifiez le préfixe : anon et sb_publishable_ sont faites pour être publiques, service_role et sb_secret_ ne le sont pas. Nous avons trouvé une clé service_role dans 3 applis sur 30 998, les probabilités penchent donc fortement du côté inoffensif. Si c'est bien la secrète, faites-la tourner dès aujourd'hui dans le tableau de bord Supabase.

De quoi devrais-je me préoccuper à la place ?

Des règles sur les tables de votre base. Parmi les applis où nous avons pu terminer cette vérification, plus de la moitié avaient au moins une table qui répondait à une requête sans aucune connexion, et dans 394 d'entre elles la table ouverte portait un nom de personnes : users, profiles, customers, orders. C'est bien plus fréquent que n'importe quelle clé qui fuit, et bien plus discret, parce que l'appli fonctionne exactement pareil dans les deux cas.

J'ai retiré la clé de mon code. Est-ce réglé ?

Pas à soi seul. L'ancienne valeur existe toujours dans votre historique de versions et dans toute copie en cache de la page, donc quiconque l'a déjà récupérée peut continuer à s'en servir. Ce qui ferme vraiment la porte, c'est de faire tourner la clé dans le tableau de bord du fournisseur, et c'est la première étape plutôt que la dernière. Ensuite, vérifiez la facturation et les journaux pour tout usage que vous ne pouvez pas expliquer.

Écrit par

Vlad Tkachenko

Fondateur de Reeve

Je passe mes journées à examiner des applications créées avec Lovable, Bolt, v0, Cursor et Replit, et la courte liste d'erreurs qui y reviennent sans cesse.

En savoir plus sur l'auteur

À lire ensuite

Tous les articles

Vous ne savez pas où en est votre propre application ?

Lancez une analyse gratuite et obtenez une note claire de A à F en une vingtaine de secondes. Sans compte, sans carte.

Analyser mon application

Vérification externe automatisée, pas un audit complet. L'absence de problème n'est pas une garantie de sécurité.