En audit, je trouve souvent des clés secrètes posées directement dans le JavaScript envoyé au navigateur. Pas cachées, juste là, visibles pour qui ouvre les outils de développement. C'est une des failles les plus rapides à exploiter, et une des plus faciles à éviter. Voici ce qui fuite, pourquoi, et comment vérifier ton propre front.

Ton front est public, point

Tout ce qui part dans ton bundle est lisible par n'importe qui. Clic droit, "afficher le code source", ouvrir les fichiers JavaScript, et c'est tout. Minifier ou obfusquer ne change rien : ça ralentit un curieux, pas un attaquant. Donc un secret dans le front n'est pas "un peu exposé", il est public.

Ce qui fuite le plus souvent

1. Un NEXT_PUBLIC sur une variable qui ne devrait pas l'être

Avec Next.js, toute variable préfixée NEXT_PUBLIC_ est injectée en clair dans le bundle client. C'est pratique, et c'est le piège : il suffit d'ajouter le préfixe à une clé secrète "pour que ça marche côté client", et elle part dans le navigateur. Justifie chaque NEXT_PUBLIC_ une par une. En cas de doute, elle ne doit pas être publique.

2. La clé service_role de Supabase

La clé service_role ignore la RLS et donne un accès total à la base. Si elle est dans le front, c'est game over : n'importe qui lit et écrit toute ta base. Elle reste côté serveur, toujours.

3. Les clés secrètes Stripe

Une clé sk_live ou sk_test permet de piloter tes paiements, rembourser, lire tes clients Stripe. Côté client, tu ne mets que la clé publishable (pk_). La clé secrète n'a rien à faire dans le front, même en test.

4. Les clés d'API facturées à l'usage

Clé OpenAI, imagerie, SMS, géocodage : si elle est côté client, quelqu'un peut l'extraire et faire exploser ta facture avec ta clé. Ces appels passent par ton serveur, qui garde la clé et sert de relais.

5. Ce qui est normal côté client

La clé anon (ou publishable) de Supabase et la clé pk_ de Stripe sont faites pour être publiques. Ce n'est pas une fuite. Mais traite-les pour ce qu'elles sont : tout ce que la clé anon peut faire, un attaquant peut le faire. C'est la RLS qui te protège, pas le secret de la clé.

La règle simple : si une clé commence par sk_, contient service_role, ou sert à payer un service à l'usage, elle ne doit jamais atteindre le navigateur.

Comment vérifier ton propre front en cinq minutes

Fais ce qu'un attaquant fait : regarde ton bundle.

  • Ouvre ton site, affiche le code source, et ouvre les fichiers JavaScript chargés.
  • Cherche les motifs qui trahissent un secret : service_role, sk_live, sk_test, eyJ (début d'un token JWT), AKIA (clé AWS).
  • En local, construis le projet et grep le build.
npm run build
grep -rIn "service_role\|sk_live\|AKIA" .next/static .next/server 2>/dev/null

Tu en trouves une ? Ne la nettoie pas, régénère-la

Si une clé secrète a fuité, la retirer du code ne suffit pas : on considère qu'elle est déjà copiée. Régénère-la chez le fournisseur (Supabase, Stripe, OpenAI...), et vérifie aussi l'historique git, car un secret supprimé au commit suivant y est toujours. Un secret exposé se rotate, il ne se nettoie pas.

Et dans ton front à toi, qu'est-ce qui traîne ?

Mon scan lit tes bundles comme le ferait un attaquant et te dit si une clé fuite. En une minute, gratuit.

Scanner mon SaaS, gratuit

Voir les offres d'audit

Questions fréquentes

Le préfixe NEXT_PUBLIC est-il sûr ?

Seulement pour des valeurs réellement publiques. Toute variable NEXT_PUBLIC_ est injectée en clair dans le bundle client. Un secret dedans est exposé à tout le monde.

La clé anon de Supabase est-elle un secret ?

Non, elle est publique par conception. Ce qui te protège, c'est la RLS, pas le fait de cacher la clé.

À lire aussi : sécuriser la RLS Supabase et les failles de webhook Stripe.

← Retour au blog