[{"data":1,"prerenderedAt":837},["ShallowReactive",2],{"blog-fr-vite-and-next-public-env-vars":3,"blog-index-fr":596},{"id":4,"title":5,"body":6,"category":548,"cover":549,"coverAlt":550,"description":551,"draft":552,"extension":553,"faq":554,"image":573,"keywords":574,"meta":584,"navigation":585,"ogTitle":586,"path":587,"published":588,"seo":589,"stem":590,"tldr":591,"updated":588,"__hash__":595},"blog_fr\u002Fblog\u002Fvite-and-next-public-env-vars.md","Variables d’environnement Vite exposées : le préfixe dit publier",{"type":7,"value":8,"toc":534},"minimark",[9,25,40,43,48,54,72,86,93,99,105,121,127,133,137,140,151,154,160,164,167,317,323,332,336,339,359,370,374,377,397,407,412,419,423,426,433,453,461,469,473,516,519,526],[10,11,12,13,17,18,21,22,24],"p",{},"Quelqu’un a ouvert votre appli Lovable, appuyé sur F12, et trouvé dans le code\nune valeur que vous êtes certain d’avoir mise dans un fichier ",[14,15,16],"code",{},".env",". Ou vous\navez demandé une fonctionnalité au builder, il a écrit une ligne commençant par\n",[14,19,20],{},"VITE_",", et quelque chose que vous avez lu depuis dit que ce préfixe est par\nlà que les clés fuient. Le fichier a ",[14,23,16],{}," dans son nom et tous les tutoriels\ndisent de ne jamais le partager. Des variables d’environnement Vite exposées à\nchaque visiteur, cela ressemble à un bug de Vite.",[10,26,27,28,32,33,35,36,39],{},"Voici la partie que guide après guide explique de travers : ",[29,30,31],"strong",{},"rien n’a échoué\nà cacher cette valeur."," ",[14,34,20],{}," et ",[14,37,38],{},"NEXT_PUBLIC_"," sont une instruction pour\nvotre outil de build, et l’instruction est de mettre la valeur dans l’appli\nque chaque visiteur télécharge. L’outil a lu l’étiquette et a fait ce qu’elle\ndisait.",[10,41,42],{},"Un build emballe votre appli dans une boîte, et chaque visiteur reçoit une\ncopie de la boîte. Le préfixe est une étiquette sur une valeur qui dit :\nemballe celle-ci aussi. Le reste de cet article porte sur les valeurs pour\nlesquelles cette étiquette est juste, sur la raison pour laquelle l’IA la\ncolle sur les mauvaises, et sur la façon de voir ce qu’il y a dans votre\npropre boîte.",[44,45,47],"h2",{"id":46},"les-variables-denvironnement-vite-sont-elles-exposées-aux-visiteurs","Les variables d’environnement Vite sont-elles exposées aux visiteurs ?",[10,49,50,51,53],{},"Celles qui commencent par ",[14,52,20],{},", oui, et c’est à cela que sert le préfixe.",[10,55,56,57,59,60,63,64,67,68,71],{},"Vite, l’outil de build derrière la plupart des applis Lovable et Bolt, lit\nvotre fichier ",[14,58,16],{}," à chaque build. Une variable nommée ",[14,61,62],{},"VITE_SUPABASE_URL","\nest copiée dans le bundle, le fichier JavaScript compressé que chaque visiteur\ntélécharge, où votre code la lit sous la forme\n",[14,65,66],{},"import.meta.env.VITE_SUPABASE_URL",". Une variable nommée ",[14,69,70],{},"DB_PASSWORD",", sans\npréfixe, arrive vide dans le navigateur. La documentation de Vite elle-même\ndit que les valeurs préfixées sont intégrées à votre code source au moment du\nbuild et ne doivent pas contenir de clés d’API.",[10,73,74,75,77,78,81,82,85],{},"Next.js, avec lequel v0 construit, a la même règle sous un autre nom :\n",[14,76,38],{},". Sa documentation décrit la valeur comme inlined, une chaîne\nfigée écrite dans le bundle du navigateur au moment du build. Expo utilise\n",[14,79,80],{},"EXPO_PUBLIC_"," et prévient avec les mêmes mots. Les anciens projets Create\nReact App utilisent ",[14,83,84],{},"REACT_APP_",". Chaque préfixe dit la même chose à son outil\nde build : celle-ci va dans la boîte.",[44,87,89,90,92],{"id":88},"pourquoi-un-fichier-env-semble-privé-et-ne-lest-pas","Pourquoi un fichier ",[14,91,16],{}," semble privé et ne l’est pas",[10,94,95,96,98],{},"Parce que l’habitude de garder une clé dans un fichier ",[14,97,16],{}," vient des\nserveurs, où elle fonctionne.",[10,100,101,102,104],{},"Sur un serveur, le fichier et le code qui le lit sont sur une machine que vous\ncontrôlez. Un visiteur reçoit une réponse de cette machine et ne voit jamais\nle fichier. Sortir la clé du code et la mettre dans un fichier que le serveur\nlit au démarrage est une bonne pratique là-bas, et c’est là qu’a été écrit\nchaque tutoriel qui dit « mettez-la dans ",[14,103,16],{}," ».",[10,106,107,108,110,111,114,115,117,118,120],{},"Votre fichier ",[14,109,16],{}," a deux lecteurs, et les tutoriels parlent d’un seul. Le\npremier, c’est quiconque peut voir votre projet : un collaborateur, un dépôt\nGitHub public, la vue des fichiers du builder lui-même. Une entrée dans\n",[14,112,113],{},".gitignore",", qui est une liste de fichiers que git laisse de côté, tient\n",[14,116,16],{}," à l’écart de ce lecteur. Le second lecteur est le build, qui ouvre le\nfichier à chaque publication et en copie tout ce qui porte le préfixe.\n",[14,119,113],{}," ne lui dit rien.",[122,123],"diagram",{"alt":124,"caption":125,"src":126},"Un fichier .env au centre avec trois valeurs, deux d’entre elles marquées VITE_. À sa gauche, un mur en pointillés étiqueté .gitignore barre le chemin vers une pile de fichiers de dépôt. À sa droite, les deux valeurs marquées traversent une étape de build jusqu’à une fenêtre de navigateur avec une personne à côté, et la valeur non marquée reste dans le fichier.","Un fichier, deux lecteurs. Le mur .gitignore arrête l’un d’eux. Le build porte chaque valeur préfixée jusqu’à l’autre.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Ftwo-readers-one-file-1600x760.png",[10,128,129,130,132],{},"Donc « mon ",[14,131,16],{}," est dans gitignore » est vrai, et répond à une autre\nquestion. Le fichier est resté hors de votre dépôt. Les valeurs préfixées sont\nquand même entrées dans l’appli, parce que c’est la route que le préfixe\nouvre, et dans un projet Lovable, Bolt ou v0, la plus grande partie du code\nque vous avez modifié tourne dans le navigateur, où il n’y a aucun serveur\nderrière lequel le fichier pourrait rester.",[44,134,136],{"id":135},"pourquoi-lia-a-pris-le-préfixe","Pourquoi l’IA a pris le préfixe",[10,138,139],{},"Parce que c’est ainsi qu’on fait fonctionner une valeur dans du code de\nnavigateur, et que le modèle n’a aucune idée de ce que la valeur coûte.",[10,141,142,143,146,147,150],{},"Vous avez demandé une carte, ou un chat qui répond aux questions sur votre\nproduit. Le code que le builder a écrit pour cela tourne dans le navigateur du\nvisiteur, et du code de navigateur qui lit ",[14,144,145],{},"process.env.OPENAI_API_KEY"," ne\nreçoit rien du tout. Le moyen de faire arriver la valeur, c’est le préfixe. Le\nbuilder renomme la variable ",[14,148,149],{},"VITE_OPENAI_API_KEY",", la fonctionnalité marche\ndans l’aperçu, et aucune erreur n’est levée nulle part, parce que du côté de\nl’outil de build rien ne s’est mal passé.",[10,152,153],{},"Le préfixe ne juge pas. C’est la même instruction pour une clé Google Maps,\nqui est censée être publique une fois restreinte, et pour une clé secrète\nStripe, qui peut rembourser chacun de vos clients. Une personne qui saurait\nque la seconde débite votre carte s’arrêterait. Le modèle sait que la\nfonctionnalité ne marchait pas tant que la ligne n’était pas là, et qu’ensuite\nelle a marché.",[10,155,156,157,159],{},"C’est pour cela que cela apparaît sur des applis dont les propriétaires ont\nfait tout ce qu’on leur a dit. La valeur a été sortie du code, gardée dans\n",[14,158,16],{},", le fichier a été mis dans gitignore, et l’appli la livre quand même,\nparce que la seule étape qui la publie ressemble à l’étape qui la fait\nmarcher.",[44,161,163],{"id":162},"quelles-valeurs-vont-derrière-le-préfixe","Quelles valeurs vont derrière le préfixe",[10,165,166],{},"Une adresse et une clé publiable. Tout ce qui dépense de l’argent ou ignore\nles règles de votre base de données, non.",[168,169,170,192],"table",{},[171,172,173],"thead",{},[174,175,176,180,189],"tr",{},[177,178,179],"th",{},"Valeur",[177,181,182,183,185,186,188],{},"Derrière ",[14,184,20],{}," ou ",[14,187,38],{}," ?",[177,190,191],{},"Pourquoi",[193,194,195,212,231,246,259,273,291,305],"tbody",{},[174,196,197,202,209],{},[198,199,200],"td",{},[14,201,62],{},[198,203,204],{},[205,206,208],"key-verdict",{"type":207},"safe","À sa place",[198,210,211],{},"Une adresse. Elle dit à quel projet votre appli parle, et rien d’autre.",[174,213,214,224,228],{},[198,215,216,219,220,223],{},[14,217,218],{},"VITE_SUPABASE_PUBLISHABLE_KEY",", ou ",[14,221,222],{},"VITE_SUPABASE_ANON_KEY"," sur un projet plus ancien",[198,225,226],{},[205,227,208],{"type":207},[198,229,230],{},"Conçue pour le navigateur. Chaque requête qu’elle fait reste filtrée par Row Level Security, les règles sur chaque table qui décident ligne par ligne qui peut lire quoi.",[174,232,233,239,243],{},[198,234,235,236],{},"Une clé Stripe ",[14,237,238],{},"pk_live_",[198,240,241],{},[205,242,208],{"type":207},[198,244,245],{},"Construit des formulaires de paiement. Ne peut ni débiter, ni rembourser, ni lire les clients.",[174,247,248,251,256],{},[198,249,250],{},"Une clé Google Maps",[198,252,253],{},[205,254,255],{"type":207},"À sa place, une fois restreinte",[198,257,258],{},"Publique par conception. Une restriction par référent dans Google Cloud est ce qui empêche un inconnu de vous facturer avec.",[174,260,261,264,270],{},[198,262,263],{},"Une clé OpenAI ou Anthropic",[198,265,266],{},[205,267,269],{"type":268},"danger","Jamais",[198,271,272],{},"Il n’existe pas de variante publiable. Qui la détient dépense votre argent.",[174,274,275,284,288],{},[198,276,277,278,185,281],{},"Une clé Supabase ",[14,279,280],{},"service_role",[14,282,283],{},"sb_secret_",[198,285,286],{},[205,287,269],{"type":268},[198,289,290],{},"Contourne Row Level Security et lit chaque ligne de chaque table.",[174,292,293,298,302],{},[198,294,235,295],{},[14,296,297],{},"sk_live_",[198,299,300],{},[205,301,269],{"type":268},[198,303,304],{},"Débits, remboursements, virements et chaque fiche client.",[174,306,307,310,314],{},[198,308,309],{},"Une clé d’accès AWS",[198,311,312],{},[205,313,269],{"type":268},[198,315,316],{},"Tout ce que ce compte peut faire, depuis n’importe où.",[10,318,319,320,322],{},"Si votre appli a ",[14,321,62],{}," et une clé publiable à côté, c’est la\npaire que Supabase a prévue pour un navigateur, et notre scan la marque comme\nétant à sa place. L’adresse et la clé publiable sont la raison d’être du\npréfixe.",[10,324,325,326,331],{},"Le test pour tout le reste, c’est de savoir si cela vous gênerait de voir la\nvaleur imprimée sur votre page d’accueil. Le préfixe la met un clic plus loin\nque cela, dans un fichier au lieu de la page, et quiconque veut le fichier\nl’a.\n",[327,328,330],"a",{"href":329},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Distinguer les deux familles",",\npar le préfixe et, sur une ancienne clé Supabase, par le rôle qu’elle\ncontient, est un article à part.",[44,333,335],{"id":334},"ce-que-30-998-applis-livraient-derrière-le-préfixe","Ce que 30 998 applis livraient derrière le préfixe",[10,337,338],{},"Surtout des clés d’API Google. 52 applis livraient une clé qui dépense de\nl’argent ou lit tout.",[10,340,341,342,346,347,351,352,185,355,358],{},"En août 2026, nous avons lancé\n",[327,343,345],{"href":344},"\u002Fresearch\u002Fvibe-coded-app-security-2026","les neuf mêmes vérifications"," sur\n30 998 applis vibe-codées en ligne. 1 332 d’entre elles, soit 4 %, livraient\nquelque chose qui ressemble à une clé dans le code que chaque visiteur\ntélécharge. 1 142 de celles-ci étaient des clés d’API Google, qui ont en\ngénéral besoin d’une\n",[327,348,350],{"href":349},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","restriction définie dans Google Cloud","\net pas d’une rotation. 204 livraient une valeur d’allure aléatoire à côté d’un\nnom comme ",[14,353,354],{},"secret",[14,356,357],{},"password",", qui peut être un vrai identifiant ou non.",[10,360,361,362,364,365,369],{},"Les coûteuses étaient rares. 33 applis livraient une clé OpenAI, 9 une clé\nd’accès AWS, 5 une clé Anthropic, 3 une clé secrète Stripe et 3 une clé\n",[14,363,280],{}," Supabase : 52 applis en tout, puisque l’une d’elles en portait\ndeux. La valeur derrière le préfixe est donc en général une clé Google, et le\nremède pour cela est un réglage. Le cas rare est celui où se trouvent les\ndégâts, et\n",[327,366,368],{"href":367},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","ce que coûte une clé OpenAI qui a fui","\nest l’article pour celui-là.",[44,371,373],{"id":372},"comment-vérifier-ce-que-votre-propre-appli-livre","Comment vérifier ce que votre propre appli livre",[10,375,376],{},"Ouvrez l’appli en ligne, appuyez sur F12, et cherchez la valeur dans chaque\nfichier chargé.",[378,379,380,384,391,394],"ol",{},[381,382,383],"li",{},"Ouvrez votre appli publiée dans un navigateur, à sa vraie adresse.\nL’aperçu du builder est un autre build et peut avoir une version de retard.",[381,385,386,387,390],{},"Appuyez sur F12 pour ouvrir les outils de développement, puis choisissez\nl’onglet ",[29,388,389],{},"Sources",".",[381,392,393],{},"Appuyez sur Ctrl+Maj+F, ou Cmd+Option+F sur un Mac. Cela ouvre une\nrecherche dans chaque fichier que la page a chargé.",[381,395,396],{},"Collez les dix premiers caractères environ de la valeur qui vous inquiète,\net ne la collez nulle part ailleurs.",[10,398,399,400,403,404,406],{},"Un résultat veut dire que la valeur est dans la boîte que reçoit chaque\nvisiteur. Cherchez la valeur plutôt que le nom : le build remplace en général\n",[14,401,402],{},"import.meta.env.VITE_OPENAI_API_KEY"," par la valeur elle-même, si bien qu’une\nrecherche de ",[14,405,20],{}," peut revenir vide alors que chaque valeur qu’il y avait\nderrière est là.",[122,408],{"alt":409,"caption":410,"src":411},"Deux volets. À gauche, un fichier source avec une ligne import.meta.env.VITE_OPENAI_API_KEY parmi des lignes de code unies. À droite, après une étape de build, le même fichier compressé en un bruit dense, le nom de la variable disparu et sa valeur dessinée comme une barre surlignée sous une loupe.","Le build remplace le nom par la valeur. Chercher VITE_ dans l’appli en ligne ne trouve rien ; chercher la valeur la trouve.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fname-goes-value-stays-1600x640.png",[10,413,414,415,390],{},"Si vous préférez ne pas parcourir votre appli valeur par valeur, notre scan\ngratuit lit votre site en ligne depuis l’extérieur, les neuf vérifications, en\n20 secondes environ et sans compte. Il nomme chaque clé trouvée par son type,\ndit lesquelles ont leur place dans un navigateur, et écrit « Impossible à\nvérifier » pour tout ce à quoi il n’a pas pu répondre plutôt qu’une coche :\n",[327,416,418],{"href":417},"\u002Fsecurity-scanner","scannez votre appli",[44,420,422],{"id":421},"où-va-un-vrai-secret-à-la-place","Où va un vrai secret à la place",[10,424,425],{},"Sur une machine depuis laquelle vos visiteurs ne téléchargent jamais rien.\nDans un projet Supabase, c’est une Edge Function, un petit morceau de code\nserveur que Supabase exécute pour vous ; dans une appli Next.js, c’est une\nroute serveur ; dans une appli Replit, c’est la moitié serveur.",[10,427,428,429,432],{},"La forme est la même partout. Votre code de navigateur demande à votre\nfonction de faire le travail. La fonction détient la clé, passe l’appel à\nOpenAI ou Stripe, et renvoie la réponse. La clé reste sur la machine et le\nvisiteur reçoit un résultat.\nL’",[327,430,431],{"href":367},"article sur OpenAI"," le dessine\ncomme un objet qui se déplace d’une case vers la droite, et le changement se\nrésume à cela.",[10,434,435,436,439,440,442,443,185,446,449,450,390],{},"Deux choses vous disent que le builder a fait ce que vous avez demandé. La\nvariable a perdu son préfixe, donc c’est ",[14,437,438],{},"OPENAI_API_KEY",", et elle vit dans\nles secrets propres à la fonction, définis dans le tableau de bord Supabase\nsous Edge Functions, sans rien dans le ",[14,441,16],{}," de l’appli. Et le fichier qui la\nlit se trouve sous ",[14,444,445],{},"supabase\u002Ffunctions\u002F",[14,447,448],{},"app\u002Fapi\u002F",", quelque part que le\nbuild n’emballe jamais, au lieu de sous ",[14,451,452],{},"src\u002F",[10,454,455,456,460],{},"Un ordre compte, et il est facile de l’inverser. Si une clé secrète a déjà été\nlivrée derrière un préfixe, la déplacer ne fait rien pour les copies déjà\ntéléchargées. Renouvelez-la d’abord chez le fournisseur, puis déplacez le\ntravail.\n",[327,457,459],{"href":458},"\u002Fblog\u002Frotate-supabase-service-role-key","Renouveler d’abord ou fermer la fuite d’abord","\ndépend de si la copie est déjà publique, et dès qu’elle a été dans un bundle\npublié, elle l’est.",[10,462,463,464,468],{},"Pour un projet Replit, la même séparation a son propre nom, Secrets, et\n",[327,465,467],{"href":466},"\u002Fblog\u002Freplit-secrets-explained","ce que l’outil Secrets couvre et ce qu’il ne couvre pas","\nest un article à part.",[44,470,472],{"id":471},"quoi-faire-maintenant","Quoi faire maintenant",[474,475,476],"key-takeaways",{},[477,478,479,492,504,507,510,513],"ul",{},[381,480,481,482,484,485,484,487,35,489,491],{},"Cherchez dans votre projet ",[14,483,20],{},", ",[14,486,38],{},[14,488,80],{},[14,490,84],{},". Chaque occurrence est une valeur que votre build publie exprès. Décidez pour chacune si elle peut être publique.",[381,493,494,495,35,497,499,500,503],{},"Gardez l’adresse et la clé publiable. ",[14,496,62],{},[14,498,218],{},", ou la clé ",[14,501,502],{},"anon"," sur un projet plus ancien, sont la paire pour laquelle le préfixe existe.",[381,505,506],{},"Une clé secrète derrière un préfixe est d’abord renouvelée chez le fournisseur, puis déplacée. Supprimer la ligne ne rappelle pas une copie déjà téléchargée.",[381,508,509],{},"Déplacez le travail qui avait besoin de la clé dans une Edge Function ou une route serveur, avec la clé dans les secrets de cette fonction et sans préfixe sur son nom.",[381,511,512],{},"Restreignez une clé Google par référent dans Google Cloud. Celle-là a besoin d’un réglage et garde sa valeur.",[381,514,515],{},"Après la prochaine publication, cherchez dans l’appli en ligne chaque valeur que vous avez déplacée.",[10,517,518],{},"Chaque publication emballe une nouvelle boîte. La prochaine fonctionnalité que\nvous demandez est une nouvelle occasion pour une valeur de recevoir le\npréfixe, et rien entre le builder et internet ne lit le bundle en sortie. Un\nscan du mois dernier a lu le bundle du mois dernier.",[10,520,521,525],{},[327,522,524],{"href":523},"\u002Fpricing","Reeve Monitor"," lit le bundle pour vous. Il relance les neuf\nvérifications toutes les heures sur trois applis au plus, vous prévient quand\nun résultat change, surveille la disponibilité toutes les 60 secondes, et\nenvoie un rapport mensuel. Une clé qui atteint le bundle avec la publication\nde mardi figure dans le re-scan de cette heure-là, que vous ayez pensé à\nregarder ou non. Il coûte €12 par mois au tarif de base, avec sept jours\ngratuits avant de vous facturer ; la page des tarifs est parfois en dessous du\nchiffre donné ici et jamais au-dessus.",[10,527,528,529,533],{},"Si vous préférez traiter cela sous forme de liste, la\n",[327,530,532],{"href":531},"\u002Fchecklist","checklist de sécurité en 10 minutes"," couvre ce point et les\nautres choses qu’il vaut la peine de désactiver dans une appli fraîchement\nlancée.",{"title":535,"searchDepth":536,"depth":536,"links":537},"",3,[538,540,542,543,544,545,546,547],{"id":46,"depth":539,"text":47},2,{"id":88,"depth":539,"text":541},"Pourquoi un fichier .env semble privé et ne l’est pas",{"id":135,"depth":539,"text":136},{"id":162,"depth":539,"text":163},{"id":334,"depth":539,"text":335},{"id":372,"depth":539,"text":373},{"id":421,"depth":539,"text":422},{"id":471,"depth":539,"text":472},"Bases de la sécurité","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcover-1200x630.png","Un fichier .env avec trois valeurs, deux étiquetées VITE_, et ces deux valeurs redessinées dans une fenêtre de navigateur à côté.","Variables d’environnement Vite exposées : votre appli a fait ce que le préfixe demandait. VITE_ et NEXT_PUBLIC_ veulent dire publier, et l’IA ignorait le prix.",false,"md",[555,558,561,564,567,570],{"q":556,"a":557},"Les fichiers .env sont-ils secrets ?","Pour votre dépôt, oui, si le fichier est listé dans .gitignore. Pour vos visiteurs, non. Le build lit .env à chaque publication et copie chaque valeur portant le préfixe VITE_ ou NEXT_PUBLIC_ dans le JavaScript que livre votre appli. Le fichier lui-même ne quitte jamais votre machine ; les valeurs que vous avez étiquetées pour le navigateur, si.",{"q":559,"a":560},"Peut-on exposer VITE_SUPABASE_ANON_KEY sans risque ?","Elle est faite pour être là. La clé anon, appelée clé publiable sur un projet récent, est conçue pour vivre dans un navigateur. Elle dit seulement à quel projet appartient une requête, et chaque requête qu’elle fait est filtrée par vos règles Row Level Security. Cela tient exactement tant que ces règles sont activées et correctes, ce qui est une vérification à part.",{"q":562,"a":563},"NEXT_PUBLIC_ est-il différent de VITE_ ?","Même règle, autre outil de build. Next.js écrit la valeur de toute variable NEXT_PUBLIC_ dans le bundle du navigateur comme une chaîne figée au moment du build, et une variable sans le préfixe arrive vide dans le code du navigateur. Expo fait pareil avec EXPO_PUBLIC_, et les anciens projets Create React App avec REACT_APP_. Quel que soit l’outil qui a construit votre appli, le préfixe veut dire publier.",{"q":565,"a":566},"Comment vérifier ce qu’il y a dans mon bundle ?","Ouvrez l’appli en ligne, appuyez sur F12, choisissez Sources et appuyez sur Ctrl+Maj+F (Cmd+Option+F sur un Mac) pour chercher dans chaque fichier que la page a chargé. Collez les premiers caractères de la valeur. Cherchez la valeur plutôt que le nom de la variable, parce que le build remplace en général le nom par la valeur, si bien que VITE_ peut être absent alors que la clé est là. Notre scan gratuit fait la même lecture depuis l’extérieur en 20 secondes environ.",{"q":568,"a":569},"Où doit vivre une clé secrète dans une appli Lovable ou Bolt ?","Dans une Supabase Edge Function, avec la clé définie dans les secrets de cette fonction dans le tableau de bord Supabase et sans préfixe VITE_ sur son nom. Votre code du navigateur appelle la fonction, la fonction appelle le fournisseur avec la clé, et la clé n’atteint jamais un visiteur. Si la clé a déjà été livrée, renouvelez-la chez le fournisseur avant de la déplacer.",{"q":571,"a":572},".gitignore protège-t-il mes clés ?","Il garde le fichier .env hors de git, donc personne qui lit votre dépôt ne le voit. Il n’a aucun effet sur le build, qui lit le fichier directement et publie chaque valeur préfixée. Un .env ignoré par git avec VITE_OPENAI_API_KEY dedans livre quand même cette clé à chaque visiteur.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",[575,576,577,578,579,580,581,582,583],"variables d’environnement vite exposées","préfixe VITE_ sécurité","next_public_ variable d’environnement secrète","les variables .env sont-elles sûres en react","vite_ est-il sûr","variables d’environnement dans le frontend","fichier .env exposé dans le navigateur","expo_public env","cacher une clé api dans le frontend",{},true,"Variables d’environnement Vite exposées : VITE_ veut dire publier","\u002Fblog\u002Fvite-and-next-public-env-vars","2026-09-18",{"title":5,"description":551},"blog\u002Fvite-and-next-public-env-vars",[592,593,594],"Les variables d’environnement Vite exposées dans votre appli sont là parce que le préfixe l’a demandé. Une variable nommée VITE_ ou NEXT_PUBLIC_ est copiée dans le JavaScript que chaque visiteur télécharge, et la garder dans un fichier .env n’y change rien.","Le préfixe est la bonne étiquette pour une adresse ou une clé publiable, et la mauvaise pour tout ce qui dépense de l’argent ou ignore les règles de votre base de données. Le build ne fait pas la différence, et l’IA qui a écrit la ligne non plus.","Sur 30 998 applis vibe-codées en ligne que nous avons scannées, 1 332 livraient quelque chose qui ressemble à une clé. 1 142 d’entre elles étaient des clés d’API Google, qui ont en général besoin d’une restriction et pas d’une rotation. 52 livraient une clé qui dépense de l’argent ou lit tout.","XyE975e3jSEUY-yOGhhbzspGtO42iiU4kNDTFBuQWic",[597,604,610,616,622,628,629,635,641,647,653,659,665,671,677,683,688,694,700,706,712,717,723,729,734,740,746,752,758,764,770,776,782,787,793,799,804,810,816,822,827,833],{"path":598,"title":599,"description":600,"published":601,"category":602,"image":603,"draft":552},"\u002Fblog\u002Fsupabase-backup-auth-users","Pourquoi votre dump Supabase ne contient aucun utilisateur","Lancez supabase db dump tout seul et vous obtenez la forme de votre base et aucune de ses lignes, sans le schéma auth où vivent vos utilisateurs.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":605,"title":606,"description":607,"published":608,"category":548,"image":609,"draft":552},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domaine expiré, site hors ligne : ce qui se passe ensuite","Votre domaine a expiré et votre site est hors ligne. Le compte à rebours qui démarre, pourquoi le certificat est le moindre souci, et comment vérifier les deux.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":611,"title":612,"description":613,"published":614,"category":548,"image":615,"draft":552},"\u002Fblog\u002Fis-lovable-safe","Lovable est-il sûr ? Ce que 18 554 applications Lovable ont montré","Lovable est-il sûr ? 18 554 applications, neuf vérifications. La plateforme était la plus propre des cinq. Les trouvailles étaient dans les applications.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":617,"title":618,"description":619,"published":620,"category":548,"image":621,"draft":552},"\u002Fblog\u002Fvibe-coded-app-security-checklist","La checklist de sécurité du vibe coding, en neuf vérifications","Une checklist de sécurité du vibe coding en neuf points, chacun vérifiable de l’extérieur sur votre appli en ligne, et chacun avec un test d’une ligne.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":623,"title":624,"description":625,"published":626,"category":548,"image":627,"draft":552},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Une clé secrète Stripe dans votre frontend peut déplacer de l’argent","Une clé secrète Stripe exposée dans votre frontend peut rembourser, débiter et lire chaque fiche client que vous détenez. Votre clé pk_live_ y a sa place.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":587,"title":5,"description":551,"published":588,"category":548,"image":573,"draft":552},{"path":630,"title":631,"description":632,"published":633,"category":548,"image":634,"draft":552},"\u002Fblog\u002Fbase44-source-maps","Sécurité Base44 : ce qu’un scan signale, et ce qui dépend de vous","Sécurité Base44 sur 5 438 applis : trois signalements sur presque chacune sont ceux de la plateforme, la source map est le badge Base44, votre part est courte.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":636,"title":637,"description":638,"published":639,"category":548,"image":640,"draft":552},"\u002Fblog\u002Fis-cursor-ai-safe","Cursor AI est-il sûr ? L’éditeur, le code et l’appli publiée","Cursor AI est-il sûr ? Trois questions dans une recherche : ce que Cursor garde, ce que son code rate, et si l’appli que vous avez publiée est ouverte.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":642,"title":643,"description":644,"published":645,"category":548,"image":646,"draft":552},"\u002Fblog\u002Fis-replit-safe","Replit est-il sûr ? Ce que 3 042 applications Replit nous ont montré","Replit est-il sûr ? 3 042 applications Replit en ligne, neuf vérifications externes. Les trouvailles étaient dans l’application publiée, pas chez l’hébergeur.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":648,"title":649,"description":650,"published":651,"category":602,"image":652,"draft":552},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup : votre copie de base n'a aucun fichier","Un Supabase storage backup est une tâche à part. Les sauvegardes de la base gardent la liste de vos fichiers et aucun des fichiers, donc chaque upload casse.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":654,"title":655,"description":656,"published":657,"category":602,"image":658,"draft":552},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery Supabase : prix et limites","Le point-in-time recovery de Supabase rembobine votre base à la seconde près sur la dernière semaine. $100 par mois en plus de Pro, et rien que la base.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":660,"title":661,"description":662,"published":663,"category":602,"image":664,"draft":552},"\u002Fblog\u002Fsupabase-project-paused-recover","Projet Supabase en pause ? Vos données sont toujours là","Supabase a mis votre projet en pause après une semaine sans activité. Rien n'est supprimé, Restaurer est à côté du nom, et vous avez un an pour cliquer.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":666,"title":667,"description":668,"published":669,"category":548,"image":670,"draft":552},"\u002Fblog\u002Fsafest-ai-app-builder","Quel builder d'app IA est le plus sûr ? 30 998 apps testées","Quel builder d'app IA est le plus sûr ? Nous avons scanné 30 998 apps actives de Lovable, Base44, Replit, v0 et Bolt. Ce n'est pas le builder qui décide.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":672,"title":673,"description":674,"published":675,"category":548,"image":676,"draft":552},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Activer Row Level Security sur chaque table Supabase, et le prouver","Activer Row Level Security dans Supabase sans politique ferme la table entièrement. Une politique sans le réglage ne fait rien. Voici le SQL, et le test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":678,"title":679,"description":680,"published":681,"category":548,"image":682,"draft":552},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\" : ce que l'alerte rate","Supabase signale \"RLS disabled in public\" comme une erreur. Elle ne dit rien de la politique de lecture qui laisse votre table tout aussi ouverte.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":458,"title":684,"description":685,"published":686,"category":548,"image":687,"draft":552},"Faire tourner une clé service_role Supabase qui a fuité","Supabase dit de colmater la fuite d'abord. D'autres guides disent de faire tourner la clé tout de suite. Tout dépend d'où votre clé service_role a fuité.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":689,"title":690,"description":691,"published":692,"category":548,"image":693,"draft":552},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de sécurité vibe coding comparés, le nôtre compris","Le meilleur scanner de sécurité vibe coding tient à trois questions qu'aucune liste de fonctions ne traite. Dix outils comparés, avec les prix.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":695,"title":696,"description":697,"published":698,"category":548,"image":699,"draft":552},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker : les cinq vérifications à faire soi-même","Un Supabase security checker lit votre app publiée plutôt que les réglages de votre projet. Voici les cinq vérifications, et comment faire chacune vous-même.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":548,"image":705,"draft":552},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de sécurité vibe coding : ce qu’un scan d’URL rate","Un scanner de sécurité vibe coding lit votre app en ligne depuis l’extérieur. Ce qu’il couvre, les quatre choses qu’il ne voit pas, et comment lire le résultat.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":707,"title":708,"description":709,"published":710,"category":548,"image":711,"draft":552},"\u002Fblog\u002Fmissing-security-headers","En-têtes de sécurité manquants : quand cela compte","Les en-têtes de sécurité manquants sont notre constat le plus fréquent. Contre quoi ils protègent, et quand ils comptent le moins dans votre rapport.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":367,"title":713,"description":714,"published":715,"category":548,"image":716,"draft":552},"Votre clé API OpenAI est exposée dans votre frontend. Changez-la.","Une clé API OpenAI exposée dans votre frontend ne peut être liée à aucun domaine. Changez-la aujourd'hui, passez par votre serveur et plafonnez la dépense.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":718,"title":719,"description":720,"published":721,"category":548,"image":722,"draft":552},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","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.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":724,"title":725,"description":726,"published":727,"category":602,"image":728,"draft":552},"\u002Fblog\u002Fsupabase-backup-tools-compared","Outils de sauvegarde Supabase comparés, le nôtre compris","Quatre familles d'outil de sauvegarde Supabase, ce que chacun copie vraiment, et quand une GitHub Action gratuite bat le fait de payer, nous compris.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":466,"title":730,"description":731,"published":732,"category":548,"image":733,"draft":552},"Utiliser les secrets sur Replit, et ce qui est publié quand même","Utiliser les secrets sur Replit : en ajouter un, le relire, corriger les deux causes du undefined. Et les clés que l'outil Secrets ne peut pas protéger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":735,"title":736,"description":737,"published":738,"category":602,"image":739,"draft":552},"\u002Fblog\u002Fback-up-supabase-free-tier","Sauvegardes du plan gratuit Supabase : en faire une sans terminal","Le plan gratuit de Supabase ne fait aucune sauvegarde : la copie vient de vous. Comment la faire depuis le tableau de bord, et ce que le CSV oublie.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":741,"title":742,"description":743,"published":744,"category":548,"image":745,"draft":552},"\u002Fblog\u002Fis-supabase-secure","Supabase est-il sûr ? Oui. Votre projet est une autre question","Supabase est-il sûr ? La plateforme est auditée, chiffrée et testée en intrusion. Sa documentation dit où cela s'arrête et où vos réglages commencent.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":747,"title":748,"description":749,"published":750,"category":548,"image":751,"draft":552},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Où trouver vos clés API Supabase : anon, service_role et URL","L'URL du projet, la clé anon et la clé service_role tiennent sur une page du tableau de bord. Voici où elle est, et laquelle des quatre va dans votre app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":753,"title":754,"description":755,"published":756,"category":548,"image":757,"draft":552},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy sur Supabase : et après ?","\"New row violates row-level security policy\" signifie que Supabase a refusé une écriture. Le correctif rapide rouvre la table à tout le monde.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":759,"title":760,"description":761,"published":762,"category":548,"image":763,"draft":552},"\u002Fblog\u002Fcors-wildcard-security-risk","Un joker CORS est-il un risque de sécurité ? Rarement.","Un joker CORS est-il un risque de sécurité ? C'est souvent le réglage par défaut de votre builder, et il ne livre rien que votre serveur ne donnait déjà.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":765,"title":766,"description":767,"published":768,"category":602,"image":769,"draft":552},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Le branching Supabase n'est pas une sauvegarde de vos données.","Pourquoi le branching Supabase n'est pas une sauvegarde : une branche démarre sans vos données, et un merge ne déplace que le schéma. À quoi il sert vraiment.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":771,"title":772,"description":773,"published":774,"category":602,"image":775,"draft":552},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Restaurer une sauvegarde Supabase, et ce qui casse après","Restaurer une sauvegarde Supabase depuis le tableau de bord ou un fichier de dump, ce que la restauration remplace et pourquoi votre app peut rester cassée.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":777,"title":778,"description":779,"published":780,"category":548,"image":781,"draft":552},"\u002Fblog\u002Fsupabase-storage-bucket-public","Votre bucket Supabase Storage est public. Est-ce un problème ?","Un bucket Supabase Storage public signifie que celui qui a l'URL d'un fichier peut l'ouvrir. Il ne signifie pas que quelqu'un peut lister ce qu'il contient.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":349,"title":783,"description":784,"published":785,"category":548,"image":786,"draft":552},"Une clé API Google dans votre frontend, est-ce un problème ?","Une clé API Google exposée dans votre frontend est la clé que notre scanner trouve le plus souvent, et en général tout va bien. Un réglage gratuit tranche.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":788,"title":789,"description":790,"published":791,"category":602,"image":792,"draft":552},"\u002Fblog\u002Fai-agent-deleted-my-database","Un agent IA a supprimé mes données Supabase. Que puis-je récupérer ?","Un agent IA a supprimé des données de votre base. Ce que vous pouvez récupérer était déjà décidé avant, et les prochaines minutes décident du reste.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":794,"title":795,"description":796,"published":797,"category":548,"image":798,"draft":552},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Qui peut lire votre base Supabase ? Nous avons testé 3 680 apps","N'importe qui peut-il lire votre base de données Supabase sans se connecter ? Nous avons scanné 30 998 apps en ligne créées avec des builders IA.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":800,"title":801,"description":802,"published":797,"category":548,"image":803,"draft":552},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps exposées : votre app publie son code original","Une source map exposée laisse n'importe qui lire le code original de votre app, commentaires compris. Le test de 30 secondes, et ce qui compte vraiment.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":805,"title":806,"description":807,"published":808,"category":548,"image":809,"draft":552},"\u002Fblog\u002Fsupabase-new-api-keys","Les nouvelles clés API Supabase : laquelle va dans votre app ?","Supabase a remplacé anon et service_role par des clés publiables et secrètes. Laquelle a sa place dans votre app, et laquelle jamais ?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":811,"title":812,"description":813,"published":814,"category":602,"image":815,"draft":552},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Supabase sauvegarde-t-il ma base de données ? Cela dépend du plan.","Supabase sauvegarde-t-il votre base de données ? Chaque jour sur les plans payants, jamais sur le gratuit. Comment savoir ce que vous avez vraiment.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":817,"title":818,"description":819,"published":820,"category":548,"image":821,"draft":552},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security est activé. La table reste publique.","Activer Supabase Row Level Security ne protège pas une table. Ce sont vos politiques, et celle qui a réparé votre app laisse peut-être entrer tout le monde.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":823,"title":824,"description":825,"published":820,"category":602,"image":826,"draft":552},"\u002Fblog\u002Fversion-history-is-not-a-backup","L'historique des versions n'est pas une sauvegarde de vos données.","Lovable et Bolt tiennent un historique des versions de votre code. Votre base de données est un service à part, et revenir en arrière ne la ramène pas.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":828,"title":829,"description":830,"published":831,"category":602,"image":832,"draft":552},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Trois façons de sauvegarder une base Supabase, et ce qui manque","Le tableau de bord, pg_dump et un service géré. Ce que chacun enregistre, ce qu'il laisse de côté sans le dire, et lequel survit à la perte du compte.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":329,"title":834,"description":835,"published":831,"category":548,"image":836,"draft":552},"Quelles clés API sont sûres côté navigateur, et lesquelles non","Votre clé anon Supabase est faite pour être publique. Votre clé service_role non, et elle ignore toutes les règles que vous posez. Comment les distinguer.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150953865]