[{"data":1,"prerenderedAt":843},["ShallowReactive",2],{"blog-de-vite-and-next-public-env-vars":3,"blog-index-de":602},{"id":4,"title":5,"body":6,"category":554,"cover":555,"coverAlt":556,"description":557,"draft":558,"extension":559,"faq":560,"image":579,"keywords":580,"meta":590,"navigation":591,"ogTitle":592,"path":593,"published":594,"seo":595,"stem":596,"tldr":597,"updated":594,"__hash__":601},"blog_de\u002Fblog\u002Fvite-and-next-public-env-vars.md","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen",{"type":7,"value":8,"toc":540},"minimark",[9,25,40,43,48,54,72,86,93,99,105,121,127,136,140,143,154,157,166,170,173,323,329,338,342,345,365,376,380,383,403,413,418,425,429,432,439,459,467,475,479,522,525,532],[10,11,12,13,17,18,21,22,24],"p",{},"Jemand hat deine Lovable-App geöffnet, F12 gedrückt und im Code einen Wert\ngefunden, von dem du sicher bist, dass du ihn in eine ",[14,15,16],"code",{},".env","-Datei gelegt hast.\nOder du hast den Builder um ein Feature gebeten, er hat eine Zeile geschrieben,\ndie mit ",[14,19,20],{},"VITE_"," beginnt, und irgendetwas, das du seitdem gelesen hast, sagt,\ndass genau dieser Präfix der Weg ist, auf dem Schlüssel durchsickern. Die Datei\nhat ",[14,23,16],{}," im Namen, und jedes Tutorial sagt, dass man sie nie weitergibt.\nVite-Env-Variablen, die für jeden Besucher offengelegt sind, klingen nach einem\nFehler in Vite.",[10,26,27,28,32,33,35,36,39],{},"Hier kommt der Teil, den eine Anleitung nach der anderen falsch erklärt:\n",[29,30,31],"strong",{},"nichts hat versagt, diesen Wert zu verstecken."," ",[14,34,20],{}," und ",[14,37,38],{},"NEXT_PUBLIC_","\nsind eine Anweisung an dein Build-Tool, und die Anweisung lautet, den Wert in\ndie App zu legen, die jeder Besucher herunterlädt. Das Tool hat das Label\ngelesen und getan, was darauf stand.",[10,41,42],{},"Ein Build packt deine App in eine Kiste, und jeder Besucher bekommt eine Kopie\nder Kiste. Der Präfix ist ein Label an einem Wert, das sagt: pack das auch ein.\nDer Rest dieses Beitrags handelt davon, für welche Werte dieses Label richtig\nist, warum die KI es an die falschen hängt, und wie du siehst, was in deiner\neigenen Kiste steckt.",[44,45,47],"h2",{"id":46},"sind-vite-env-variablen-für-besucher-offengelegt","Sind Vite-Env-Variablen für Besucher offengelegt?",[10,49,50,51,53],{},"Die, die mit ",[14,52,20],{}," beginnen, ja, und genau dafür ist der Präfix da.",[10,55,56,57,59,60,63,64,67,68,71],{},"Vite, das Build-Tool hinter den meisten Lovable- und Bolt-Apps, liest deine\n",[14,58,16],{},"-Datei bei jedem Build. Eine Variable namens ",[14,61,62],{},"VITE_SUPABASE_URL"," wird in\ndas Bundle kopiert, die komprimierte JavaScript-Datei, die jeder Besucher\nherunterlädt, wo dein Code sie als ",[14,65,66],{},"import.meta.env.VITE_SUPABASE_URL"," liest.\nEine Variable namens ",[14,69,70],{},"DB_PASSWORD",", ohne Präfix, kommt im Browser leer zurück.\nVites eigene Dokumentation sagt, dass die Werte mit Präfix beim Build in\ndeinen Quellcode gebündelt werden und keine API-Schlüssel enthalten sollten.",[10,73,74,75,77,78,81,82,85],{},"Next.js, mit dem v0 baut, hat dieselbe Regel unter anderem Namen:\n",[14,76,38],{},". Seine Dokumentation beschreibt den Wert als inlined, ein fest\neingetragener String, der beim Build in das Browser-Bundle geschrieben wird.\nExpo benutzt ",[14,79,80],{},"EXPO_PUBLIC_"," und warnt mit denselben Worten. Ältere\nCreate-React-App-Projekte benutzen ",[14,83,84],{},"REACT_APP_",". Jeder Präfix sagt seinem\nBuild-Tool dasselbe: der hier kommt in die Kiste.",[44,87,89,90,92],{"id":88},"warum-sich-eine-env-datei-privat-anfühlt-und-es-nicht-ist","Warum sich eine ",[14,91,16],{},"-Datei privat anfühlt und es nicht ist",[10,94,95,96,98],{},"Weil die Gewohnheit, einen Schlüssel in einer ",[14,97,16],{},"-Datei zu halten, von\nServern stammt, wo sie funktioniert.",[10,100,101,102,104],{},"Auf einem Server liegen die Datei und der Code, der sie liest, auf einer\nMaschine, die du kontrollierst. Ein Besucher bekommt eine Antwort von dieser\nMaschine und sieht die Datei nie. Den Schlüssel aus dem Code herauszuhalten und\nin eine Datei zu legen, die der Server beim Start liest, ist dort gute Praxis,\nund dort wurde jedes Tutorial geschrieben, das sagt: „leg ihn in ",[14,103,16],{},"“.",[10,106,107,108,110,111,114,115,117,118,120],{},"Deine ",[14,109,16],{},"-Datei hat zwei Leser, und die Tutorials handeln von einem davon.\nDer erste ist jeder, der dein Projekt sehen kann: ein Mitstreiter, ein\nöffentliches GitHub-Repository, die Dateiansicht des Builders selbst. Ein\nEintrag in ",[14,112,113],{},".gitignore",", einer Liste von Dateien, die git auslässt, hält ",[14,116,16],{},"\nvon diesem Leser fern. Der zweite Leser ist der Build, der die Datei bei jedem\nVeröffentlichen öffnet und alles herauskopiert, was den Präfix trägt.\n",[14,119,113],{}," sagt ihm nichts.",[122,123],"diagram",{"alt":124,"caption":125,"src":126},"Eine .env-Datei in der Mitte mit drei Werten, zwei davon mit VITE_ markiert. Links davon stoppt eine gestrichelte Wand mit der Beschriftung .gitignore den Weg zu einem Stapel Repository-Dateien. Rechts davon wandern die zwei markierten Werte durch einen Build-Schritt in ein Browserfenster mit einer Person daneben, und der unmarkierte Wert bleibt in der Datei.","Eine Datei, zwei Leser. Die .gitignore-Wand hält einen davon auf. Der Build trägt jeden Wert mit Präfix zum anderen.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Ftwo-readers-one-file-1600x760.png",[10,128,129,130,132,133,135],{},"„Meine ",[14,131,16],{}," steht in ",[14,134,113],{},"“ stimmt also, und es beantwortet eine\nandere Frage. Die Datei ist aus deinem Repository herausgeblieben. Die Werte\nmit Präfix sind trotzdem in die App gewandert, weil das der Weg ist, den der\nPräfix öffnet, und in einem Lovable-, Bolt- oder v0-Projekt läuft der meiste\nCode, den du bearbeitet hast, im Browser, wo es keinen Server gibt, hinter dem\ndie Datei bleiben könnte.",[44,137,139],{"id":138},"warum-die-ki-zum-präfix-gegriffen-hat","Warum die KI zum Präfix gegriffen hat",[10,141,142],{},"Weil man so einen Wert im Browsercode zum Laufen bringt, und weil das Modell\nkeine Ahnung hat, was der Wert kostet.",[10,144,145,146,149,150,153],{},"Du hast um eine Karte gebeten, oder um ein Chat-Feature, das Fragen zu deinem\nProdukt beantwortet. Der Code, den der Builder dafür geschrieben hat, läuft im\nBrowser des Besuchers, und Browsercode, der ",[14,147,148],{},"process.env.OPENAI_API_KEY","\nliest, bekommt gar nichts. Der Weg, den Wert ankommen zu lassen, ist der\nPräfix. Der Builder benennt die Variable in ",[14,151,152],{},"VITE_OPENAI_API_KEY"," um, das\nFeature funktioniert in der Vorschau, und nirgends wird ein Fehler gemeldet,\nweil aus Sicht des Build-Tools nichts schiefgelaufen ist.",[10,155,156],{},"Der Präfix urteilt nicht. Er ist dieselbe Anweisung für einen\nGoogle-Maps-Schlüssel, der öffentlich sein soll, sobald er eingeschränkt ist,\nund für einen geheimen Stripe-Schlüssel, der jedem deiner Kunden Geld\nzurückerstatten kann. Ein Mensch, der wüsste, dass der zweite deine Karte\nbelastet, würde innehalten. Das Modell weiß, dass das Feature nicht lief, bis\ndie Zeile da war, und dann lief es.",[10,158,159,160,162,163,165],{},"Deshalb taucht das bei Apps auf, deren Besitzer alles getan haben, was man\nihnen gesagt hat. Der Wert wurde aus dem Code herausgenommen, er lag in\n",[14,161,16],{},", die Datei stand in ",[14,164,113],{},", und die App liefert ihn trotzdem aus,\nweil der eine Schritt, der ihn veröffentlicht, aussieht wie der Schritt, der\nihn zum Laufen bringt.",[44,167,169],{"id":168},"welche-werte-hinter-den-präfix-gehören","Welche Werte hinter den Präfix gehören",[10,171,172],{},"Eine Adresse und ein veröffentlichbarer Schlüssel. Alles, was Geld ausgibt oder\ndeine Datenbankregeln ignoriert, nicht.",[174,175,176,198],"table",{},[177,178,179],"thead",{},[180,181,182,186,195],"tr",{},[183,184,185],"th",{},"Wert",[183,187,188,189,191,192,194],{},"Hinter ",[14,190,20],{}," oder ",[14,193,38],{},"?",[183,196,197],{},"Warum",[199,200,201,218,237,252,265,279,297,311],"tbody",{},[180,202,203,208,215],{},[204,205,206],"td",{},[14,207,62],{},[204,209,210],{},[211,212,214],"key-verdict",{"type":213},"safe","Gehört hierher",[204,216,217],{},"Eine Adresse. Sie sagt, mit welchem Projekt deine App spricht, und sonst nichts.",[180,219,220,230,234],{},[204,221,222,225,226,229],{},[14,223,224],{},"VITE_SUPABASE_PUBLISHABLE_KEY",", oder ",[14,227,228],{},"VITE_SUPABASE_ANON_KEY"," bei einem älteren Projekt",[204,231,232],{},[211,233,214],{"type":213},[204,235,236],{},"Für den Browser gebaut. Jede Anfrage, die er stellt, wird weiterhin von Row Level Security gefiltert, den Regeln an jeder Tabelle, die Zeile für Zeile entscheiden, wer was lesen darf.",[180,238,239,245,249],{},[204,240,241,242],{},"Ein Stripe-Schlüssel ",[14,243,244],{},"pk_live_",[204,246,247],{},[211,248,214],{"type":213},[204,250,251],{},"Baut Zahlungsformulare. Kann weder abbuchen noch erstatten noch Kunden lesen.",[180,253,254,257,262],{},[204,255,256],{},"Ein Google-Maps-Schlüssel",[204,258,259],{},[211,260,261],{"type":213},"Gehört hierher, sobald eingeschränkt",[204,263,264],{},"Von Natur aus öffentlich. Eine Referrer-Einschränkung in Google Cloud ist das, was einen Fremden davon abhält, dir damit Kosten zu verursachen.",[180,266,267,270,276],{},[204,268,269],{},"Ein OpenAI- oder Anthropic-Schlüssel",[204,271,272],{},[211,273,275],{"type":274},"danger","Nie",[204,277,278],{},"Es gibt keine veröffentlichbare Variante. Wer ihn hält, gibt dein Geld aus.",[180,280,281,290,294],{},[204,282,283,284,191,287],{},"Ein Supabase-Schlüssel ",[14,285,286],{},"service_role",[14,288,289],{},"sb_secret_",[204,291,292],{},[211,293,275],{"type":274},[204,295,296],{},"Umgeht Row Level Security und liest jede Zeile in jeder Tabelle.",[180,298,299,304,308],{},[204,300,241,301],{},[14,302,303],{},"sk_live_",[204,305,306],{},[211,307,275],{"type":274},[204,309,310],{},"Abbuchungen, Erstattungen, Auszahlungen und jeder Kundendatensatz.",[180,312,313,316,320],{},[204,314,315],{},"Ein AWS-Zugangsschlüssel",[204,317,318],{},[211,319,275],{"type":274},[204,321,322],{},"Was immer dieses Konto kann, von überall.",[10,324,325,326,328],{},"Wenn deine App ",[14,327,62],{}," und daneben einen veröffentlichbaren\nSchlüssel hat, ist das das Paar, das Supabase für einen Browser vorgesehen hat,\nund unser Scan markiert es als „gehört hierher“. Die Adresse und der\nveröffentlichbare Schlüssel sind der Grund, warum es den Präfix gibt.",[10,330,331,332,337],{},"Der Test für alles andere ist, ob es dich stören würde, den Wert auf deiner\nStartseite abgedruckt zu sehen. Der Präfix legt ihn einen Klick weiter weg als\ndas, in eine Datei statt auf die Seite, und wer die Datei will, hat sie.\n",[333,334,336],"a",{"href":335},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Die beiden Familien auseinanderzuhalten",",\nam Präfix und bei einem älteren Supabase-Schlüssel an der Rolle darin, ist ein\neigener Artikel.",[44,339,341],{"id":340},"was-30998-apps-hinter-dem-präfix-ausgeliefert-haben","Was 30.998 Apps hinter dem Präfix ausgeliefert haben",[10,343,344],{},"Meistens Google-API-Schlüssel. 52 Apps lieferten einen Schlüssel aus, der Geld\nausgibt oder alles liest.",[10,346,347,348,352,353,357,358,191,361,364],{},"Im August 2026 haben wir\n",[333,349,351],{"href":350},"\u002Fresearch\u002Fvibe-coded-app-security-2026","dieselben neun Checks"," auf 30.998\nlive geschalteten vibe-gecodeten Apps laufen lassen. 1.332 davon, 4 %,\nlieferten etwas Schlüsselförmiges in dem Code aus, den jeder Besucher\nherunterlädt. 1.142 davon waren Google-API-Schlüssel, die meist eine\n",[333,354,356],{"href":355},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Einschränkung in Google Cloud","\nbrauchen und keine Rotation. 204 lieferten einen zufällig aussehenden Wert\nneben einem Namen wie ",[14,359,360],{},"secret",[14,362,363],{},"password"," aus, der ein echter Zugang sein\nkann oder auch nicht.",[10,366,367,368,370,371,375],{},"Die teuren waren selten. 33 Apps lieferten einen OpenAI-Schlüssel aus, 9 einen\nAWS-Zugangsschlüssel, 5 einen Anthropic-Schlüssel, 3 einen geheimen\nStripe-Schlüssel und 3 einen Supabase-",[14,369,286],{},"-Schlüssel: 52 Apps\ninsgesamt, da eine davon zwei trug. Der Wert hinter dem Präfix ist also meist\nein Google-Schlüssel, und die Lösung dafür ist eine Einstellung. Der seltene\nFall ist der, in dem der Schaden liegt, und\n",[333,372,374],{"href":373},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","was ein geleakter OpenAI-Schlüssel kostet","\nist der Beitrag dazu.",[44,377,379],{"id":378},"wie-du-prüfst-was-deine-eigene-app-ausliefert","Wie du prüfst, was deine eigene App ausliefert",[10,381,382],{},"Öffne die live geschaltete App, drücke F12 und durchsuche jede geladene Datei\nnach dem Wert.",[384,385,386,390,397,400],"ol",{},[387,388,389],"li",{},"Öffne deine veröffentlichte App in einem Browser, unter ihrer echten\nAdresse. Die Vorschau des Builders ist ein anderer Build und kann eine\nVersion hinterherhängen.",[387,391,392,393,396],{},"Drücke F12, um die Entwicklerwerkzeuge zu öffnen, und wähle dann den Reiter\n",[29,394,395],{},"Sources",".",[387,398,399],{},"Drücke Strg+Umschalt+F, oder Cmd+Wahl+F auf einem Mac. Das öffnet eine Suche\nüber jede Datei, die die Seite geladen hat.",[387,401,402],{},"Füge die ersten etwa zehn Zeichen des Werts ein, um den du dir Sorgen\nmachst, und füge ihn nirgends sonst ein.",[10,404,405,406,409,410,412],{},"Ein Treffer heißt, dass der Wert in der Kiste liegt, die jeder Besucher\nbekommt. Suche nach dem Wert statt nach dem Namen: Der Build ersetzt\n",[14,407,408],{},"import.meta.env.VITE_OPENAI_API_KEY"," meist durch den Wert selbst, sodass eine\nSuche nach ",[14,411,20],{}," leer ausgehen kann, während jeder Wert dahinter da ist.",[122,414],{"alt":415,"caption":416,"src":417},"Zwei Fenster. Links eine Quelldatei mit einer Zeile import.meta.env.VITE_OPENAI_API_KEY zwischen schlichten Codezeilen. Rechts, nach einem Build-Schritt, dieselbe Datei zu dichtem Rauschen komprimiert, der Variablenname verschwunden und sein Wert als hervorgehobener Balken unter einer Lupe.","Der Build ersetzt den Namen durch den Wert. Wer die live geschaltete App nach VITE_ durchsucht, findet nichts; wer nach dem Wert sucht, findet ihn.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fname-goes-value-stays-1600x640.png",[10,419,420,421,396],{},"Wenn du deine App lieber nicht Wert für Wert durchgehen willst, liest unser\nkostenloser Scan deine live geschaltete Seite von außen, alle neun Checks, in\netwa 20 Sekunden und ohne Konto. Er benennt jeden gefundenen Schlüssel nach\nseiner Art, sagt, welche in einen Browser gehören, und schreibt „Konnte nicht\nprüfen“ für alles, was er nicht beantworten konnte, statt ein Häkchen zu\nsetzen: ",[333,422,424],{"href":423},"\u002Fsecurity-scanner","scanne deine App",[44,426,428],{"id":427},"wo-ein-echtes-geheimnis-stattdessen-hingehört","Wo ein echtes Geheimnis stattdessen hingehört",[10,430,431],{},"Auf eine Maschine, von der deine Besucher nie etwas herunterladen. In einem\nSupabase-Projekt ist das eine Edge Function, ein kleines Stück Servercode, das\nSupabase für dich ausführt; in einer Next.js-App ist es eine Server-Route; in\neiner Replit-App ist es die Serverhälfte.",[10,433,434,435,438],{},"Die Form ist überall dieselbe. Dein Browsercode bittet deine Funktion, die\nArbeit zu erledigen. Die Funktion hält den Schlüssel, ruft OpenAI oder Stripe\nauf und schickt die Antwort zurück. Der Schlüssel bleibt auf der Maschine, und\nder Besucher bekommt ein Ergebnis. Der\n",[333,436,437],{"href":373},"OpenAI-Beitrag"," zeichnet es als ein\nObjekt, das um eine Box nach rechts wandert, und mehr ist die Änderung nicht.",[10,440,441,442,445,446,448,449,191,452,455,456,396],{},"Zwei Dinge sagen dir, dass der Builder getan hat, worum du gebeten hast. Die\nVariable hat ihren Präfix verloren, heißt also ",[14,443,444],{},"OPENAI_API_KEY",", und sie lebt\nin den eigenen Secrets der Funktion, gesetzt im Supabase-Dashboard unter Edge\nFunctions, ohne etwas in der ",[14,447,16],{}," der App. Und die Datei, die sie liest,\nliegt unter ",[14,450,451],{},"supabase\u002Ffunctions\u002F",[14,453,454],{},"app\u002Fapi\u002F",", irgendwo, wo der Build nie\neinpackt, statt unter ",[14,457,458],{},"src\u002F",[10,460,461,462,466],{},"Eine Reihenfolge ist wichtig, und man dreht sie leicht um. Wenn ein geheimer\nSchlüssel schon hinter einem Präfix ausgeliefert wurde, hilft das Verschieben\nnichts gegen die Kopien, die schon heruntergeladen sind. Rotiere ihn zuerst\nbeim Anbieter, dann verschiebe die Arbeit.\n",[333,463,465],{"href":464},"\u002Fblog\u002Frotate-supabase-service-role-key","Ob zuerst rotieren oder zuerst das Leck schließen","\nhängt davon ab, ob die Kopie schon öffentlich ist, und sobald sie in einem\nveröffentlichten Bundle war, ist sie es.",[10,468,469,470,474],{},"Bei einem Replit-Projekt hat dieselbe Trennung einen eigenen Namen, Secrets,\nund\n",[333,471,473],{"href":472},"\u002Fblog\u002Freplit-secrets-explained","was das Secrets-Werkzeug abdeckt und was nicht","\nist ein eigener Beitrag.",[44,476,478],{"id":477},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[480,481,482],"key-takeaways",{},[483,484,485,498,510,513,516,519],"ul",{},[387,486,487,488,490,491,490,493,35,495,497],{},"Durchsuche dein Projekt nach ",[14,489,20],{},", ",[14,492,38],{},[14,494,80],{},[14,496,84],{},". Jeder Treffer ist ein Wert, den dein Build absichtlich veröffentlicht. Entscheide für jeden, ob er öffentlich sein darf.",[387,499,500,501,35,503,505,506,509],{},"Behalte die Adresse und den veröffentlichbaren Schlüssel. ",[14,502,62],{},[14,504,224],{},", oder der ",[14,507,508],{},"anon","-Schlüssel bei einem älteren Projekt, sind das Paar, für das es den Präfix gibt.",[387,511,512],{},"Ein geheimer Schlüssel hinter einem Präfix wird zuerst beim Anbieter rotiert, dann verschoben. Die Zeile zu löschen holt keine Kopie zurück, die schon heruntergeladen wurde.",[387,514,515],{},"Verschiebe die Arbeit, die den Schlüssel brauchte, in eine Edge Function oder eine Server-Route, mit dem Schlüssel in den Secrets dieser Funktion und ohne Präfix im Namen.",[387,517,518],{},"Schränke einen Google-Schlüssel in Google Cloud per Referrer ein. Der braucht eine Einstellung und behält seinen Wert.",[387,520,521],{},"Durchsuche nach dem nächsten Veröffentlichen die live geschaltete App nach jedem Wert, den du verschoben hast.",[10,523,524],{},"Jedes Veröffentlichen packt eine neue Kiste. Das nächste Feature, um das du\nbittest, ist eine weitere Gelegenheit für einen Wert, den Präfix zu bekommen,\nund nichts zwischen dem Builder und dem Internet liest das Bundle auf dem Weg\nnach draußen. Ein Scan vom letzten Monat hat das Bundle vom letzten Monat\ngelesen.",[10,526,527,531],{},[333,528,530],{"href":529},"\u002Fpricing","Reeve Monitor"," liest das Bundle für dich. Er führt alle neun Checks\njede Stunde auf bis zu drei Apps aus, sagt dir Bescheid, wenn sich ein\nErgebnis ändert, prüft die Erreichbarkeit alle 60 Sekunden und schickt einen\nMonatsbericht. Ein Schlüssel, der mit dem Veröffentlichen am Dienstag ins\nBundle gelangt, steht im Re-Scan dieser Stunde, ob du daran gedacht hast\nnachzusehen oder nicht. Er kostet €12 im Monat zum Listenpreis, mit sieben\nTagen kostenlos, bevor er dir etwas berechnet; die Preisseite liegt manchmal\nunter der Zahl hier und nie darüber.",[10,533,534,535,539],{},"Wenn du das lieber als Liste abarbeiten willst, deckt die\n",[333,536,538],{"href":537},"\u002Fchecklist","10-Minuten-Sicherheitscheckliste"," das hier und die anderen Dinge\nab, die man in einer frisch gestarteten App abschalten sollte.",{"title":541,"searchDepth":542,"depth":542,"links":543},"",3,[544,546,548,549,550,551,552,553],{"id":46,"depth":545,"text":47},2,{"id":88,"depth":545,"text":547},"Warum sich eine .env-Datei privat anfühlt und es nicht ist",{"id":138,"depth":545,"text":139},{"id":168,"depth":545,"text":169},{"id":340,"depth":545,"text":341},{"id":378,"depth":545,"text":379},{"id":427,"depth":545,"text":428},{"id":477,"depth":545,"text":478},"Sicherheitsgrundlagen","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcover-1200x630.png","Eine .env-Datei mit drei Werten, zwei mit dem Label VITE_, und dieselben zwei Werte noch einmal in einem Browserfenster daneben.","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.",false,"md",[561,564,567,570,573,576],{"q":562,"a":563},"Sind .env-Dateien geheim?","Vor deinem Repository ja, wenn die Datei in .gitignore steht. Vor deinen Besuchern nein. Der Build liest .env bei jedem Veröffentlichen und kopiert jeden Wert mit dem Präfix VITE_ oder NEXT_PUBLIC_ in das JavaScript, das deine App ausliefert. Die Datei selbst verlässt deinen Rechner nie; die Werte, die du für den Browser markiert hast, schon.",{"q":565,"a":566},"Ist es sicher, VITE_SUPABASE_ANON_KEY offenzulegen?","Er gehört dorthin. Der anon-Schlüssel, bei einem neueren Projekt publishable key genannt, ist dafür gebaut, im Browser zu liegen. Er sagt nur, zu welchem Projekt eine Anfrage gehört, und jede Anfrage, die er stellt, wird von deinen Row-Level-Security-Regeln gefiltert. Das gilt genau so lange, wie diese Regeln an und korrekt sind, und das ist eine eigene Prüfung.",{"q":568,"a":569},"Ist NEXT_PUBLIC_ irgendwie anders als VITE_?","Dieselbe Regel, ein anderes Build-Tool. Next.js schreibt den Wert jeder NEXT_PUBLIC_-Variable beim Build als fest eingetragenen String in das Browser-Bundle, und eine Variable ohne den Präfix kommt im Browsercode leer zurück. Expo macht dasselbe mit EXPO_PUBLIC_, ältere Create-React-App-Projekte mit REACT_APP_. Egal, welches Tool deine App gebaut hat, der Präfix heißt veröffentlichen.",{"q":571,"a":572},"Wie prüfe ich, was in meinem Bundle steckt?","Öffne die live geschaltete App, drücke F12, wähle Sources und drücke Strg+Umschalt+F (Cmd+Wahl+F auf einem Mac), um jede Datei zu durchsuchen, die die Seite geladen hat. Füge die ersten paar Zeichen des Werts ein. Suche nach dem Wert statt nach dem Variablennamen, denn der Build ersetzt den Namen meist durch den Wert, sodass VITE_ fehlen kann, während der Schlüssel da ist. Unser kostenloser Scan macht dieselbe Lesung von außen in etwa 20 Sekunden.",{"q":574,"a":575},"Wo sollte ein geheimer Schlüssel in einer Lovable- oder Bolt-App liegen?","In einer Supabase Edge Function, mit dem Schlüssel in den Secrets dieser Funktion im Supabase-Dashboard und ohne VITE_-Präfix im Namen. Dein Browsercode ruft die Funktion auf, die Funktion ruft den Anbieter mit dem Schlüssel auf, und der Schlüssel erreicht nie einen Besucher. Wenn der Schlüssel schon ausgeliefert wurde, rotiere ihn beim Anbieter, bevor du ihn verschiebst.",{"q":577,"a":578},"Schützt .gitignore meine Schlüssel?","Es hält die .env-Datei aus git heraus, sodass niemand, der dein Repository liest, sie sieht. Auf den Build hat es keine Wirkung; der liest die Datei direkt und veröffentlicht jeden Wert mit Präfix. Eine .env in .gitignore mit VITE_OPENAI_API_KEY darin liefert diesen Schlüssel trotzdem an jeden Besucher aus.","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",[581,582,583,584,585,586,587,588,589],"vite env variablen offengelegt","VITE_ präfix sicherheit","next_public_ umgebungsvariable geheim","sind .env variablen in react sicher","ist vite_ sicher","umgebungsvariablen im frontend",".env datei im browser sichtbar","expo_public env","api key im frontend verstecken",{},true,"Vite-Env-Variablen offengelegt: VITE_ heißt veröffentlichen","\u002Fblog\u002Fvite-and-next-public-env-vars","2026-09-18",{"title":5,"description":557},"blog\u002Fvite-and-next-public-env-vars",[598,599,600],"Vite-Env-Variablen sind in deiner App offengelegt, weil der Präfix genau das verlangt hat. Eine Variable namens VITE_ oder NEXT_PUBLIC_ wird in das JavaScript kopiert, das jeder Besucher herunterlädt, und dass sie in einer .env-Datei liegt, ändert daran nichts.","Der Präfix ist das richtige Label für eine Adresse oder einen veröffentlichbaren Schlüssel und das falsche für alles, was Geld ausgibt oder deine Datenbankregeln ignoriert. Der Build kann die beiden nicht unterscheiden, und die KI, die die Zeile geschrieben hat, auch nicht.","Von 30.998 live gescannten vibe-gecodeten Apps lieferten 1.332 etwas Schlüsselförmiges aus. 1.142 davon waren Google-API-Schlüssel, die meist eine Einschränkung brauchen und keine Rotation. 52 lieferten einen Schlüssel aus, der Geld ausgibt oder alles liest.","pgeW-vDakAzmQKVDfAdGH4mEyQXmOK5LmsXPuPEGb38",[603,610,616,622,628,634,635,641,647,653,659,665,671,677,683,689,694,700,706,712,718,723,729,735,740,746,752,758,764,770,776,782,788,793,799,805,810,816,822,828,833,839],{"path":604,"title":605,"description":606,"published":607,"category":608,"image":609,"draft":558},"\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":611,"title":612,"description":613,"published":614,"category":554,"image":615,"draft":558},"\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":617,"title":618,"description":619,"published":620,"category":554,"image":621,"draft":558},"\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.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":623,"title":624,"description":625,"published":626,"category":554,"image":627,"draft":558},"\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":629,"title":630,"description":631,"published":632,"category":554,"image":633,"draft":558},"\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":593,"title":5,"description":557,"published":594,"category":554,"image":579,"draft":558},{"path":636,"title":637,"description":638,"published":639,"category":554,"image":640,"draft":558},"\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":642,"title":643,"description":644,"published":645,"category":554,"image":646,"draft":558},"\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":648,"title":649,"description":650,"published":651,"category":554,"image":652,"draft":558},"\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":654,"title":655,"description":656,"published":657,"category":608,"image":658,"draft":558},"\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":660,"title":661,"description":662,"published":663,"category":608,"image":664,"draft":558},"\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":666,"title":667,"description":668,"published":669,"category":608,"image":670,"draft":558},"\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":672,"title":673,"description":674,"published":675,"category":554,"image":676,"draft":558},"\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":678,"title":679,"description":680,"published":681,"category":554,"image":682,"draft":558},"\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":684,"title":685,"description":686,"published":687,"category":554,"image":688,"draft":558},"\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":464,"title":690,"description":691,"published":692,"category":554,"image":693,"draft":558},"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":695,"title":696,"description":697,"published":698,"category":554,"image":699,"draft":558},"\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":701,"title":702,"description":703,"published":704,"category":554,"image":705,"draft":558},"\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":707,"title":708,"description":709,"published":710,"category":554,"image":711,"draft":558},"\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":713,"title":714,"description":715,"published":716,"category":554,"image":717,"draft":558},"\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":373,"title":719,"description":720,"published":721,"category":554,"image":722,"draft":558},"Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","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.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":724,"title":725,"description":726,"published":727,"category":554,"image":728,"draft":558},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","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":730,"title":731,"description":732,"published":733,"category":608,"image":734,"draft":558},"\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":472,"title":736,"description":737,"published":738,"category":554,"image":739,"draft":558},"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":741,"title":742,"description":743,"published":744,"category":608,"image":745,"draft":558},"\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":747,"title":748,"description":749,"published":750,"category":554,"image":751,"draft":558},"\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":753,"title":754,"description":755,"published":756,"category":554,"image":757,"draft":558},"\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":759,"title":760,"description":761,"published":762,"category":554,"image":763,"draft":558},"\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":765,"title":766,"description":767,"published":768,"category":554,"image":769,"draft":558},"\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":771,"title":772,"description":773,"published":774,"category":608,"image":775,"draft":558},"\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":777,"title":778,"description":779,"published":780,"category":608,"image":781,"draft":558},"\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":783,"title":784,"description":785,"published":786,"category":554,"image":787,"draft":558},"\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":355,"title":789,"description":790,"published":791,"category":554,"image":792,"draft":558},"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":794,"title":795,"description":796,"published":797,"category":608,"image":798,"draft":558},"\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":800,"title":801,"description":802,"published":803,"category":554,"image":804,"draft":558},"\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":806,"title":807,"description":808,"published":803,"category":554,"image":809,"draft":558},"\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":811,"title":812,"description":813,"published":814,"category":554,"image":815,"draft":558},"\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":817,"title":818,"description":819,"published":820,"category":608,"image":821,"draft":558},"\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":823,"title":824,"description":825,"published":826,"category":554,"image":827,"draft":558},"\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":829,"title":830,"description":831,"published":826,"category":608,"image":832,"draft":558},"\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":834,"title":835,"description":836,"published":837,"category":608,"image":838,"draft":558},"\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":335,"title":840,"description":841,"published":837,"category":554,"image":842,"draft":558},"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]