[{"data":1,"prerenderedAt":925},["ShallowReactive",2],{"blog-de-move-a-secret-to-an-edge-function":3,"blog-index-de":573},{"id":4,"title":5,"body":6,"category":528,"cover":529,"coverAlt":530,"description":531,"draft":532,"extension":533,"faq":534,"image":551,"keywords":552,"meta":561,"navigation":562,"ogTitle":563,"path":564,"published":565,"seo":566,"stem":567,"tldr":568,"updated":565,"__hash__":572},"blog_de\u002Fblog\u002Fmove-a-secret-to-an-edge-function.md","API-Schlüssel verstecken: ab in eine Supabase Edge Function",{"type":7,"value":8,"toc":514},"minimark",[9,13,29,32,37,40,53,56,62,66,69,72,80,84,87,162,171,201,221,225,228,244,247,257,263,268,272,275,282,292,313,316,320,323,347,350,354,357,360,378,381,389,393,396,409,412,420,429,433,436,454,460,473,477,506],[10,11,12],"p",{},"Jeder Beitrag über einen geleakten API-Schlüssel endet an derselben Stelle: ab\ndamit auf einen Server. Dann hört er auf. Zurück bleibst du mit einer App, die du\nin Lovable, Bolt oder Cursor gebaut hast, keinem Server weit und breit und einem\nSatz, der voraussetzt, dass du schon weißt, was als Nächstes zu tun ist.",[10,14,15,16,20,21,28],{},"Das hier lässt ein Beitrag nach dem anderen weg. ",[17,18,19],"strong",{},"Der Schlüssel in einer\nSupabase Edge Function ist aus deiner Seite verschwunden, und das allein hält\nniemanden davon ab, ihn zu benutzen."," Supabase schreibt selbst, warum: Die\nPrüfung, die eine deployte Function von Haus aus durchläuft,\n",[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fauth-headers",[26],"nofollow","akzeptiert auch deinen öffentlichen Schlüssel",",\nund dein öffentlicher Schlüssel steht in deinem Frontend, wo ihn jeder kopieren\nkann. Den Schlüssel zu verstecken ist die einfache Hälfte. Über die andere\nschreibt niemand: zu entscheiden, wem deine neue Function antwortet.",[10,30,31],{},"Stell dir den Schlüssel als Generalschlüssel zu einem Lager vor. Im Moment klebt\ner innen am Schaufenster, wo ihn jeder lesen kann, der stehen bleibt. Eine Edge\nFunction ist ein Hinterzimmer mit Durchreiche: Der Schlüssel kommt dort hinein,\nund Besucher fragen durch die Luke, statt hereinzukommen und sich zu bedienen. Ob\ndas eine Verbesserung ist, hängt davon ab, für wen sich die Luke öffnet.",[33,34,36],"h2",{"id":35},"wohin-gehört-mein-api-schlüssel-wenn-nicht-ins-frontend","Wohin gehört mein API-Schlüssel, wenn nicht ins Frontend?",[10,38,39],{},"Überall dorthin, wo kein Browser ist. Eine Edge Function ist die kleinste\nVariante davon.",[10,41,42,43,47,48,52],{},"Ein Browser kann kein Geheimnis behalten. Alles, was deine Seite zum Laufen\nbraucht, wird von jedem Besucher heruntergeladen, und ein Besucher kann alles\ndavon lesen: den Code, die Bilder, die Werte, die in den Code kompiliert wurden.\nDas ist kein Fehler deines Baukastens. Es ist das, was eine Webseite ist.\n",[22,44,46],{"href":45},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind","\nist die lange Fassung; die kurze lautet, dass ein ",[49,50,51],"code",{},"sk_","-Schlüssel, ein\nOpenAI-Schlüssel oder ein geheimer Supabase-Schlüssel es im Browser nie\nüberlebt hätte.",[10,54,55],{},"Eine Supabase Edge Function ist ein kleines Stück Code, das auf Supabase-Maschinen\nläuft. Sie kann Secrets lesen, die du in deinem Projekt gesetzt hast, sie\nantwortet unter einer eigenen Webadresse, und deine App ruft sie beim Namen auf.\nDu schreibst eine Datei, Supabase führt sie aus, und es gibt keinen Server, den\ndu mieten, patchen oder wachhalten müsstest.",[57,58],"diagram",{"alt":59,"caption":60,"src":61},"Zwei Anordnungen. Oben steckt der Schlüssel im Bundle, das jeder Besucher herunterlädt, und der Browser ruft den Anbieter direkt auf. Unten trägt das Bundle keinen Schlüssel, der Browser ruft die Edge Function auf, und die Function hält den Schlüssel und ruft den Anbieter.","Oben: Der Schlüssel liegt in der Datei, die jeder Besucher herunterlädt, also hat ihn jeder Besucher. Unten: Der Browser fragt die Function, und der Schlüssel verlässt Supabase nie.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fwhere-the-key-lives-1600x800.png",[33,63,65],{"id":64},"tausche-den-veröffentlichten-schlüssel-aus-bevor-du-irgendetwas-verschiebst","Tausche den veröffentlichten Schlüssel aus, bevor du irgendetwas verschiebst",[10,67,68],{},"Der Schlüssel, der heute in deinem Frontend steht, ist bereits öffentlich, und\ner bleibt es, nachdem du ihn aus dem Code genommen hast.",[10,70,71],{},"Jeder Besucher, der deine Seite geladen hat, hat ihn heruntergeladen. Jeder\nCrawler auch, und es laufen automatische durch das ganze Web, die genau nach\nsolchen Zeichenketten suchen. Dein altes Bundle steckt außerdem noch in deiner\nVersionsgeschichte und in jedem Cache, der eine Kopie deiner Seite hat. Eine\nZeile aus einer Datei zu löschen, die dir gehört, ändert nichts an einem Wert,\nder längst ausgehändigt wurde.",[10,73,74,75,79],{},"Die Reihenfolge ist also: beim Anbieter einen neuen Schlüssel erzeugen, ihn einen\nMoment behalten und den alten widerrufen, sobald die Function unten läuft. Lies\ndanach Abrechnung und Nutzungsprotokolle für den ganzen Zeitraum, in dem der\nalte Schlüssel draußen war. Ein Tausch stoppt, was als Nächstes passiert; auf das\nbereits Geschehene hat er keinen Einfluss. War es ein geheimer\nSupabase-Schlüssel, hat ",[22,76,78],{"href":77},"\u002Fblog\u002Frotate-supabase-service-role-key","die richtige\nReihenfolge"," einen Haken, den du vorher\nkennen solltest.",[33,81,83],{"id":82},"die-vier-schritte","Die vier Schritte",[10,85,86],{},"Secret ablegen, Function schreiben, deployen, dann deine App umstellen, damit sie\ndie Function statt des Anbieters aufruft.",[88,89,90,106],"table",{},[91,92,93],"thead",{},[94,95,96,100,103],"tr",{},[97,98,99],"th",{},"Schritt",[97,101,102],{},"Auf der Kommandozeile",[97,104,105],{},"Im Dashboard",[107,108,109,123,136,149],"tbody",{},[94,110,111,115,120],{},[112,113,114],"td",{},"1. Secret ablegen",[112,116,117],{},[49,118,119],{},"supabase secrets set MY_API_KEY=…",[112,121,122],{},"Edge Functions → Secrets, dann Key und Value",[94,124,125,128,133],{},[112,126,127],{},"2. Function schreiben",[112,129,130],{},[49,131,132],{},"supabase functions new forward-request",[112,134,135],{},"Edge Functions → Deploy a new function → Via Editor",[94,137,138,141,146],{},[112,139,140],{},"3. Deployen",[112,142,143],{},[49,144,145],{},"supabase functions deploy",[112,147,148],{},"Der Deploy-Knopf unter dem Editor",[94,150,151,154,159],{},[112,152,153],{},"4. Aus der App aufrufen",[112,155,156],{},[49,157,158],{},"supabase.functions.invoke('…')",[112,160,161],{},"Dasselbe, im Code deiner App",[10,163,164,165,170],{},"In der Function kommt das Secret als Umgebungsvariable an, also als benannter\nWert, den der Code lesen kann und niemand von außen. Die Supabase-Doku zu\n",[22,166,169],{"href":167,"rel":168},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fsecrets",[26],"Edge Function Secrets"," hat\ndie vollständige Referenz, und drei Details darin sparen eine verwirrende Stunde:",[172,173,174,185,191],"ul",{},[175,176,177,184],"li",{},[17,178,179,180,183],{},"Ein Secret-Name darf nicht mit ",[49,181,182],{},"SUPABASE_"," beginnen."," Dieses Präfix ist für\ndie Werte reserviert, die Supabase für dich setzt, und Dashboard wie API\nweisen es ab.",[175,186,187,190],{},[17,188,189],{},"Ein neues Secret ist sofort lesbar."," Du musst die Function danach nicht neu\ndeployen.",[175,192,193,196,197,200],{},[17,194,195],{},"Lokal und Produktion sind getrennt."," Der lokale Stack liest\n",[49,198,199],{},"supabase\u002Ffunctions\u002F.env",", was ein anderer Ort ist als die Secrets deines\nlaufenden Projekts. Setze den Wert also an beiden Stellen, sonst läuft die\nFunction auf deinem Rechner und scheitert nach dem Deploy.",[10,202,203,204,207,208,211,212,215,216,220],{},"Lösche danach die alte Variable aus deinem Frontend. Hieß sie ",[49,205,206],{},"VITE_",",\n",[49,209,210],{},"NEXT_PUBLIC_"," oder ",[49,213,214],{},"EXPO_PUBLIC_",", war dieses Präfix die Anweisung, den Wert in\ndas Bundle zu kompilieren, und ",[22,217,219],{"href":218},"\u002Fblog\u002Fvite-and-next-public-env-vars","das Präfix ist die ganze\nGeschichte"," dahinter.",[33,222,224],{"id":223},"heißt-eine-token-pflicht-dass-nur-meine-nutzer-aufrufen-können","Heißt eine Token-Pflicht, dass nur meine Nutzer aufrufen können?",[10,226,227],{},"Nein, und das ist die eine Stelle in diesem Beitrag, die zweimal zu lesen lohnt.",[10,229,230,231,234,235,238,239,243],{},"Supabase schaltet von Haus aus eine Prüfung namens ",[49,232,233],{},"verify_jwt"," ein. Sie sieht\nsich den ",[49,236,237],{},"Authorization","-Header an, bevor dein Code läuft, und weist die Anfrage\nab, wenn dort nichts Gültiges steht. Das klingt nach einer Tür, die nur deine\nNutzer öffnen. Das ist sie nicht, denn Supabase dokumentiert ebenso, dass\ndieselbe Prüfung\n",[22,240,242],{"href":24,"rel":241},[26],"einen öffentlichen oder geheimen Schlüssel akzeptiert","\nund zwar auf beiden Headern, aus Kompatibilität mit älteren Projekten, und sagt\nklar dazu, dass die Prüfung allein einen Aufrufer nicht authentifiziert, der nur\neinen API-Schlüssel schickt.",[10,245,246],{},"Dein öffentlicher Schlüssel steht in deinem Frontend. Das ist richtig so und\ngenau dafür gedacht. Es heißt aber auch: Wer deine Seite öffnet, den Schlüssel\nliest und ihn an deine neue Function schickt, kommt an der Plattformprüfung\nvorbei und in deinen Code hinein.",[248,249,251],"callout",{"type":250},"warn",[10,252,253,256],{},[17,254,255],{},"So wird aus einem verschobenen Schlüssel ein offener Proxy."," Der Schlüssel\nsteht nicht mehr in deiner Seite, ein Scanner, der nach schlüsselförmigen\nZeichenketten sucht, findet also nichts, und die Rechnung von OpenAI oder Stripe\nwächst weiter. Geändert hat sich, dass die Anfragen jetzt über dich laufen.\nVorher hatte ein Fremder deinen Schlüssel; jetzt hat ein Fremder eine Webadresse\nvon dir, die deinen Schlüssel für ihn benutzt, beliebig oft.",[10,258,259,260,262],{},"Im Lager ist ",[49,261,233],{}," ein Pförtner, der prüft, ob du einen Besucherausweis\ndabeihast. Den hat jeder Besucher, weil du sie an der Tür ausgibst. Die Person an\nder Durchreiche hat eine andere Aufgabe, und die fragt, welcher Besucher du bist.",[57,264],{"alt":265,"caption":266,"src":267},"Zwei Aufrufer erreichen dieselbe Edge Function. Ein Fremder, der nur den öffentlichen Schlüssel schickt, kommt durch die Plattformprüfung verify_jwt und wird dann von der Prüfung in der Function abgewiesen. Ein angemeldeter Nutzer mit Sitzungstoken kommt durch beide und erreicht die Anbieter-API.","Beide Aufrufer kommen durch die Plattformprüfung. Nur der zweite kommt durch eine Prüfung, wer da ruft, und genau die musst du selbst hinzufügen.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Ftwo-checks-1600x860.png",[33,269,271],{"id":270},"die-function-abriegeln-damit-kein-offener-proxy-daraus-wird","Die Function abriegeln, damit kein offener Proxy daraus wird",[10,273,274],{},"Entscheide, welche Aufrufer deine Function akzeptiert, und schreibe diese\nEntscheidung in die Function.",[10,276,277,278,281],{},"Supabase liefert dafür einen Wrapper mit, es ist also eine Zeile und kein\nProjekt. Setze ",[49,279,280],{},"auth: 'user'",", und die Function nimmt das Token eines\nangemeldeten Nutzers an und gibt deinem Code einen Datenbank-Client, der bereits\nauf dessen Row-Level-Security-Regeln eingegrenzt ist:",[283,284,290],"pre",{"className":285,"code":287,"language":288,"meta":289},[286],"language-ts","import { withSupabase } from 'npm:@supabase\u002Fserver@1'\n\nexport default {\n  fetch: withSupabase({ auth: 'user' }, async (_req, ctx) => {\n    \u002F\u002F ctx.userClaims ist, wer da ruft. Weise hier ab, was du nicht willst,\n    \u002F\u002F und rufe dann den Anbieter mit dem Secret aus der Umgebung auf.\n    return Response.json({ ok: true })\n  }),\n}\n","ts","",[49,291,287],{"__ignoreMap":289},[10,293,294,295,300,301,304,305,308,309,312],{},"Die Seite ",[22,296,299],{"href":297,"rel":298},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fauth",[26],"Securing Edge\nFunctions"," listet die anderen\nModi, und zwei davon sind für gewöhnliche Apps wichtig. Eine Function, die von\neiner anderen Maschine statt von einem Browser aufgerufen wird, nimmt\n",[49,302,303],{},"auth: 'secret'",", mit dem geheimen Schlüssel im ",[49,306,307],{},"apikey","-Header. Eine Function,\ndie Webhooks von Stripe oder GitHub empfängt, kann keines von beidem nehmen, weil\ndiese Anbieter kein Token von dir haben; sie setzt ",[49,310,311],{},"verify_jwt = false"," und prüft\nstattdessen die Signatur des Anbieters im Handler.",[10,314,315],{},"Was auch immer du wählst, entscheide bewusst, was passiert, wenn ein Aufrufer\nauftaucht, mit dem du nicht gerechnet hast. Supabase nennt als Beispiel für eine\nFunction, die jeden annehmen darf, einen Health-Check, und ein Health-Check\nkostet nichts, wenn ein Fremder ihn aufruft. Eine Function, die einen bezahlten\nAPI-Aufruf weiterreicht, stellt dir jeden einzelnen in Rechnung.",[33,317,319],{"id":318},"darf-ich-service_role-in-einer-edge-function-benutzen","Darf ich service_role in einer Edge Function benutzen?",[10,321,322],{},"Ja. Eine Function ist der eine Ort, an den ein geheimer Supabase-Schlüssel\ngehört.",[10,324,325,326,329,330,333,334,337,338,341,342,346],{},"Einfügen musst du ihn auch nicht. Supabase legt die Projektschlüssel in die\nUmgebung der Function, der Code liest sie also von dort und nicht aus einem\nSecret, das du gesetzt hast. Neuere Projekte bekommen ",[49,327,328],{},"SUPABASE_SECRET_KEYS"," und\n",[49,331,332],{},"SUPABASE_PUBLISHABLE_KEYS",", jeweils ein kleines Verzeichnis benannter Schlüssel;\nältere Projekte bekommen ",[49,335,336],{},"SUPABASE_SERVICE_ROLE_KEY"," und ",[49,339,340],{},"SUPABASE_ANON_KEY","\nunter ihren ursprünglichen Namen. ",[22,343,345],{"href":344},"\u002Fblog\u002Fsupabase-new-api-keys","Was sich mit den neuen Supabase-Schlüsseln\ngeändert hat"," sagt dir, welches Paar du hast.",[10,348,349],{},"Nimm den geheimen Schlüssel für Arbeit, die wirklich jede Zeile sehen muss, etwa\neinen Prüfeintrag, den der Nutzer nicht bearbeiten darf. Für alles, was ein\nNutzer über sich selbst liest, nimm sein eigenes Token und lass deine\nRow-Level-Security-Regeln filtern, wofür sie da sind.",[33,351,353],{"id":352},"im-browser-nachsehen-der-einzige-echte-beweis","Im Browser nachsehen, der einzige echte Beweis",[10,355,356],{},"Lade deine laufende Seite, öffne den Netzwerk-Tab und sieh dir an, was dein\nBrowser tatsächlich sendet.",[10,358,359],{},"Zwei Dinge zum Prüfen:",[172,361,362,372],{},[175,363,364,367,368,371],{},[17,365,366],{},"Keine Anfrage trägt den Schlüssel."," Klick dich durch den Teil deiner App,\nder früher den Anbieter aufgerufen hat. Die ausgehende Anfrage sollte an\n",[49,369,370],{},"…supabase.co\u002Ffunctions\u002Fv1\u002Fdeine-function"," gehen, und das einzige Merkmal\ndarin sollte dein öffentlicher Schlüssel oder das Token deines Nutzers sein.",[175,373,374,377],{},[17,375,376],{},"Der Schlüssel steht nicht im heruntergeladenen Code."," Nutze die Suche\ndeines Browsers über alle geladenen Dateien und füge das erste Dutzend Zeichen\ndes alten Schlüssels ein. Kein Treffer ist die Antwort, die du willst.",[10,379,380],{},"Erst ein neuer Build und ein neues Deploy nehmen einen Wert aus dem Bundle. Ein\nSchlüssel, der in der Suche noch auftaucht, heißt deshalb meistens, dass das\nFrontend raus war, bevor die Variable heraus war.",[10,382,383,384,388],{},"Unser kostenloser Scan macht die zweite Prüfung von außen und nennt, was er in\ndeinem laufenden Bundle lesen kann, auch welchen Supabase-Schlüssel du\nausgeliefert hast. Er dauert rund 20 Sekunden und braucht kein Konto:\n",[22,385,387],{"href":386},"\u002Fsecurity-scanner","App scannen",".",[33,390,392],{"id":391},"so-geht-es-aus-lovable-bolt-oder-replit-heraus","So geht es aus Lovable, Bolt oder Replit heraus",[10,394,395],{},"Nimm das Supabase-Dashboard. Darin kommt kein Terminal vor.",[10,397,398,399,402,403,408],{},"Öffne dein Projekt, wähle in der Seitenleiste Edge Functions und dann ",[17,400,401],{},"Deploy a\nnew function → Via Editor",". Supabase' ",[22,404,407],{"href":405,"rel":406},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fquickstart-dashboard",[26],"Dashboard-Schnelleinstieg","\nführt mit Screenshots hindurch, und unter den angebotenen Vorlagen ist eine für\ndas Weiterreichen an einen KI-Anbieter, also genau die Form dieser Aufgabe. Das\nDeployen dauert zwischen zehn und dreißig Sekunden, danach läuft die Function\nunter einer eigenen Adresse. Dein Secret kommt im selben Bereich auf die Seite\nEdge Function Secrets.",[10,410,411],{},"Ein Hinweis, bevor du dich darauf verlässt: Supabase schreibt, dass der\nDashboard-Editor keine Versionsverwaltung, keine Versionen und kein Zurückrollen\nkennt, und empfiehlt ihn für schnelle Arbeit statt für Code, der bleiben soll.\nEin Druck auf Deploy überschreibt, was da war. Wenn die Function am Ende etwas\ntut, das dir wichtig ist, lade sie auf dieser Seite herunter und bewahre die\nDatei auf.",[10,413,414,415,419],{},"Für Replit gibt es eine eigene Fassung dieser Frage, weil Replit einen eigenen\nSecrets-Speicher hat und deine App dort ihren eigenen Server betreibt. ",[22,416,418],{"href":417},"\u002Fblog\u002Freplit-secrets-explained","Was\nReplit Secrets wirklich tun"," ist diese Fassung.",[248,421,423],{"type":422},"note",[10,424,425,428],{},[17,426,427],{},"Kommt der Aufruf aus einem Browser, braucht die Function CORS-Header."," Ein\nBrowser lässt deine Seite eine Antwort von einer anderen Adresse nur lesen, wenn\ndiese Adresse es erlaubt. Die Vorlagen im Supabase-Dashboard bringen die Header\nmit; eine selbst geschriebene Function nicht, und das Symptom ist eine Anfrage,\ndie in den Logs der Function gut aussieht und in deiner App scheitert.",[33,430,432],{"id":431},"wann-eine-edge-function-die-falsche-antwort-ist","Wann eine Edge Function die falsche Antwort ist",[10,434,435],{},"Zwei Fälle, und in beiden kostet der Umzug Arbeit und bringt nichts.",[10,437,438,441,442,445,446,449,450,453],{},[17,439,440],{},"Der Schlüssel war öffentlich gedacht."," Ein Stripe-Schlüssel mit ",[49,443,444],{},"pk_live_",",\nein öffentlicher Supabase-Schlüssel oder ein ",[49,447,448],{},"anon","-Schlüssel, ein öffentliches\nMapbox-Token: Die gehören in einen Browser, und der Schutz sitzt woanders. Einen\ndavon hinter eine Function zu legen fügt einen Umweg hinzu und nimmt kein Risiko\nweg. ",[22,451,452],{"href":45},"Welche Schlüssel das\nsind"," ist die Liste.",[10,455,456,459],{},[17,457,458],{},"Der Schlüssel lässt sich auf deine eigene Seite beschränken."," Googles\nBrowser-Schlüssel sind das übliche Beispiel: In der Google-Konsole kannst du\neinen auf deine Domains begrenzen, und genau das ist die Lösung, die Google für\ndiesen Fall vorsieht. Der Schlüssel bleibt lesbar und nützt niemandem mehr, der\nihn kopiert.",[10,461,462,463,467,468,472],{},"Alles andere gehört auf einen Server. Von einem OpenAI- oder Anthropic-Schlüssel\ngibt es keine öffentliche Variante, weshalb ",[22,464,466],{"href":465},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","ein KI-Schlüssel in deinem\nFrontend"," durch keine Einstellung zu\nretten ist, und kein Minifizieren versteckt einen ",[22,469,471],{"href":470},"\u002Fblog\u002Fstripe-secret-key-in-frontend","geheimen\nStripe-Schlüssel"," vor jemandem, der deine\nSeite liest.",[33,474,476],{"id":475},"was-du-jetzt-tun-kannst","Was du jetzt tun kannst",[478,479,480],"key-takeaways",{},[172,481,482,485,491,494,500,503],{},[175,483,484],{},"Tausche zuerst den Schlüssel. Erzeuge beim Anbieter einen neuen, lege ihn als Secret der Function ab und widerrufe den alten, sobald die Function läuft.",[175,486,487,488,490],{},"Lege das Secret in deinem Supabase-Projekt ab, nicht im Repository und nicht in einer ",[49,489,206],{},"-Variablen. Setze es für lokale Entwicklung und für Produktion getrennt.",[175,492,493],{},"Deploye eine Function, die das Secret benutzt, und stelle deine App so um, dass sie die Function beim Namen aufruft statt den Anbieter.",[175,495,496,497,499],{},"Füge eine Prüfung hinzu, wer da ruft. ",[49,498,233],{}," allein akzeptiert den öffentlichen Schlüssel aus deinem eigenen Frontend und hält damit keinen Fremden ab.",[175,501,502],{},"Lösche die alte Variable, baue neu, und prüfe im Netzwerk-Tab deines Browsers, dass nichts Ausgehendes den Schlüssel trägt.",[175,504,505],{},"Lies Abrechnung und Nutzung für den ganzen Zeitraum, in dem der alte Schlüssel öffentlich war. Ein Tausch stoppt die nächste Buchung und nicht die letzte.",[10,507,508,509,513],{},"Wenn du lieber deine ganze App durchgehst statt eines einzelnen Schlüssels: Die\n",[22,510,512],{"href":511},"\u002Fchecklist","Sicherheits-Checkliste in 10 Minuten"," deckt das hier zusammen mit\nden anderen Dingen ab, die in einer frisch gestarteten App zu schließen sind.",{"title":289,"searchDepth":515,"depth":515,"links":516},3,[517,519,520,521,522,523,524,525,526,527],{"id":35,"depth":518,"text":36},2,{"id":64,"depth":518,"text":65},{"id":82,"depth":518,"text":83},{"id":223,"depth":518,"text":224},{"id":270,"depth":518,"text":271},{"id":318,"depth":518,"text":319},{"id":352,"depth":518,"text":353},{"id":391,"depth":518,"text":392},{"id":431,"depth":518,"text":432},{"id":475,"depth":518,"text":476},"Sicherheitsgrundlagen","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcover-1200x630.png","Eine Seite mit einem Loch in Schlüsselform, dahinter eine versiegelte Kiste mit Schloss und dem Schlüssel hinter einem Fenster.","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.",false,"md",[535,537,540,543,546,548],{"q":36,"a":536},"Überall dorthin, wo kein Browser ist. Eine Supabase Edge Function ist die kleinste Möglichkeit: Du legst den Schlüssel als Secret in deinem Projekt ab, schreibst eine kleine Datei, die ihn benutzt, und deine App ruft diese Function beim Namen auf, statt den Anbieter direkt anzusprechen. Genauso funktionieren eine Serverless-Route bei deinem Hoster oder ein eigener Server. Gemeinsam ist ihnen, dass der Schlüssel dort gelesen wird, wo dein Besucher ihn nicht sieht.",{"q":538,"a":539},"Was ist eine Supabase Edge Function?","Ein kleines Stück Code, das auf Supabase-Maschinen läuft statt im Browser deines Besuchers. Es antwortet unter einer eigenen Webadresse, es kann Secrets lesen, die du in deinem Projekt gesetzt hast, und deine App ruft es mit supabase.functions.invoke auf. Du schreibst eine Datei, Supabase führt sie aus, und es gibt keinen Server, den du mieten oder pflegen müsstest.",{"q":541,"a":542},"Muss ich meinen Schlüssel nach dem Umzug austauschen?","Ja, und zwar zuerst. Der Schlüssel aus deinem Frontend wurde von jedem Besucher und von jedem Crawler heruntergeladen, der deine Seite gelesen hat, und ihn aus dem Code zu nehmen ändert an diesen Kopien nichts. Erzeuge beim Anbieter einen neuen Schlüssel, lege ihn als Secret deiner Edge Function ab und widerrufe den alten. Sieh dir danach Abrechnung und Nutzung für den ganzen Zeitraum an, in dem der alte Schlüssel gültig war.",{"q":544,"a":545},"Kann jeder meine Edge Function aufrufen?","Von Haus aus weist eine Function eine Anfrage ohne jedes Token ab, aber diese Prüfung ist schwächer, als sie klingt. Supabase dokumentiert, dass die Plattformprüfung auch deinen öffentlichen oder geheimen Schlüssel akzeptiert, und dein öffentlicher Schlüssel steht in deinem Frontend, wo ihn jeder lesen kann. Die Prüfung stoppt also eine leere Anfrage und keine entschlossene. Wenn nur deine angemeldeten Nutzer durchkommen sollen, prüfe den Aufrufer in der Function selbst.",{"q":319,"a":547},"Ja. Eine Edge Function ist der eine Ort, an den ein geheimer Supabase-Schlüssel gehört, und Supabase legt die Projektschlüssel für dich in die Umgebung der Function, sodass du nie einen einfügen musst. Nimm ihn für Arbeit, die jede Zeile sehen muss, und nimm das Token des Aufrufers für alles, was sich an deine Row-Level-Security-Regeln halten soll.",{"q":549,"a":550},"Geht das auch ohne Terminal?","Ja. Das Supabase-Dashboard hat einen Bereich Edge Functions, in dem du eine Function im Browser schreibst, auf Deploy drückst und dein Secret auf der Seite Edge Function Secrets setzt. Supabase weist darauf hin, dass der Dashboard-Editor keine Versionsgeschichte führt, und empfiehlt ihn deshalb für schnelle Arbeit und die Kommandozeile für alles, was bleiben soll.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",[553,554,555,556,557,558,559,560],"api schlüssel verstecken supabase edge function","supabase edge function secrets","supabase secrets set","api schlüssel auf den server verschieben","openai aus edge function aufrufen","api schlüssel aus dem frontend halten","supabase edge function umgebungsvariablen","wohin mit einem geheimen schlüssel",{},true,"API-Schlüssel in einer Supabase Edge Function verstecken","\u002Fblog\u002Fmove-a-secret-to-an-edge-function","2026-10-05",{"title":5,"description":531},"blog\u002Fmove-a-secret-to-an-edge-function",[569,570,571],"Nichts im Browser kann ein Geheimnis behalten. Einen API-Schlüssel verstecken heißt also, ihn dorthin zu verschieben, wo das geht. Eine Supabase Edge Function ist der kleinste Server, den du bekommst.","Der Umzug sind vier Schritte. Tausche den bereits veröffentlichten Schlüssel vorher aus, denn die Kopie in deinem alten Bundle bleibt lesbar, auch nachdem du ihn herausgenommen hast.","Eine deployte Function verlangt von Haus aus ein Token, und der öffentliche Schlüssel aus deinem eigenen Frontend erfüllt diese Forderung. Zu prüfen, wer da ruft, ist ein eigener Schritt, und dieser hält Fremde von deinem Kontingent fern.","LTDlakiJ9VaGkMQNwrIt12F1PJCATtpdm_zu4-EVryA",[574,580,586,592,598,604,610,611,617,623,629,635,641,647,654,660,666,671,677,683,689,695,701,707,712,717,723,729,735,741,747,753,759,765,771,776,782,788,794,800,805,811,817,822,828,834,840,846,852,858,864,870,876,882,888,893,898,904,910,915,921],{"path":575,"title":576,"description":577,"published":578,"category":528,"image":579,"draft":532},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":581,"title":582,"description":583,"published":584,"category":528,"image":585,"draft":532},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":587,"title":588,"description":589,"published":590,"category":528,"image":591,"draft":532},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":593,"title":594,"description":595,"published":596,"category":528,"image":597,"draft":532},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":599,"title":600,"description":601,"published":602,"category":528,"image":603,"draft":532},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":605,"title":606,"description":607,"published":608,"category":528,"image":609,"draft":532},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":564,"title":5,"description":531,"published":565,"category":528,"image":551,"draft":532},{"path":612,"title":613,"description":614,"published":615,"category":528,"image":616,"draft":532},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":618,"title":619,"description":620,"published":621,"category":528,"image":622,"draft":532},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":624,"title":625,"description":626,"published":627,"category":528,"image":628,"draft":532},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":630,"title":631,"description":632,"published":633,"category":528,"image":634,"draft":532},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":636,"title":637,"description":638,"published":639,"category":528,"image":640,"draft":532},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":642,"title":643,"description":644,"published":645,"category":528,"image":646,"draft":532},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":648,"title":649,"description":650,"published":651,"category":652,"image":653,"draft":532},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":655,"title":656,"description":657,"published":658,"category":652,"image":659,"draft":532},"\u002Fblog\u002Fsupabase-backup-github-action","Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":661,"title":662,"description":663,"published":664,"category":652,"image":665,"draft":532},"\u002Fblog\u002Fdownload-your-supabase-backup","Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":667,"title":668,"description":669,"published":664,"category":528,"image":670,"draft":532},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":672,"title":673,"description":674,"published":675,"category":528,"image":676,"draft":532},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":678,"title":679,"description":680,"published":681,"category":528,"image":682,"draft":532},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":684,"title":685,"description":686,"published":687,"category":652,"image":688,"draft":532},"\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","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":690,"title":691,"description":692,"published":693,"category":528,"image":694,"draft":532},"\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":696,"title":697,"description":698,"published":699,"category":528,"image":700,"draft":532},"\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":702,"title":703,"description":704,"published":705,"category":528,"image":706,"draft":532},"\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":470,"title":708,"description":709,"published":710,"category":528,"image":711,"draft":532},"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":218,"title":713,"description":714,"published":715,"category":528,"image":716,"draft":532},"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":718,"title":719,"description":720,"published":721,"category":528,"image":722,"draft":532},"\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":724,"title":725,"description":726,"published":727,"category":528,"image":728,"draft":532},"\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":730,"title":731,"description":732,"published":733,"category":528,"image":734,"draft":532},"\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":736,"title":737,"description":738,"published":739,"category":652,"image":740,"draft":532},"\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":742,"title":743,"description":744,"published":745,"category":652,"image":746,"draft":532},"\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":748,"title":749,"description":750,"published":751,"category":652,"image":752,"draft":532},"\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":754,"title":755,"description":756,"published":757,"category":528,"image":758,"draft":532},"\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":760,"title":761,"description":762,"published":763,"category":528,"image":764,"draft":532},"\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":766,"title":767,"description":768,"published":769,"category":528,"image":770,"draft":532},"\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":77,"title":772,"description":773,"published":774,"category":528,"image":775,"draft":532},"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":777,"title":778,"description":779,"published":780,"category":528,"image":781,"draft":532},"\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":783,"title":784,"description":785,"published":786,"category":528,"image":787,"draft":532},"\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":789,"title":790,"description":791,"published":792,"category":528,"image":793,"draft":532},"\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":795,"title":796,"description":797,"published":798,"category":528,"image":799,"draft":532},"\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":465,"title":801,"description":802,"published":803,"category":528,"image":804,"draft":532},"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":806,"title":807,"description":808,"published":809,"category":528,"image":810,"draft":532},"\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":812,"title":813,"description":814,"published":815,"category":652,"image":816,"draft":532},"\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":417,"title":818,"description":819,"published":820,"category":528,"image":821,"draft":532},"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":823,"title":824,"description":825,"published":826,"category":652,"image":827,"draft":532},"\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":829,"title":830,"description":831,"published":832,"category":528,"image":833,"draft":532},"\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":835,"title":836,"description":837,"published":838,"category":528,"image":839,"draft":532},"\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":841,"title":842,"description":843,"published":844,"category":528,"image":845,"draft":532},"\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":847,"title":848,"description":849,"published":850,"category":528,"image":851,"draft":532},"\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":853,"title":854,"description":855,"published":856,"category":652,"image":857,"draft":532},"\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":859,"title":860,"description":861,"published":862,"category":652,"image":863,"draft":532},"\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":865,"title":866,"description":867,"published":868,"category":528,"image":869,"draft":532},"\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":871,"title":872,"description":873,"published":874,"category":528,"image":875,"draft":532},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","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":877,"title":878,"description":879,"published":880,"category":652,"image":881,"draft":532},"\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":883,"title":884,"description":885,"published":886,"category":528,"image":887,"draft":532},"\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":889,"title":890,"description":891,"published":886,"category":528,"image":892,"draft":532},"\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":344,"title":894,"description":895,"published":896,"category":528,"image":897,"draft":532},"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":899,"title":900,"description":901,"published":902,"category":652,"image":903,"draft":532},"\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":905,"title":906,"description":907,"published":908,"category":528,"image":909,"draft":532},"\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":911,"title":912,"description":913,"published":908,"category":652,"image":914,"draft":532},"\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":916,"title":917,"description":918,"published":919,"category":652,"image":920,"draft":532},"\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":45,"title":922,"description":923,"published":919,"category":528,"image":924,"draft":532},"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",1791705957971]