Clé API exposée dans le navigateur ? Vérifiez votre clé OpenAI, Claude ou Gemini en 2 minutes

Si votre application appelle OpenAI, Claude ou Gemini directement depuis le navigateur, n’importe qui peut copier la clé depuis les DevTools. Une vérification de 2 minutes, l’ordre des correctifs, et comment votre agent de codage peut tester la route proxy.

Ashley Innocent

Ashley Innocent

2 November 2026

Clé API exposée dans le navigateur ? Vérifiez votre clé OpenAI, Claude ou Gemini en 2 minutes

Apidog pour les entreprises

Déploiement sur site

SSO & RBAC

Conforme SOC 2

Découvrir Apidog Enterprise

Si votre application web appelle OpenAI, Claude ou Gemini directement depuis le navigateur, votre clé API est exposée dans le navigateur, et quiconque ouvre les DevTools peut la copier. Vous pouvez le vérifier en 2 minutes : ouvrez l'onglet Réseau, envoyez une requête IA, et cherchez un en-tête Authorization, x-api-key ou x-goog-api-key envoyé au fournisseur. Si vous y voyez votre clé, renouvelez-la aujourd'hui et déplacez l'appel derrière une route serveur.

Ci-dessous : la vérification, l'ordre des corrections, et comment votre agent de codage peut tester la route corrigée.

Pourquoi une clé API exposée dans le navigateur est un problème

Une clé API exposée dans le navigateur est un secret qui est livré dans votre code frontend ou votre trafic réseau, où chaque visiteur peut le lire. Si le navigateur envoie la clé, l'utilisateur peut la copier et appeler le fournisseur sur votre facture.

Le guide de la clé API Gemini de Google indique « Ne codez pas en dur les clés API directement dans les applications web ou mobiles » car « Les clés compilées dans du code côté client peuvent être extraites par les utilisateurs », et il vous recommande d'« exécuter un serveur proxy backend pour effectuer les appels API réels ». Le guide de sécurité des clés API d'OpenAI donne la même règle : acheminez les requêtes via votre propre backend au lieu de déployer la clé sur le client.

Le README d'openai-node indique que le support du navigateur est désactivé par défaut « pour éviter d'exposer vos identifiants API secrets », et vous devez définir dangerouslyAllowBrowser: true pour l'activer. Le SDK TypeScript d'Anthropic utilise le même nom d'option, et son API n'accepte les appels navigateur (CORS) que lorsque la requête porte l'en-tête anthropic-dangerous-direct-browser-access: true, comme l'a documenté Simon Willison lors de sa sortie.

Ce schéma est courant dans les applications construites rapidement avec des générateurs d'applications IA et des agents de codage : le chemin fonctionnel le plus court est un fetch depuis un composant React avec la clé dans une variable VITE_ ou NEXT_PUBLIC_. Les clés volées sont ensuite revendues pour de l'inférence en masse, comme expliqué dans notre article sur les clés API IA volées et le LLMjacking, et c'est sur votre facture que vous vous en apercevez.

Comment vérifier si votre clé API est exposée (2 minutes)

Three-step infographic of the 2-minute key exposure check: 1 Network tab with a POST request highlighted, 2 search the JavaScript bundle for sk- and AIza, 3 check env vars prefixed NEXT_PUBLIC_ or VITE_

Effectuez ces vérifications sur la production, pas sur localhost.

  1. Surveillez l'onglet Réseau (45 secondes). Ouvrez votre site, appuyez sur F12 (Cmd+Option+I sur un Mac), choisissez l'onglet Réseau et déclenchez une fonctionnalité IA, comme l'envoi d'un message de chat. Filtrez par openai, anthropic ou googleapis. Si une requête va directement vers api.openai.com, api.anthropic.com ou generativelanguage.googleapis.com, cliquez dessus et ouvrez Headers. Une clé dans Authorization: Bearer, x-api-key, x-goog-api-key ou un paramètre de requête ?key= signifie qu'elle est exposée.
  2. Cherchez dans le bundle (45 secondes). Dans les DevTools, appuyez sur Cmd+Option+F (Ctrl+Shift+F sous Windows) pour rechercher dans tous les scripts chargés. Cherchez sk-, sk-ant-, AIza et dangerouslyAllowBrowser. Toute occurrence dans un fichier .js servi au navigateur est une fuite, même si aucune requête n'a encore été déclenchée.
  3. Vérifiez les préfixes de vos variables d'environnement (30 secondes). Ouvrez votre fichier .env et votre tableau de bord d'hébergement. Les outils de build copient certaines variables dans le bundle client par conception : VITE_* dans Vite (voir la doc env de Vite),NEXT_PUBLIC_* dans Next.js, REACT_APP_* dans Create React App et EXPO_PUBLIC_* dans Expo. Une clé de fournisseur derrière l'un de ces préfixes est publique, peu importe son nom.

