[{"data":1,"prerenderedAt":713},["ShallowReactive",2],{"blog-de-openai-api-key-exposed-in-frontend":3,"blog-index-de":471},{"id":4,"title":5,"body":6,"category":428,"cover":429,"coverAlt":430,"description":431,"draft":432,"extension":433,"faq":434,"image":450,"keywords":451,"meta":457,"navigation":458,"ogTitle":459,"path":460,"published":461,"seo":462,"stem":463,"tldr":464,"updated":469,"__hash__":470},"blog_de\u002Fblog\u002Fopenai-api-key-exposed-in-frontend.md","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.",{"type":7,"value":8,"toc":414},"minimark",[9,18,26,35,40,43,54,57,60,64,67,82,96,99,103,106,114,117,123,131,134,140,151,154,158,161,164,167,170,174,177,180,185,188,214,217,220,224,242,245,248,253,348,351,367,371,397],[10,11,12,13,17],"p",{},"Öffne deine App in einem Browser, sieh dir den Seitenquelltext an und such darin\nnach ",[14,15,16],"code",{},"sk-proj-",". Kommt eine lange Zeichenkette zurück, liegt dein\nOpenAI-API-Schlüssel offen im Frontend, und jeder Besucher, den du je hattest,\nhätte ihn kopieren können.",[10,19,20,21,25],{},"Hier ist der Teil, den die meisten Ratschläge dazu falsch machen: ",[22,23,24],"strong",{},"ein\nOpenAI-Schlüssel ist kein Google-Schlüssel mit anderem Präfix, und nichts, was du\nin einem Dashboard einstellen kannst, macht ihn dort unbedenklich."," Ein\nGoogle-Maps-Schlüssel gehört in deine Seite, und eine kostenlose Einstellung\nschützt ihn. Ein OpenAI-Schlüssel hat nirgends eine vergleichbare Einstellung,\nund deshalb lautet die einzige ehrliche erste Anweisung, ihn auszutauschen.",[10,27,28,29,34],{},"Zwischen dem 12. und 14. August 2026 haben wir neun externe Prüfungen über 30.998\nlive erreichbare Apps laufen lassen, gebaut mit Lovable, Bolt, v0, Replit und\nBase44. In 33 davon tauchte ein OpenAI-Schlüssel auf. Alle 33 kamen mit Note D\noder F zurück, weil ein einziger kritischer Fund die Note deckelt, egal was die\nApp sonst richtig gemacht hat. Die vollständigen Zahlen stehen in\n",[30,31,33],"a",{"href":32},"\u002Fresearch\u002Fvibe-coded-app-security-2026","unserem Scan-Bericht",".",[36,37,39],"h2",{"id":38},"ist-ein-openai-api-schlüssel-im-frontend-ein-problem","Ist ein OpenAI-API-Schlüssel im Frontend ein Problem?",[10,41,42],{},"Ja. Das ist der Fall, in dem der Alarm recht hat.",[10,44,45,46,49,50,53],{},"Ein OpenAI-Schlüssel ist ein ",[22,47,48],{},"Bearer-Token",", und das Wort trägt die ganze\nErklärung: wer ihn trägt, darf ihn benutzen. Er reist in einem Header, der\n",[14,51,52],{},"Authorization: Bearer sk-proj-…"," lautet, und die Server von OpenAI fragen nach\nnichts weiter. Nicht, welche Website ihn geschickt hat. Nicht, aus welchem Land er\nkam oder ob der Absender du bist.",[10,55,56],{},"Denk an eine Fahrkarte statt an einen Reisepass. Ein Schaffner prüft nicht,\nwessen Name auf einer Fahrkarte steht, denn sie zu besitzen ist die ganze\nBerechtigung. Das macht eine Fahrkarte diebstahlswert und einen Reisepass meistens\nnicht.",[10,58,59],{},"Ein in deine App gedruckter Schlüssel ist also eine Fahrkarte, die du jedem\nBesucher in die Hand gedrückt hast. Die meisten werden nie hinsehen. Die, die\nhinsehen, sind meist überhaupt keine Menschen: automatische Scraper durchsuchen\nöffentliche Seiten nach schlüsselförmigen Zeichenketten, und sie müssen nicht\nwissen, wer du bist, um deine zu finden.",[36,61,63],{"id":62},"warum-die-umgebungsvariable-ihn-nicht-versteckt-hat","Warum die Umgebungsvariable ihn nicht versteckt hat",[10,65,66],{},"Weil ein Frontend-Build Umgebungsvariablen in die Datei kompiliert, die er\nausliefert.",[10,68,69,70,73,74,77,78,81],{},"Das ist der Schritt, der die Leute sicher sein lässt, der Schlüssel sei\ngeschützt. Du hast ihn aus deinem Code in eine ",[14,71,72],{},".env","-Datei geholt, ihn\n",[14,75,76],{},"VITE_OPENAI_API_KEY"," oder ",[14,79,80],{},"NEXT_PUBLIC_OPENAI_API_KEY"," genannt, und jetzt nennt\nder Code eine Variable, wo vorher der Schlüssel stand. An der ausgelieferten App\nhat sich nichts geändert. Das Build-Werkzeug hat diese Variable auf dem Weg nach\ndraußen durch ihren Wert ersetzt, und der Wert liegt in dem JavaScript, das dein\nBesucher herunterlädt.",[10,83,84,85,88,89,91,92,95],{},"Die Dokumentation von Vite sagt es unmissverständlich: Variablen mit dem Präfix\n",[14,86,87],{},"VITE_"," werden nach dem Bundling im clientseitigen Quellcode offengelegt, und\nsensible Informationen wie API-Schlüssel gehören nicht in eine davon, weil die\nWerte in deinen Quellcode gebündelt werden. Die Präfixe ",[14,90,87],{}," und\n",[14,93,94],{},"NEXT_PUBLIC_"," sind keine sichere Schachtel. Sie sind eine Erklärung, dass du\nverstanden hast, dass diese Variable öffentlich ist.",[10,97,98],{},"Eine Umgebungsvariable hat sehr wohl eine echte Sache für dich getan: sie hat den\nSchlüssel aus deinem Repository herausgehalten, wo ihn jeder gefunden hätte, der\ndeinen Code liest. Deine Besucher lesen deinen Code nie. Sie lesen die Datei, die\ndein Build daraus gemacht hat.",[36,100,102],{"id":101},"warum-du-ihn-nicht-wie-einen-google-schlüssel-einschränken-kannst","Warum du ihn nicht wie einen Google-Schlüssel einschränken kannst",[10,104,105],{},"Weil OpenAI keine Einschränkung dieser Art anbietet.",[10,107,108,109,113],{},"Wenn du über einen Google-API-Schlüssel im Frontend gelesen hast, bist du einer\nLösung von fünf Minuten begegnet: Schlüssel in der Google Cloud Console öffnen,\neine HTTP-Referrer-Einschränkung setzen, und der in deiner Seite abgedruckte\nSchlüssel funktioniert auf deiner Website und liefert überall sonst einen Fehler.\n",[30,110,112],{"href":111},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Dieser Rat ist für einen Google-Schlüssel richtig",",\nund er trägt nicht hinüber.",[10,115,116],{},"Es gibt kein Feld an einem OpenAI-Schlüssel für \"nur von yourapp.com\". Keine\nDomain-Zulassungsliste, keine Referrer-Prüfung und keine IP-Einschränkung, die\neinen Browser überlebt. Was OpenAI dir stattdessen gibt, sitzt am Konto hinter\ndem Schlüssel: zu welchem Projekt er gehört, was dieses Projekt im Monat ausgeben\ndarf und ob der Schlüssel noch existiert. Das begrenzt, was ein gestohlener\nSchlüssel kosten kann. Der Schlüssel selbst funktioniert von überall weiter, bis\ndu ihn löschst.",[118,119],"diagram",{"alt":120,"caption":121,"src":122},"Zwei Bahnen. In der oberen Bahn verlässt ein Google-Schlüssel zwei verschiedene Websites und trifft auf eine massive Sperre: die Anfrage von yourapp.com kommt durch und erreicht Google, die von other.example wird gestoppt und mit einem Kreuz markiert. In der unteren Bahn verlässt ein OpenAI-Schlüssel dieselben zwei Websites, es ist gar keine Sperre gezeichnet, und beide Anfragen erreichen api.openai.com.","Die obere Bahn ist die Lösung, von der man den Leuten erzählt. In der unteren gibt es nichts zu zeichnen, weil OpenAI keine Einstellung dieser Form hat.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fno-gate-to-set-1600x820.png",[36,124,126,127,130],{"id":125},"was-dangerouslyallowbrowser-tatsächlich-tut","Was ",[14,128,129],{},"dangerouslyAllowBrowser"," tatsächlich tut",[10,132,133],{},"Es schaltet eine Absicherung ab, und sein Name ist die Dokumentation.",[10,135,136,137,139],{},"Die offizielle JavaScript-Bibliothek von OpenAI weigert sich, standardmäßig in\neinem Browser zu laufen. Die README sagt, die Browser-Unterstützung sei\n\"disabled by default to avoid exposing your secret API credentials\", und das\nEinschalten von ",[14,138,129],{}," \"can be dangerous because it exposes\nyour secret API credentials in the client-side code\".",[10,141,142,143,146,147,150],{},"Wenn deine App OpenAI aus dem Browser aufruft, steht diese Option irgendwo in\ndeinem Code auf ",[14,144,145],{},"true",", denn die Bibliothek startet ohne sie nicht. Jemand hat das\nWort ",[14,148,149],{},"dangerously"," getippt, um eine Fehlermeldung loszuwerden. So kommt dieser\nFund üblicherweise zustande, und die Bibliothek hat es dir zuerst gesagt.",[10,152,153],{},"Die Option hat echte Anwendungen, und alle sind eng: ein internes Werkzeug, bei\ndem du jeden Nutzer kennst, ein vorübergehender Entwicklungsschlüssel, ein so\neng zugeschnittener Schlüssel, dass ihn auszugeben nichts kostet. Eine\nöffentliche App im offenen Internet ist keines davon.",[36,155,157],{"id":156},"was-es-kostet-wenn-jemand-deinen-schlüssel-findet","Was es kostet, wenn jemand deinen Schlüssel findet",[10,159,160],{},"Eine Rechnung, und eine App, die aufhört zu funktionieren.",[10,162,163],{},"Die Rechnung ist der Teil, den die Leute erwarten. Die Anfragen von jemand\nanderem werden deinem Konto belastet, und Modellaufrufe sind nach den Maßstäben\neines Nebenprojekts nicht billig. Üblicherweise merkt ein Betreiber es an einer\nRechnung, die größer ist als die des Vormonats, ohne dass er einen Grund benennen\nkönnte.",[10,165,166],{},"Der Ausfall ist der Teil, den sie nicht erwarten. Dein Konto hat Ratenlimits, und\nder Verkehr eines Fremden verbraucht sie. Deine eigene App fängt an, in den\nStunden Fehler zu liefern, in denen jemand anderes beschäftigt ist, und das liest\nsich wie ein Bug statt wie ein Diebstahl, also verbringen Leute einen Tag damit,\ndas Falsche zu debuggen.",[10,168,169],{},"Es gibt eine dritte Kostenart, und sie hängt davon ab, wie eng der Schlüssel\nzugeschnitten war. Ein API-Schlüssel authentifiziert jeden Aufruf, den das\nProjekt machen kann, zu dem er gehört, also erreicht ein breit zugeschnittener\nSchlüssel alles andere, was dort liegt: in das Konto hochgeladene Dateien,\nfeinabgestimmte Modelle, von dir gebaute Assistenten. Prüfe, was der Schlüssel\ntatsächlich erreichen konnte, bevor du entscheidest, dass es hier nur um Geld\nging.",[36,171,173],{"id":172},"wie-du-openai-aufrufst-ohne-den-schlüssel-auszuliefern","Wie du OpenAI aufrufst, ohne den Schlüssel auszuliefern",[10,175,176],{},"Stell etwas von dir zwischen deinen Besucher und OpenAI.",[10,178,179],{},"Die Form ist überall dieselbe. Deine App ruft einen kleinen Endpunkt auf, der dir\ngehört. Dieser Endpunkt hält den Schlüssel, ruft OpenAI auf und reicht die\nAntwort zurück. Der Browser sieht den Schlüssel nie, weil der Schlüssel deinen\nServer nie verlässt.",[118,181],{"alt":182,"caption":183,"src":184},"Zwei Reihen. In der oberen Reihe hält ein Browserfenster einen roten Schlüsselwert, und eine Linie läuft von dort direkt zu api.openai.com. In der unteren Reihe hält das Browserfenster keinen Schlüssel, eine Linie läuft zu einem Serverkasten, der den Schlüssel in Türkis hält, und eine zweite Linie läuft vom Server weiter zu api.openai.com.","In beiden Reihen dieselbe Anfrage. Was sich ändert, ist, auf welcher Seite deines eigenen Servers der Schlüssel steht.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fwho-holds-the-key-1600x720.png",[10,186,187],{},"Wo dieser Endpunkt liegt, hängt davon ab, womit du gebaut hast:",[189,190,191,198,208],"ul",{},[192,193,194,197],"li",{},[22,195,196],{},"Supabase in deinem Stack",": eine Edge Function, mit dem Schlüssel als Secret im Supabase-Dashboard.",[192,199,200,203,204,207],{},[22,201,202],{},"Auf Vercel oder Netlify deployt",": eine Serverless Function unter ",[14,205,206],{},"\u002Fapi",", mit dem Schlüssel in den serverseitigen Umgebungsvariablen des Projekts.",[192,209,210,213],{},[22,211,212],{},"Lovable, Bolt oder Replit",": jedes hat einen eigenen Secrets-Speicher. Die Regel ändert sich nicht, und die Falle auch nicht: ein Speicher mit der Aufschrift Secrets liefert den Wert trotzdem an den Browser, wenn der Code, der ihn liest, dort läuft.",[10,215,216],{},"Zwei Dinge lohnen sich, solange du dabei bist. Gib deinem Endpunkt ein\nRatenlimit, denn ein Endpunkt, der OpenAI für jeden aufruft, der fragt, ist\ndieselbe Rechnung auf einem langsameren Weg. Und setz ein monatliches\nAusgabenlimit für das OpenAI-Projekt, die eine Kontrolle, die dem schlimmsten\nFall einen Boden einzieht.",[10,218,219],{},"Wenn deine App die Realtime-API von OpenAI für Sprache nutzt, braucht der Browser\ntatsächlich Zugangsdaten, und OpenAI dokumentiert, wie man ihm welche gibt: dein\nServer erzeugt ein kurzlebiges Client-Secret und reicht der Seite dieses. Die\nFahrkarte existiert weiter, sie läuft in Minuten ab, und dein eigener Server hat\nsie ausgestellt.",[36,221,223],{"id":222},"wie-du-kostenlos-jeden-schlüssel-findest-den-deine-app-ausliefert","Wie du kostenlos jeden Schlüssel findest, den deine App ausliefert",[10,225,226,227,229,230,233,234,237,238,241],{},"Fang von Hand an, das kostet fünf Minuten und braucht keine Installation. Sieh\ndir den Quelltext deiner Live-Website an und such darin nach ",[14,228,16],{}," für einen\nOpenAI-Schlüssel, ",[14,231,232],{},"sk-ant-"," für einen von Anthropic, ",[14,235,236],{},"AIza"," für Google und ",[14,239,240],{},"eyJ","\nfür ein Supabase-Token.",[10,243,244],{},"Was dabei durchrutscht, ist das JavaScript, das die Seite danach nachlädt, und\ndas ist bei einer vibe-codeten App fast alles. Unser Scanner öffnet deine App in\neinem echten Browser, wartet, bis die Bundles eintreffen, und liest diese statt\ndes HTML. Er entschlüsselt außerdem jedes Supabase-Token und meldet die darin\ngeschriebene Rolle, sodass ein Schlüssel, der in deine Seite gehört, als korrekt\nmarkiert zurückkommt und nicht in einer Wand aus Rot untergeht.",[10,246,247],{},"Die Schlüsselprüfung ist eine von neun, und die anderen acht sind der Grund,\nwarum eine Note dir mehr sagt als eine Suche:",[118,249],{"alt":250,"caption":251,"src":252},"Die Reeve-Marke über einer Reihe von neun umrissenen Symbolen, eines je Prüfung: ein Schlüssel, ein Datenbankzylinder, ein Dokument, ein Vorhängeschloss, eine Kiste mit Deckel, ein Paar Code-Klammern, ein Globus, eine Zertifikatsrosette und ein Kalender.","Die neun rein lesenden Prüfungen eines Scans, in der Reihenfolge der Liste darunter. Jede einzelne wird von außen gelesen, so wie ein Fremder deine App sieht.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fnine-checks-1600x420.png",[254,255,256,269],"table",{},[257,258,259],"thead",{},[260,261,262,266],"tr",{},[263,264,265],"th",{},"Worauf der Scan schaut",[263,267,268],{},"Die Frage, die er beantwortet",[270,271,272,281,289,300,308,316,324,332,340],"tbody",{},[260,273,274,278],{},[275,276,277],"td",{},"Geheime Schlüssel in deinem Code",[275,279,280],{},"Ist ein kostenpflichtiger API- oder Admin-Schlüssel für jeden lesbar?",[260,282,283,286],{},[275,284,285],{},"Datenbankregeln",[275,287,288],{},"Kann ein Fremder ohne Anmeldung die Zeilen deiner Nutzer lesen?",[260,290,291,294],{},[275,292,293],{},"Private Dateien",[275,295,296,297,299],{},"Sind ",[14,298,72],{},"-Dateien oder Datenbank-Dumps über eine URL abrufbar?",[260,301,302,305],{},[275,303,304],{},"Sicherheits-Header",[275,306,307],{},"Sind die Schutzmechanismen im Browser eingeschaltet?",[260,309,310,313],{},[275,311,312],{},"Storage-Buckets",[275,314,315],{},"Kann jeder die von deinen Nutzern hochgeladenen Dateien auflisten?",[260,317,318,321],{},[275,319,320],{},"Source Maps",[275,322,323],{},"Ist dein originaler Quellcode neben der App veröffentlicht?",[260,325,326,329],{},[275,327,328],{},"Offene APIs und CORS",[275,330,331],{},"Antworten deine Endpunkte jeder Website, die fragt?",[260,333,334,337],{},[275,335,336],{},"Zertifikatsablauf",[275,338,339],{},"Ist HTTPS gültig und läuft es nicht gleich bei deinen Besuchern ab?",[260,341,342,345],{},[275,343,344],{},"Domain-Verlängerung",[275,346,347],{},"Ist der Name verlängert, bevor ihn jemand anderes nehmen kann?",[10,349,350],{},"Du bekommst Note, Punktzahl und die Zählungen in etwa 20 Sekunden auf den\nBildschirm, ohne Konto. Gib eine E-Mail-Adresse an, und die ausführliche Liste\nkommt dazu, samt einer für deinen Builder geschriebenen Lösung, die du direkt\neinfügen kannst.",[10,352,353,354,357,358,362,363,34],{},"Drei Dinge tut er nicht, und das sind die Gründe, warum man ihn auf eine Live-App\nrichten kann: er meldet sich nie an, er schreibt nie etwas, und er behält nie\neinen gefundenen Schlüssel. Ein offenliegendes Geheimnis wird als maskierter\nHinweis der Form ",[14,355,356],{},"sk-proj-…a1b2"," gespeichert, und der echte Wert wird verworfen.\n",[30,359,361],{"href":360},"\u002F#scan","Scanne deine App",", oder lies vorher,\n",[30,364,366],{"href":365},"\u002Fsecurity-scanner","worauf jede der neun Prüfungen schaut",[36,368,370],{"id":369},"was-jetzt-zu-tun-ist","Was jetzt zu tun ist",[372,373,374],"key-takeaways",{},[189,375,376,379,382,385,388],{},[192,377,378],{},"Tausch den Schlüssel zuerst aus, im OpenAI-Dashboard unter API keys. Ihn aus deinem Code zu löschen schließt nichts, denn der alte Wert steht weiterhin in deiner Versionsgeschichte und in jeder zwischengespeicherten Kopie deiner Seite.",[192,380,381],{},"Setz ein monatliches Ausgabenlimit für das Projekt, zu dem der Schlüssel gehört. Es ist die eine Kontrolle, die deckelt, was dieser oder ein späterer Fehler dich kosten kann.",[192,383,384],{},"Verleg den Aufruf hinter einen eigenen Endpunkt und gib diesem Endpunkt ein eigenes Ratenlimit. Ein Browser sollte nie einen Schlüssel halten, der Geld ausgibt.",[192,386,387],{},"Lies deine Nutzungsseite für die Tage, an denen der Schlüssel aktiv war. Ein Austausch stoppt, was als Nächstes passiert, und sagt nichts über das, was schon passiert ist.",[192,389,390,391,393,394,396],{},"Halte ein ",[14,392,87],{},"- oder ",[14,395,94],{},"-Präfix von allem fern, dessen Lektüre durch einen Fremden dich stören würde. Diese Präfixe bedeuten öffentlich, und dein Build-Werkzeug nimmt sie beim Wort.",[10,398,399,400,404,405,409,410,34],{},"Wenn du das lieber in einer Sitzung durchgehst: die\n",[30,401,403],{"href":402},"\u002Fchecklist","Sicherheits-Checkliste in 10 Minuten"," deckt das zusammen mit den\nanderen Dingen ab, die sich in einer frisch gestarteten App schließen lassen. Und\nfür die größere Frage, welche Schlüssel überhaupt in einen Browser gehören, haben\nwir\n",[30,406,408],{"href":407},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","einen Leitfaden, der veröffentlichbare von geheimen unterscheidet","\nund\n",[30,411,413],{"href":412},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","eine Erhebung dazu, was 30.998 Apps tatsächlich ausgeliefert haben",{"title":415,"searchDepth":416,"depth":416,"links":417},"",3,[418,420,421,422,424,425,426,427],{"id":38,"depth":419,"text":39},2,{"id":62,"depth":419,"text":63},{"id":101,"depth":419,"text":102},{"id":125,"depth":419,"text":423},"Was dangerouslyAllowBrowser tatsächlich tut",{"id":156,"depth":419,"text":157},{"id":172,"depth":419,"text":173},{"id":222,"depth":419,"text":223},{"id":369,"depth":419,"text":370},"Sicherheitsgrundlagen","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcover-1200x630.png","Ein schlüsselförmiger Wert in einer Seite App-Code, so lang gezeichnet, dass er rechts über den Rand des Fensters hinausläuft, das ihn hält.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.",false,"md",[435,438,441,444,447],{"q":436,"a":437},"Jemand hat meinen OpenAI-Schlüssel in meiner App gefunden. Was mache ich zuerst?","Tausch ihn aus. Öffne dein OpenAI-Dashboard unter API keys, erzeuge einen neuen Schlüssel, leg den neuen auf deinen Server und lösche den alten. Ihn aus deinem Code zu löschen ist nicht dasselbe, denn der alte Wert steht weiterhin in deiner Versionsgeschichte und in jeder zwischengespeicherten Kopie deiner Seite. Setz danach ein Ausgabenlimit für das Projekt und lies deine Nutzungsseite für die Tage, an denen der Schlüssel aktiv war.",{"q":439,"a":440},"Kann ich einen OpenAI-Schlüssel auf meine Domain beschränken, so wie einen Google-Schlüssel?","Nein. Ein Google-API-Schlüssel nimmt eine HTTP-Referrer-Einschränkung an, die ihn auf deiner Website funktionieren und überall sonst scheitern lässt, und genau deshalb ist ein Google-Schlüssel in deiner Seite meistens unbedenklich. OpenAI bietet nichts Vergleichbares. Es gibt weder eine Domain-Zulassungsliste noch eine Referrer-Prüfung für einen API-Schlüssel, also hast du nur Kontrollen über das Konto dahinter: zu welchem Projekt der Schlüssel gehört, was dieses Projekt ausgeben darf und ob der Schlüssel überhaupt noch existiert.",{"q":442,"a":443},"Die OpenAI-Bibliothek hat eine Option namens dangerouslyAllowBrowser. Macht die den Schlüssel sicher?","Nein, und der Name ist die Warnung. OpenAI liefert die Browser-Unterstützung ausgeschaltet aus, und die eigene README sagt, dass die Option gefährlich ist, weil sie deine geheimen API-Zugangsdaten im clientseitigen Code offenlegt. Sie einzuschalten ändert nichts daran, was der Browser lesen kann; sie hält die Bibliothek nur davon ab, den Start zu verweigern. Die engen Fälle, für die sie gedacht ist, sind interne Werkzeuge mit bekannten Nutzern und kurzlebige Entwicklungsschlüssel, nicht eine öffentliche App.",{"q":445,"a":446},"Wie viel kann jemand mit einem gefundenen Schlüssel ausgeben?","So viel, wie dein Konto zulässt, und deshalb zählt das Ausgabenlimit mehr als die Höhe der Rechnung, die du bisher gesehen hast. Ein gestohlener Schlüssel zieht an denselben Ratenlimits wie deine App, also ist das erste Symptom oft gar nicht die Rechnung: deine eigene App fängt an zu scheitern, während jemand anderes beschäftigt ist. Setz ein monatliches Ausgabenlimit für das Projekt, dann hast du eine Obergrenze für alles davon.",{"q":448,"a":449},"Ich habe den Schlüssel nur für eine schnelle Demo benutzt. Spielt das trotzdem eine Rolle?","Ja. Ein Schlüssel bleibt aktiv, bis ihn jemand widerruft, und er weiß nicht, dass er vorübergehend sein sollte. Automatische Scraper sammeln fortlaufend schlüsselförmige Zeichenketten von öffentlichen Seiten, also arbeitet das Alter der Demo gegen dich statt für dich. Den Schlüssel zu löschen dauert kürzer als die Entscheidung, ob er das Löschen wert war.","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",[452,453,454,455,129,456],"openai api key im frontend","openai api-schlüssel in react verstecken","openai sicher vom frontend aufrufen","openai api-schlüssel sicherheit","openai api-schlüssel geleakt",{},true,"OpenAI-API-Schlüssel im Frontend sichtbar?","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","2026-09-03",{"title":5,"description":431},"blog\u002Fopenai-api-key-exposed-in-frontend",[465,466,467,468],"Ein OpenAI-API-Schlüssel im Frontend ist der Fall, in dem der Alarm recht hat. Keine Einstellung macht so einen Schlüssel im Browser unbedenklich.","Er ist ein Bearer-Token, es genügt also, ihn zu besitzen. Es gibt keine Domain-Einschränkung, die ihn an deine eigene Website bindet, so wie es sie für einen Google-Schlüssel gibt.","Tausch ihn heute im OpenAI-Dashboard aus, verleg den Aufruf hinter einen eigenen Endpunkt und setz ein Ausgabenlimit für das Projekt.","Wir fanden einen in 33 von 30.998 gescannten Apps. Selten, und alle 33 kamen mit Note D oder F heraus.","2026-09-21","IcdCGjNW1bbC3ODg1RtNNWkBPr2oUTjqzxVJRl97sr4",[472,479,485,490,496,502,508,514,520,526,532,538,544,550,556,562,568,574,580,586,592,593,598,604,610,616,622,628,634,640,646,652,658,663,669,675,680,686,692,698,703,709],{"path":473,"title":474,"description":475,"published":476,"category":477,"image":478,"draft":432},"\u002Fblog\u002Fsupabase-backup-auth-users","Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","Backups","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":480,"title":481,"description":482,"published":483,"category":428,"image":484,"draft":432},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":486,"title":487,"description":488,"published":469,"category":428,"image":489,"draft":432},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":491,"title":492,"description":493,"published":494,"category":428,"image":495,"draft":432},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":497,"title":498,"description":499,"published":500,"category":428,"image":501,"draft":432},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":503,"title":504,"description":505,"published":506,"category":428,"image":507,"draft":432},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":509,"title":510,"description":511,"published":512,"category":428,"image":513,"draft":432},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":515,"title":516,"description":517,"published":518,"category":428,"image":519,"draft":432},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":521,"title":522,"description":523,"published":524,"category":428,"image":525,"draft":432},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":527,"title":528,"description":529,"published":530,"category":477,"image":531,"draft":432},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":533,"title":534,"description":535,"published":536,"category":477,"image":537,"draft":432},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":539,"title":540,"description":541,"published":542,"category":477,"image":543,"draft":432},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":545,"title":546,"description":547,"published":548,"category":428,"image":549,"draft":432},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":551,"title":552,"description":553,"published":554,"category":428,"image":555,"draft":432},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":557,"title":558,"description":559,"published":560,"category":428,"image":561,"draft":432},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":563,"title":564,"description":565,"published":566,"category":428,"image":567,"draft":432},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":569,"title":570,"description":571,"published":572,"category":428,"image":573,"draft":432},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Zehn Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":575,"title":576,"description":577,"published":578,"category":428,"image":579,"draft":432},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":581,"title":582,"description":583,"published":584,"category":428,"image":585,"draft":432},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":587,"title":588,"description":589,"published":590,"category":428,"image":591,"draft":432},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":460,"title":5,"description":431,"published":461,"category":428,"image":450,"draft":432},{"path":412,"title":594,"description":595,"published":596,"category":428,"image":597,"draft":432},"API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":599,"title":600,"description":601,"published":602,"category":477,"image":603,"draft":432},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":605,"title":606,"description":607,"published":608,"category":428,"image":609,"draft":432},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":611,"title":612,"description":613,"published":614,"category":477,"image":615,"draft":432},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":617,"title":618,"description":619,"published":620,"category":428,"image":621,"draft":432},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":623,"title":624,"description":625,"published":626,"category":428,"image":627,"draft":432},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":629,"title":630,"description":631,"published":632,"category":428,"image":633,"draft":432},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":635,"title":636,"description":637,"published":638,"category":428,"image":639,"draft":432},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":641,"title":642,"description":643,"published":644,"category":477,"image":645,"draft":432},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":647,"title":648,"description":649,"published":650,"category":477,"image":651,"draft":432},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":428,"image":657,"draft":432},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":111,"title":659,"description":660,"published":661,"category":428,"image":662,"draft":432},"Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":664,"title":665,"description":666,"published":667,"category":477,"image":668,"draft":432},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":670,"title":671,"description":672,"published":673,"category":428,"image":674,"draft":432},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":676,"title":677,"description":678,"published":673,"category":428,"image":679,"draft":432},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":681,"title":682,"description":683,"published":684,"category":428,"image":685,"draft":432},"\u002Fblog\u002Fsupabase-new-api-keys","Supabases neue API-Schlüssel: welcher gehört in deine App?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":687,"title":688,"description":689,"published":690,"category":477,"image":691,"draft":432},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":693,"title":694,"description":695,"published":696,"category":428,"image":697,"draft":432},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":699,"title":700,"description":701,"published":696,"category":477,"image":702,"draft":432},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":704,"title":705,"description":706,"published":707,"category":477,"image":708,"draft":432},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":407,"title":710,"description":711,"published":707,"category":428,"image":712,"draft":432},"Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1790150951364]