Pour une analyse en terminal de la sortie de votre build :

# from your project root after a production build
grep -rnoE "sk-(proj-|ant-)?[A-Za-z0-9_-]{20,}|AIza[0-9A-Za-z_-]{35}" dist/ build/ .next/static/ 2>/dev/null
grep -rn "dangerouslyAllowBrowser" dist/ build/ .next/static/ 2>/dev/null

Une sortie vide est un succès. Google précise que les nouvelles clés AI Studio créées depuis le 28 mai 2026 sont des « clés d'authentification », dont le format peut différer de AIza, donc cherchez aussi generativelanguage.googleapis.com dans le bundle. Vous réussissez uniquement lorsque le navigateur communique avec votre propre domaine (par exemple /api/chat) et qu'aucun nom d'hôte de fournisseur ni aucune clé n'apparaît nulle part.

Que faire lorsque votre clé est exposée : ordre des corrections

Renouveler d'abord ferme la brèche du jour ; le changement d'architecture la ferme définitivement.

Étape Ce que vous faites Pourquoi cet ordre Durée
1. Renouveler la clé Créez une nouvelle clé dans la console du fournisseur, puis révoquez celle qui a fuité L'ancienne clé a peut-être déjà été copiée ; la révocation est la seule chose qui empêche son utilisation 5 min
2. Déplacer l'appel côté serveur Placez l'appel au fournisseur dans une route serveur ou une fonction edge qui détient la clé Empêche la nouvelle clé de fuiter de la même manière 30 à 60 min
3. Ajouter l'authentification et des limites de débit par utilisateur Exigez une session sur la route et plafonnez les requêtes par utilisateur Sans cela, votre proxy devient un point d'accès IA gratuit pour tout le monde 30 min
4. Définir des limites de dépenses chez le fournisseur Fixez des budgets ou des limites de dépenses dans les paramètres de facturation de chaque fournisseur Plafonne la facture dans le pire des cas si autre chose fuite 10 min
5. Scanner en CI Faites échouer le build si un motif de clé apparaît dans le bundle de sortie Empêche la prochaine fonctionnalité écrite par un agent d'annuler la correction 15 min

Déployez la nouvelle clé côté serveur avant de révoquer l'ancienne, sinon votre fonctionnalité IA tombera en panne. Notre guide sur les bonnes pratiques de rotation des clés API couvre la rotation sans interruption. À l'étape 4, les recommandations de sécurité des clés d'OpenAI préconisent des limites de dépenses avec application stricte, car les alertes seules n'arrêtent pas le trafic ; un budget de facturation Google Cloud vous alerte mais n'arrête pas l'utilisation à lui seul.

Comment déplacer les appels OpenAI, Claude et Gemini derrière une route serveur

Diagram comparing an unsafe setup, where the browser holds the API key and calls the AI provider directly while DevTools copies the key, with a safe setup where the browser calls your server route, which holds the key and applies auth, rate limits and a spend cap before calling the provider

Une route de proxy backend est un petit point d'accès serveur qui reçoit le prompt de l'utilisateur, ajoute la clé API côté serveur, appelle le fournisseur et renvoie uniquement la réponse. Le navigateur ne voit jamais la clé. Voici une route Next.js minimale pour OpenAI ; Claude et Gemini suivent la même forme :

// app/api/chat/route.ts (runs on the server only)
import OpenAI from "openai";
import { getSession } from "@/lib/auth";        // your auth helper
import { checkRateLimit } from "@/lib/limits";  // your per-user limiter

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); // no NEXT_PUBLIC_ prefix

export async function POST(req: Request) {
  const session = await getSession(req);
  if (!session) return new Response("Unauthorized", { status: 401 });

  if (!(await checkRateLimit(session.userId, 20))) {   // 20 requests per minute
    return new Response("Too many requests", { status: 429 });
  }

  const { message } = await req.json();
  if (typeof message !== "string" || message.length > 4000) {
    return new Response("Bad request", { status: 400 });
  }

  const response = await client.responses.create({
    model: process.env.OPENAI_MODEL!,   // pin the model server-side
    input: message,
  });

  return Response.json({ reply: response.output_text }); // return the answer, nothing else
}

Ce qui la rend sûre, et pas seulement cachée :

Pour Claude et Gemini, utilisez leurs SDK avec ANTHROPIC_API_KEY ou GEMINI_API_KEY. Les restrictions de site web et d'IP de Google aident, mais n'importe qui avec curl peut envoyer n'importe quel en-tête Referer, alors considérez-les comme une seconde couche. Le seul cas légitime d'appel navigateur est un outil apportez-votre-propre-clé où chaque utilisateur colle sa propre clé.

Laissez votre agent de codage tester la route proxy avec Apidog CLI

Déplacer la clé, c'est la moitié du travail ; l'autre moitié consiste à prouver qu'elle reste déplacée après la prochaine fonctionnalité écrite par votre agent. Laissez l'agent qui a construit la route la tester avec Apidog CLI. Configurez-le une fois :

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com   # pick your agent when prompted

Ensuite, donnez à Claude Code, Codex, Cursor ou à l'agent que vous utilisez un seul prompt :

Create Apidog test cases in project <id> for POST /api/chat on our staging
environment that assert:
1. a request without a session cookie returns 401,
2. a valid request returns 200 and the body does not contain "sk-", "sk-ant-",
   "AIza" or "api_key",
3. the 21st request inside 60 seconds from the same user returns 429.
Run them and summarize any failures.

L'agent lit le schéma, valide sa charge utile, écrit les cas de test et les exécute :

apidog test-case category --project <id>
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <id> --file case.json
apidog run --test-case <caseId> --project <id> -e <envId> -r cli,json

La deuxième assertion est la plus importante : elle échoue dès qu'un objet d'erreur de fournisseur ou un champ de débogage commence à renvoyer votre clé au client. Placez la même étape apidog run ... -r junit dans votre pipeline pour que chaque déploiement la revérifie ; notre guide Apidog CLI CI/CD montre la configuration, et Apidog CLI dans Claude Code couvre le côté agent. Le plan gratuit d'Apidog couvre jusqu'à 4 utilisateurs, donc une petite équipe peut faire tourner cela sans siège payant.

Pour le volet dépôt du même problème, les clés commitées dans Git plutôt que livrées au navigateur, voir notre vérification de fuite de clé API avec un scanner de secrets. Si vos agents appellent des outils qui manipulent des données clients, tester les agents IA pour les fuites de données couvre la couche suivante.

Erreurs courantes qui maintiennent la clé exposée

button

FAQ

Comment savoir si ma clé API OpenAI est exposée dans le navigateur ? Déclenchez une fonctionnalité IA avec l'onglet Réseau des DevTools ouvert. Une requête vers api.openai.com avec un en-tête Authorization: Bearer sk-... signifie qu'elle est exposée. Cherchez aussi sk- et dangerouslyAllowBrowser dans les scripts chargés.

Est-il sûr de mettre une clé API dans une variable d'environnement NEXT_PUBLIC_ ou VITE_ ? Non. Ces préfixes existent pour copier des valeurs dans le bundle client. Toute clé de fournisseur stockée sous ces préfixes est livrée à chaque visiteur. Utilisez une variable sans préfixe, réservée au serveur, et lisez-la à l'intérieur d'une route serveur.

Restreindre une clé API Gemini à mon site web la rend-elle sûre dans le navigateur ? Cela aide, mais un script en dehors du navigateur peut envoyer n'importe quel en-tête Referer. Le guide de Google lui-même recommande un proxy backend pour les applications clientes.

J'ai découvert que ma clé est exposée. Que dois-je faire en premier ? Créez une nouvelle clé, déployez-la côté serveur, puis révoquez l'ancienne. Ensuite, déplacez l'appel derrière une route authentifiée avec des limites de débit par utilisateur, et définissez des limites de dépenses chez le fournisseur.

Mon agent de codage peut-il corriger et tester cela pour moi ? Oui. Demandez-lui de déplacer l'appel au fournisseur dans une route serveur, puis utilisez Apidog CLI pour créer et exécuter des tests qui vérifient un 401 sans session, l'absence de motifs de clé dans les réponses et un 429 au-delà de votre limite de débit.

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API