[{"data":1,"prerenderedAt":1251},["ShallowReactive",2],{"blog-de-edge-function-returned-a-non-2xx-status-code":3,"blog-index-de":725},{"id":4,"title":5,"body":6,"category":683,"cover":684,"coverAlt":685,"description":686,"draft":687,"extension":688,"faq":689,"image":704,"keywords":705,"meta":713,"navigation":714,"ogTitle":715,"path":716,"published":717,"seo":718,"stem":719,"tldr":720,"updated":717,"__hash__":724},"blog_de\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code.md","\"Edge Function returned a non-2xx status code\": der echte Fehler",{"type":7,"value":8,"toc":670},"minimark",[9,13,24,27,35,40,43,62,65,82,88,92,95,120,133,139,171,175,178,299,314,318,321,337,343,361,378,382,390,407,435,438,458,463,467,470,505,511,515,518,538,553,561,568,572,578,587,601,611,628,632,658],[10,11,12],"p",{},"Du drückst in deiner App den Knopf, der eine Edge Function aufruft, und statt\neines Ergebnisses zeigt deine App das hier:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Edge Function returned a non-2xx status code\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Es ist derselbe Satz, egal was schiefging. Ein fehlender Schlüssel, eine\nabgestürzte Funktion, eine Anfrage, die abgewiesen wurde, bevor dein Code lief:\nAlle lauten \"Edge Function returned a non-2xx status code\", also sagt dir die\nMeldung allein fast nichts darüber, was zu reparieren ist.",[10,28,29,30,34],{},"Was sie dir nicht sagt: Der Grund ist schon angekommen. ",[31,32,33],"strong",{},"Der Fehler kam in\nderselben Antwort zurück wie dieser Satz, und supabase-js liest ihn dir nicht\nvor."," Wer den Satz sucht, findet die Vermutungen anderer Leute. Wer die Antwort\nliest, findet seine eigene.",[36,37,39],"h2",{"id":38},"was-bedeutet-edge-function-returned-a-non-2xx-status-code","Was bedeutet \"Edge Function returned a non-2xx status code\"?",[10,41,42],{},"Deine Funktion hat geantwortet, und die Antwort war ein Fehler. Mehr sagt der\nSatz nicht.",[10,44,45,46,49,50,57,58,61],{},"Jede Antwort im Web trägt einen Statuscode, eine dreistellige Zahl, die sagt,\nwie die Anfrage gelaufen ist. Alles in den 200ern heißt, es hat geklappt. Wenn\ndeine App eine Funktion über ",[21,47,48],{},"supabase.functions.invoke"," aufruft, schaut\nsupabase-js auf diese Zahl, und liegt sie außerhalb der 200er, bekommt deine App\nstatt der Daten einen festen Satz. Der Satz steht wörtlich in\n",[51,52,56],"a",{"href":53,"rel":54},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fsupabase-js\u002Fblob\u002Fmaster\u002Fpackages\u002Fcore\u002Ffunctions-js\u002Fsrc\u002Ftypes.ts",[55],"nofollow","supabase-js selbst",",\nund der Fehler, der ihn trägt, heißt ",[21,59,60],{},"FunctionsHttpError",".",[10,63,64],{},"Stell dir den Aufruf als Brief vor, den du an ein Büro im Hinterhaus schickst.\nDas Büro beantwortet entweder, was du gefragt hast, oder schickt den Brief\nzurück. Kommt er zurück, liest supabase-js den Stempel auf dem Umschlag und sagt\ndir, dass er zurückkam. Den Umschlag öffnet es nicht. Die Notiz darin sagt,\nwarum, und das Büro hat ein Logbuch über alles geführt, was mit deinem Brief\npassiert ist.",[10,66,67,68,71,72,76,77,81],{},"Zwei nahe Verwandte sehen ähnlich aus und bedeuten etwas anderes. ",[21,69,70],{},"Failed to send a request to the Edge Function"," heißt, dass überhaupt keine lesbare Antwort\nzurückkam, und im Browser ist das oft ein fehlender CORS-Header, den\n",[51,73,75],{"href":74},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","der Beitrag zu dieser Meldung","\nbehandelt. Und wenn mehrere voneinander unabhängige Teile deiner App im selben\nMoment kaputtgingen, prüf zuerst,\n",[51,78,80],{"href":79},"\u002Fblog\u002Fis-supabase-down-or-your-app","ob es an Supabase oder an deiner App liegt",",\nbevor du irgendeinen Code öffnest.",[83,84],"diagram",{"alt":85,"caption":86,"src":87},"Eine Anfrage geht vom Browser an eine Edge Function. Die Antwort, die zurückkommt, trägt den Status 500 und einen Inhalt voller Zeilen. supabase-js macht daraus einen einzigen grauen Balken für die App, während eine gestrichelte Linie vom Balken zurück zur offenen Antwort und weiter zum Log der Funktion führt.","Die Antwort trägt den Status und den Grund. supabase-js gibt deiner App einen Satz weiter, und der Grund hängt weiter am Fehler und steht im Log der Funktion.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fthe-reason-rides-back-1600x740.png",[36,89,91],{"id":90},"wo-steht-der-echte-fehler","Wo steht der echte Fehler?",[10,93,94],{},"An zwei Stellen, und du kannst beide lesen, ohne eine Zeile Code zu ändern.",[10,96,97,100,101,104,105,108,109,112,113,116,117,61],{},[31,98,99],{},"Die Antwort selbst."," Öffne deine Live-App in Chrome, Edge oder Firefox, drück\nF12, wähl den Tab ",[31,102,103],{},"Network"," und wiederhole, was fehlgeschlagen ist. Klick die\nAnfrage an, deren Adresse ",[21,106,107],{},"\u002Ffunctions\u002Fv1\u002F"," gefolgt vom Namen deiner Funktion\nenthält. Ihre Spalte ",[31,110,111],{},"Status"," zeigt die Zahl, und ihr Tab ",[31,114,115],{},"Response"," zeigt,\nwas die Funktion mitgeschickt hat: eine Meldung, die dein eigener Code\ngeschrieben hat, ein kurzer JSON-Inhalt von der Plattform von Supabase oder die\nWorte ",[21,118,119],{},"Internal Server Error",[10,121,122,123,128,129,132],{},"Wenn du oder das Werkzeug, das deinen Code schreibt, den Aufruf ändern kann,\nzeigt der\n",[51,124,127],{"href":125,"rel":126},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Ferror-handling",[55],"Leitfaden zur Fehlerbehandlung von Supabase",",\nwie man dieselbe Antwort in der App liest, denn die ursprüngliche Antwort reist\nmit dem Fehler als ",[21,130,131],{},"error.context",":",[14,134,137],{"className":135,"code":136,"language":19},[17],"const { data, error } = await supabase.functions.invoke('your-function', { body })\nif (error) console.log(error.context.status, await error.context.text())\n",[21,138,136],{"__ignoreMap":23},[10,140,141,144,145,148,149,152,153,156,157,162,163,166,167,170],{},[31,142,143],{},"Das Logbuch der Funktion."," Öffne im Supabase-Dashboard ",[31,146,147],{},"Edge Functions",",\nwähl die Funktion und lies zwei Tabs. ",[31,150,151],{},"Invocations"," listet jede Anfrage mit\nihrem Statuscode und ihrer Dauer. ",[31,154,155],{},"Logs"," enthält, was der\n",[51,158,161],{"href":159,"rel":160},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Flogging",[55],"Logging-Leitfaden von Supabase","\nPlattform-Ereignisse, nicht abgefangene Ausnahmen und eigene Log-Meldungen\nnennt, also alles, was dein Code mit ",[21,164,165],{},"console.log"," oder ",[21,168,169],{},"console.error","\nausgegeben hat. Lös den Fehler einmal aus, merk dir die Uhrzeit und lies beide\nTabs zu dieser Minute.",[36,172,174],{"id":173},"lies-zuerst-den-statuscode","Lies zuerst den Statuscode",[10,176,177],{},"Die Zahl sagt dir, wie weit deine Anfrage kam, bevor sie zurückgeschickt wurde,\nund das entscheidet, wo der Grund aufgeschrieben ist.",[179,180,181,196],"table",{},[182,183,184],"thead",{},[185,186,187,190,193],"tr",{},[188,189,111],"th",{},[188,191,192],{},"Was passiert ist",[188,194,195],{},"Wo der Grund steht",[197,198,199,220,236,249,262,275,288],"tbody",{},[185,200,201,207,210],{},[202,203,204],"td",{},[21,205,206],{},"401",[202,208,209],{},"Abgewiesen, bevor dein Code lief, oder dein Code hat abgewiesen",[202,211,212,213,166,216,219],{},"Die Antwort. ",[21,214,215],{},"Invalid JWT",[21,217,218],{},"Missing authorization header"," ist die Plattform",[185,221,222,227,230],{},[202,223,224],{},[21,225,226],{},"404",[202,228,229],{},"In diesem Projekt ist keine Funktion mit diesem Namen deployt",[202,231,232,233],{},"Die Antwort lautet ",[21,234,235],{},"Requested function was not found",[185,237,238,243,246],{},[202,239,240],{},[21,241,242],{},"500",[202,244,245],{},"Dein Code lief und hat einen Fehler geworfen oder absichtlich 500 geliefert",[202,247,248],{},"Der Tab Logs",[185,250,251,256,259],{},[202,252,253],{},[21,254,255],{},"503",[202,257,258],{},"Die Funktion ist gar nicht erst gestartet",[202,260,261],{},"Der Tab Logs: ein Import, ein Syntaxfehler oder die Konfiguration der Funktion",[185,263,264,269,272],{},[202,265,266],{},[21,267,268],{},"504",[202,270,271],{},"Keine Antwort innerhalb von 150 Sekunden",[202,273,274],{},"Der Tab Invocations, dann das, worauf dein Code gewartet hat",[185,276,277,282,285],{},[202,278,279],{},[21,280,281],{},"546",[202,283,284],{},"CPU-Zeit oder Speicher sind ausgegangen",[202,286,287],{},"Der Tab Logs sagt, welches von beiden",[185,289,290,293,296],{},[202,291,292],{},"Jeder andere 4xx",[202,294,295],{},"Dein eigener Code hat ihn gewählt, etwa indem er die Antwort eines Dienstes weitergibt",[202,297,298],{},"Die Antwort",[10,300,301,302,307,308,313],{},"Die Bedeutungen stammen aus der\n",[51,303,306],{"href":304,"rel":305},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fstatus-codes",[55],"Statuscode-Referenz von Supabase","\nund ihrer ",[51,309,312],{"href":310,"rel":311},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Flimits",[55],"Seite zu den Limits",".\nFür einen 404 reicht diese Tabelle: Vergleich den Namen der Funktion in deiner\nApp mit der Liste im Dashboard, und prüf, ob sie in dem Projekt deployt ist, mit\ndem deine App spricht. Die anderen Zeilen haben unten je einen eigenen\nAbschnitt.",[36,315,317],{"id":316},"_500-deine-funktion-lief-und-ist-gescheitert","500: Deine Funktion lief und ist gescheitert",[10,319,320],{},"Irgendetwas in deinem Code hat einen Fehler geworfen, und der Tab Logs hat die\nZeile.",[10,322,323,324,329,330,332,333,336],{},"Die ",[51,325,328],{"href":326,"rel":327},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-500-error-response",[55],"Seite von Supabase zu diesem Fehler","\nteilt ihn in zwei Fälle. Lautet die Antwort genau ",[21,331,119],{},", ist\ndein Code abgestürzt, und das Log zeigt die Art des Fehlers und die Zeile, in der\ner passiert ist, etwa ",[21,334,335],{},"TypeError: Cannot read properties of undefined",". Lautet\ndie Antwort anders, hat dein Code diese Meldung selbst geschrieben und die 500\nabsichtlich geliefert, also such in der Funktion nach dem Status, den sie\ngeschickt hat.",[10,338,339,340],{},"Eine Ursache lohnt es vor allen anderen auszuschließen, wenn eine Funktion\nOpenAI, Stripe oder irgendeine bezahlte API aufruft: ",[31,341,342],{},"ein Secret, das auf deinem\nRechner existiert und in deinem Live-Projekt nicht.",[10,344,345,346,349,350,357,358,360],{},"In der Funktion wird ein Secret mit ",[21,347,348],{},"Deno.env.get('OPENAI_API_KEY')"," gelesen.\nIst kein Secret dieses Namens gesetzt, liefert das laut Doku von Deno\n",[51,351,354],{"href":352,"rel":353},"https:\u002F\u002Fdocs.deno.com\u002Fapi\u002Fdeno\u002F~\u002FDeno.Env.get",[55],[21,355,356],{},"undefined",", statt zu\nscheitern. Die Funktion läuft also weiter, baut eine Anfrage mit dem Wort\n",[21,359,356],{}," an der Stelle des Schlüssels und schickt sie ab. OpenAI antwortet\nmit einem eigenen 401, \"Incorrect API key provided\", und deine Funktion gibt das\nentweder weiter oder stürzt beim Lesen einer Antwort ab, mit der sie nicht\ngerechnet hat. Im Bild mit dem Umschlag: Das Büro hat deinen Brief geöffnet, ist\nzu der Schublade gegangen, in der der Schlüssel liegen sollte, hat sie leer\nvorgefunden und eine Notiz über einen falschen Schlüssel zurückgeschickt.",[10,362,363,364,367,368,373,374,377],{},"Die Reparatur liegt auf der Seite ",[31,365,366],{},"Edge Function Secrets"," deines\nSupabase-Projekts. Laut\n",[51,369,372],{"href":370,"rel":371},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fsecrets",[55],"Secrets-Leitfaden von Supabase","\nliest eine Funktion ein neues Secret sofort, du musst also nicht neu deployen,\nund kein Secret-Name darf mit ",[21,375,376],{},"SUPABASE_"," beginnen, weil dieses Präfix für die\nWerte reserviert ist, die Supabase für dich setzt. Ein Secret, das du für die\nlokale Entwicklung setzt, bleibt auf deinem Rechner; das Live-Projekt hat seine\neigene Liste.",[36,379,381],{"id":380},"_401-abgewiesen-bevor-dein-code-lief","401: Abgewiesen, bevor dein Code lief",[10,383,384,385,166,387,389],{},"Lautet die Antwort ",[21,386,215],{},[21,388,218],{},", hat deine\nFunktion die Anfrage nie gesehen. Die Plattform von Supabase hat sie an der Tür\nabgewiesen.",[10,391,392,393,396,397,400,401,406],{},"Diese Tür ist eine Prüfung namens ",[21,394,395],{},"verify_jwt",", standardmäßig an, die den Header\n",[21,398,399],{},"Authorization"," jeder Anfrage liest, bevor dein Code läuft. Die\n",[51,402,405],{"href":403,"rel":404},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-401-error-response",[55],"Seite von Supabase zum 401","\nnennt drei Arten, an ihr zu scheitern:",[408,409,410,417,429],"ul",{},[411,412,413,416],"li",{},[31,414,415],{},"Der Schlüssel passt nicht zu den Schlüsseln deines Projekts."," Zum Beispiel\nein Schlüssel aus einem anderen Projekt oder ein alter, der nach einer Rotation\nnoch irgendwo eingetragen ist.",[411,418,419,424,425,428],{},[31,420,421,422,61],{},"Es gibt überhaupt keinen Header ",[21,423,399],{}," supabase-js fügt einen\nfür dich hinzu. Ein einfaches ",[21,426,427],{},"fetch"," an die Adresse der Funktion oder ein\nWebhook von einem anderen Dienst tut das nicht.",[411,430,431,434],{},[31,432,433],{},"Dein Projekt nutzt die neueren Signaturschlüssel von Supabase."," Die\neingebaute Prüfung versteht nur das ältere Format, und die Lösung von Supabase\nist, die Prüfung für diese Funktion abzuschalten.",[10,436,437],{},"Dieser letzte Punkt reicht über den einen Fall hinaus. Supabase empfiehlt\ninzwischen, die eingebaute Prüfung abzuschalten und die Authentifizierung direkt\nim Code deiner Funktion zu erledigen. Die Empfehlung hat zwei Hälften, und die\nzweite ist die, die unter den Tisch fällt.",[10,439,440,441,444,445,449,450,453,454,457],{},"Kam der 401 mit einer Meldung, die dein eigener Code geschrieben hat, hat die\nPlattform die Anfrage durchgelassen, und deine Funktion hat sie abgewiesen oder\neinen 401 des aufgerufenen Dienstes weitergegeben, oft das leere Secret aus dem\nAbschnitt zur 500. Das ist außerdem eine andere Prüfung als die hinter\n",[21,442,443],{},"PGRST301"," bei deinen Datenbankabfragen, die\n",[51,446,448],{"href":447},"\u002Fblog\u002Fsupabase-invalid-jwt","eine eigene Seite hat",". Steht im Log der Funktion\n",[21,451,452],{},"invalid claim: missing sub claim",", hat sie Supabase Auth gefragt, wer da\naufruft, und statt eines angemeldeten Nutzers den Schlüssel deines Projekts\nbekommen; ",[51,455,75],{"href":456},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","\nverfolgt das.",[83,459],{"alt":460,"caption":461,"src":462},"Eine Anfrage reist vom Browser durch ein Tor in die Funktion und weiter zu einem externen Dienst. Jeder Ort, an dem sie stehen bleiben kann, trägt seine Zahl: 401 am Tor, 404 dort, wo an der Adresse keine Funktion steht, 500 in der Funktion, 546 und 504 an einer Uhr daneben, und ein 401 des externen Dienstes, den die Funktion zurückgibt.","Der Status sagt, wie weit die Anfrage kam. Ein 401 am Tor hat deinen Code nie erreicht; ein 401, den der aufgerufene Dienst zurückgibt, schon.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fhow-far-it-got-1600x720.png",[36,464,466],{"id":465},"_546-und-504-keine-ressourcen-oder-keine-zeit-mehr","546 und 504: keine Ressourcen oder keine Zeit mehr",[10,468,469],{},"Supabase stoppt eine Funktion, die zu viel braucht, und die beiden Zahlen sagen,\nwelches Limit sie getroffen hat.",[10,471,472,475,476,479,480,483,484,487,488,491,492,166,495,498,499,504],{},[31,473,474],{},"546 ist Rechenleistung."," Die\n",[51,477,312],{"href":310,"rel":478},[55]," gibt\neiner Funktion 256 MB Speicher und jeder Anfrage 2 Sekunden CPU-Zeit. Geht eines\ndavon darüber, lautet die Antwort\n",[21,481,482],{},"Function failed due to not having enough compute resources (please check logs)",",\nmit dem Code ",[21,485,486],{},"WORKER_RESOURCE_LIMIT"," (ältere Logs sagen ",[21,489,490],{},"WORKER_LIMIT","). Der Tab\nLogs sagt ",[21,493,494],{},"CPU Time exceeded",[21,496,497],{},"Memory limit exceeded",". Die\n",[51,500,503],{"href":501,"rel":502},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-546-error-response",[55],"Seite von Supabase zum 546","\nnennt Bildverarbeitung, KI-Embeddings und Web-Scraping als Beispiele, und ihre\nAntwort ist, pro Anfrage weniger zu tun oder den schweren Teil an einen anderen\nDienst abzugeben.",[10,506,507,510],{},[31,508,509],{},"504 ist Zeit."," Eine Funktion, die innerhalb von 150 Sekunden keine Antwort\nschickt, bekommt einen 504. Das CPU-Limit zählt nur die Zeit, in der dein Code\ntatsächlich rechnet: Laut der Seite zu den Limits zählt asynchrone Ein- und\nAusgabe nicht dazu, und genau das ist Warten auf das Netz. Eine Funktion, die\nauf ein langsames KI-Modell wartet, verbraucht also keine CPU. Sie lässt die Uhr\nvon 150 Sekunden ablaufen, und wenn die abgelaufen ist, bekommst du einen 504\nund keinen 546.",[36,512,514],{"id":513},"zwei-lösungen-die-es-schlimmer-machen","Zwei Lösungen, die es schlimmer machen",[10,516,517],{},"Zwei Änderungen lassen diese Meldung in wenigen Minuten verschwinden, und beide\nlassen dich schlechter dastehen als der Fehler.",[10,519,520,523,524,527,528,532,533,537],{},[31,521,522],{},"Die API stattdessen aus der Seite aufrufen."," Am schnellsten hört eine\nfehlschlagende Funktion auf zu fehlschlagen, wenn man sie nicht mehr benutzt:\nden Schlüssel in eine Variable mit ",[21,525,526],{},"VITE_"," legen und OpenAI direkt aus deinem\nFrontend aufrufen. Das klappt beim ersten Versuch. Es legt den Schlüssel aber\nauch in die Datei, die jeder Besucher herunterlädt, denn dieses Präfix ist\n",[51,529,531],{"href":530},"\u002Fblog\u002Fvite-and-next-public-env-vars","eine Anweisung, den Wert in dein Bundle zu kompilieren",",\nund dort kann ihn jeder lesen. Unter den Live-Apps, die wir gescannt haben,\ntauchte im JavaScript von 33 ein OpenAI-Schlüssel auf, und\n",[51,534,536],{"href":535},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","was ein Fremder damit anfangen kann",",\nsteht in einem eigenen Beitrag.",[10,539,540,543,544,546,547,552],{},[31,541,542],{},"Die Prüfung abschalten und dabei stehen bleiben."," Einen 401 zu beseitigen,\nindem man ",[21,545,395],{}," abschaltet, ist die erste Hälfte des eigenen Rats von\nSupabase. Der\n",[51,548,551],{"href":549,"rel":550},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Ffunction-configuration",[55],"Konfigurationsleitfaden von Supabase","\nsagt klar, was das allein bewirkt: Dann kann jeder deine Edge Function ohne\ngültiges JWT aufrufen. Die Adresse deiner Funktion steht in deinem Frontend, für\njeden lesbar. Hält die Funktion einen OpenAI-Schlüssel, kann ein Fremder ihn\njetzt über dich ausgeben. Nutzt sie den geheimen Schlüssel des Projekts, den\nSupabase in die Umgebung jeder Funktion legt, läuft die Anfrage eines Fremden mit\neinem Schlüssel, der an jeder Row-Level-Security-Regel vorbeikommt, die du\ngeschrieben hast.",[10,554,555,556,560],{},"Die zweite Hälfte, eine Prüfung im Code der Funktion, wer da aufruft, ist ein\npaar Zeilen lang.\n",[51,557,559],{"href":558},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Ein Secret in eine Edge Function verschieben","\nenthält sie und erklärt, warum selbst die Standardprüfung mehr Aufrufer\ndurchlässt, als ihr Name vermuten lässt.",[10,562,563,564,61],{},"Den ersten Fehler sieht man von außen, und so haben wir ihn gezählt. Unser\nkostenloser Scan liest das JavaScript deiner Live-App so, wie ein Fremder es\nlesen würde, und nennt jeden Schlüssel, den er findet, samt der Angabe, ob er\ndorthin gehört. Das dauert etwa 20 Sekunden und braucht kein Konto:\n",[51,565,567],{"href":566},"\u002Fsecurity-scanner","scanne deine App",[36,569,571],{"id":570},"damit-der-schlüssel-bleibt-wo-du-ihn-hingelegt-hast","Damit der Schlüssel bleibt, wo du ihn hingelegt hast",[10,573,574,577],{},[31,575,576],{},"Die Lösung von heute kann der Prompt von nächster Woche rückgängig machen.","\nEin Builder, der ein Feature wieder zum Laufen bringen soll, darf die Abkürzung\nvon oben nehmen, und deine App läuft weiter, während er es tut.",[10,579,580],{},[31,581,582,586],{},[51,583,585],{"href":584},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft jede Stunde, damit du es nicht musst:",[408,588,589,592,595,598],{},[411,590,591],{},"alle neun Checks jede Stunde, für bis zu drei Apps",[411,593,594],{},"eine E-Mail an dem Tag, an dem ein erneuter Scan deine App schlechter benotet als der vorige; ein geheimer Schlüssel in deinem JavaScript deckelt die Note allein schon bei D",[411,596,597],{},"ob die App erreichbar ist, alle 60 Sekunden",[411,599,600],{},"ein monatlicher Bericht darüber, was gesehen wurde",[10,602,603],{},[31,604,605,606,610],{},"Eine Funktion, die mit deinem geheimen Schlüssel läuft, kommt an jeder\nRow-Level-Security-Regel vorbei. ",[51,607,609],{"href":608},"\u002Fsupabase-backups","Reeve Care"," hält eine Kopie\ndeiner Supabase-Datenbank dort, wo nichts in deinem Projekt sie erreicht.",[408,612,613,616,619,622,625],{},[411,614,615],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[411,617,618],{},"jede Kopie wird geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[411,620,621],{},"eine Wiederherstellung per Klick, die sichert, was jetzt da ist, bevor sie es ersetzt",[411,623,624],{},"deine hochgeladenen Dateien ebenfalls, sobald du eine Storage-Zugangsberechtigung verbindest",[411,626,627],{},"alles, was Monitor tut",[36,629,631],{"id":630},"was-jetzt-zu-tun-ist","Was jetzt zu tun ist",[633,634,635],"key-takeaways",{},[408,636,637,640,643,646,649,652],{},[411,638,639],{},"Lös den Fehler einmal aus und merk dir die Uhrzeit.",[411,641,642],{},"Öffne die Anfrage im Tab Network deines Browsers und lies Status und Antwort, bevor du irgendetwas änderst.",[411,644,645],{},"Lies die Tabs Invocations und Logs der Funktion im Supabase-Dashboard zu dieser Minute.",[411,647,648],{},"Bei einer 500 aus einer Funktion, die eine bezahlte API aufruft: Prüf, ob das Secret auf der Seite Edge Function Secrets des Live-Projekts gesetzt ist. Danach ist kein neues Deploy nötig.",[411,650,651],{},"Bei einem 401 von der Plattform: Korrigier den Schlüssel oder schalte die eingebaute Prüfung ab, und füg in derselben Änderung eine Prüfung in der Funktion hinzu, wer da aufruft.",[411,653,654,655,657],{},"Beseitige diesen Fehler nie, indem du den Schlüssel in eine Variable mit ",[21,656,526],{}," verschiebst.",[10,659,660,661,664,665,669],{},"Die Prüfung, wer da aufruft, ist der Schritt, den man am leichtesten auslässt,\nund\n",[51,662,663],{"href":558},"die Anleitung zu Secrets in Edge Functions","\nbehandelt ihn vollständig. Die ",[51,666,668],{"href":667},"\u002Fchecklist","10-Minuten-Sicherheitscheckliste","\ndeckt ab, was in einer frisch gestarteten App sonst gern offen bleibt.",{"title":23,"searchDepth":671,"depth":671,"links":672},3,[673,675,676,677,678,679,680,681,682],{"id":38,"depth":674,"text":39},2,{"id":90,"depth":674,"text":91},{"id":173,"depth":674,"text":174},{"id":316,"depth":674,"text":317},{"id":380,"depth":674,"text":381},{"id":465,"depth":674,"text":466},{"id":513,"depth":674,"text":514},{"id":570,"depth":674,"text":571},{"id":630,"depth":674,"text":631},"Sicherheitsgrundlagen","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcover-1200x630.png","Ein zurückgeschickter Umschlag mit einem gelben Stempel quer über der Vorderseite und offener Lasche, aus der der gefaltete Brief noch herausschaut.","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.",false,"md",[690,692,695,698,701],{"q":39,"a":691},"Deine Supabase Edge Function hat mit einem Fehlerstatus geantwortet, also mit irgendeiner Zahl außerhalb der 200er, und supabase-js hat aus dieser Antwort einen festen Satz gemacht. Der Satz ist derselbe für einen Absturz, einen fehlenden Schlüssel, eine Anfrage, die abgewiesen wurde, bevor dein Code lief, und eine Zeitüberschreitung. Die Antwort selbst, die sagt, was davon es war, hängt noch am Fehler, und die Funktion führt ein eigenes Log.",{"q":693,"a":694},"Wie sehe ich den echten Fehler dahinter?","Öffne deine Live-App, drück F12, wähl den Tab Network und wiederhole, was fehlgeschlagen ist. Klick die Anfrage an, deren Adresse \u002Ffunctions\u002Fv1\u002F enthält, und lies ihren Status und ihre Antwort: Das ist, was die Funktion tatsächlich geschickt hat. Öffne dann Edge Functions in deinem Supabase-Dashboard, wähl die Funktion und lies zur selben Zeit die Tabs Invocations und Logs. Im Code liest der Leitfaden von Supabase dieselbe Antwort mit await error.context.json().",{"q":696,"a":697},"Warum läuft meine Edge Function lokal und scheitert nach dem Deploy?","Prüf zuerst, ob ein Secret auf deinem Rechner existiert und in deinem Live-Projekt nicht. Die lokale Umgebung liest ihre eigene Umgebungsdatei, die deployte Funktion liest die Secrets, die im Projekt gesetzt sind. Ein fehlendes Secret kommt als undefined zurück statt als Fehler, also läuft die Funktion weiter und scheitert später, meist wenn der aufgerufene Dienst einen leeren Schlüssel ablehnt. Setz es auf der Seite Edge Function Secrets; laut Supabase wird ein neues Secret sofort gelesen, ohne neues Deploy.",{"q":699,"a":700},"Soll ich die JWT-Prüfung abschalten, um einen 401 loszuwerden?","Supabase empfiehlt inzwischen, die eingebaute Prüfung abzuschalten und den Aufrufer stattdessen in deiner Funktion zu prüfen. Beide Hälften zählen. Allein abgeschaltet hält die Prüfung nichts mehr auf, und die Doku von Supabase warnt selbst, dass dann jeder deine Funktion ohne gültiges JWT aufrufen kann. Hält die Funktion einen OpenAI-Schlüssel oder den geheimen Schlüssel des Projekts, ist das jeder im Internet, der dein Kontingent verbraucht oder an deinen Row-Level-Security-Regeln vorbeikommt.",{"q":702,"a":703},"Was bedeutet Fehler 546 bei einer Supabase Edge Function?","Der Funktion ist die Rechenleistung ausgegangen: mehr als 2 Sekunden CPU-Zeit oder mehr als ihr Speicher bei einer Anfrage. Die Antwort lautet \"Function failed due to not having enough compute resources (please check logs)\", und der Tab Logs sagt, welches Limit es war, CPU Time exceeded oder Memory limit exceeded. Das Warten auf eine langsame API zählt nicht als CPU-Zeit; eine Funktion, die zu lange wartet, bekommt stattdessen einen 504.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",[706,707,60,708,709,710,711,712],"edge function returned a non-2xx status code","supabase edge function fehler","supabase functions invoke fehler","supabase edge function 500","supabase edge function 401","supabase edge function logs","lovable edge function fehler",{},true,"\"Edge Function returned a non-2xx status code\" in Supabase","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","2026-10-27",{"title":5,"description":686},"blog\u002Fedge-function-returned-a-non-2xx-status-code",[721,722,723],"\"Edge Function returned a non-2xx status code\" sagt supabase-js zu jeder Antwort deiner Funktion außerhalb der 200er. Der echte Grund kam in derselben Antwort zurück, und die Logs der Funktion enthalten den Rest.","Lies zuerst die Statusnummer. 401 heißt, die Anfrage wurde abgewiesen, bevor dein Code lief, 404, dass keine Funktion dieses Namens deployt ist, 500, dass dein Code gescheitert ist, 546 oder 504, dass Ressourcen oder Zeit ausgingen.","Zwei schnelle Lösungen lassen die Meldung verschwinden und reißen ein Loch: die API aus deinem Frontend aufrufen, mit dem Schlüssel darin, und die JWT-Prüfung abschalten, ohne eine eigene Prüfung an ihre Stelle zu setzen.","lH0M28DPtJkj3YkJYK_2sZP8onlqY1mY32z6cIMpbMs",[726,732,738,744,750,756,761,766,772,778,784,791,797,803,804,810,816,822,828,834,840,846,852,858,864,869,875,881,887,893,899,905,911,917,923,929,934,940,946,952,957,963,969,975,981,987,992,998,1004,1010,1016,1022,1028,1034,1039,1045,1051,1057,1063,1069,1075,1081,1087,1093,1099,1105,1111,1117,1123,1128,1134,1140,1146,1152,1158,1164,1170,1176,1182,1188,1194,1200,1206,1212,1217,1223,1229,1235,1240,1246],{"path":727,"title":728,"description":729,"published":730,"category":683,"image":731,"draft":687},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":733,"title":734,"description":735,"published":736,"category":683,"image":737,"draft":687},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":739,"title":740,"description":741,"published":742,"category":683,"image":743,"draft":687},"\u002Fblog\u002Fviolates-foreign-key-constraint","Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":745,"title":746,"description":747,"published":748,"category":683,"image":749,"draft":687},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":751,"title":752,"description":753,"published":754,"category":683,"image":755,"draft":687},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":456,"title":757,"description":758,"published":759,"category":683,"image":760,"draft":687},"Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":74,"title":762,"description":763,"published":764,"category":683,"image":765,"draft":687},"\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":767,"title":768,"description":769,"published":770,"category":683,"image":771,"draft":687},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":773,"title":774,"description":775,"published":776,"category":683,"image":777,"draft":687},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" bei einem neuen Link","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":779,"title":780,"description":781,"published":782,"category":683,"image":783,"draft":687},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":785,"title":786,"description":787,"published":788,"category":789,"image":790,"draft":687},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":792,"title":793,"description":794,"published":795,"category":683,"image":796,"draft":687},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":798,"title":799,"description":800,"published":801,"category":683,"image":802,"draft":687},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":716,"title":5,"description":686,"published":717,"category":683,"image":704,"draft":687},{"path":805,"title":806,"description":807,"published":808,"category":683,"image":809,"draft":687},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":811,"title":812,"description":813,"published":814,"category":683,"image":815,"draft":687},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": was im Zitat steht","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":817,"title":818,"description":819,"published":820,"category":683,"image":821,"draft":687},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":823,"title":824,"description":825,"published":826,"category":683,"image":827,"draft":687},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":829,"title":830,"description":831,"published":832,"category":683,"image":833,"draft":687},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":835,"title":836,"description":837,"published":838,"category":683,"image":839,"draft":687},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":841,"title":842,"description":843,"published":844,"category":683,"image":845,"draft":687},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":847,"title":848,"description":849,"published":850,"category":683,"image":851,"draft":687},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":853,"title":854,"description":855,"published":856,"category":683,"image":857,"draft":687},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":859,"title":860,"description":861,"published":862,"category":683,"image":863,"draft":687},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": die drei Dinge, die es bedeutet","Supabase \"Bucket not found\" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":447,"title":865,"description":866,"published":867,"category":683,"image":868,"draft":687},"Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":870,"title":871,"description":872,"published":873,"category":683,"image":874,"draft":687},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":876,"title":877,"description":878,"published":879,"category":683,"image":880,"draft":687},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":882,"title":883,"description":884,"published":885,"category":683,"image":886,"draft":687},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":888,"title":889,"description":890,"published":891,"category":683,"image":892,"draft":687},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":894,"title":895,"description":896,"published":897,"category":683,"image":898,"draft":687},"\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":900,"title":901,"description":902,"published":903,"category":683,"image":904,"draft":687},"\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":906,"title":907,"description":908,"published":909,"category":683,"image":910,"draft":687},"\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":912,"title":913,"description":914,"published":915,"category":683,"image":916,"draft":687},"\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":918,"title":919,"description":920,"published":921,"category":683,"image":922,"draft":687},"\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":924,"title":925,"description":926,"published":927,"category":683,"image":928,"draft":687},"\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":558,"title":930,"description":931,"published":932,"category":683,"image":933,"draft":687},"API-Schlüssel verstecken: ab in eine Supabase Edge Function","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.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":935,"title":936,"description":937,"published":938,"category":683,"image":939,"draft":687},"\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":941,"title":942,"description":943,"published":944,"category":683,"image":945,"draft":687},"\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":947,"title":948,"description":949,"published":950,"category":683,"image":951,"draft":687},"\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":79,"title":953,"description":954,"published":955,"category":683,"image":956,"draft":687},"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":958,"title":959,"description":960,"published":961,"category":683,"image":962,"draft":687},"\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":964,"title":965,"description":966,"published":967,"category":683,"image":968,"draft":687},"\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":970,"title":971,"description":972,"published":973,"category":789,"image":974,"draft":687},"\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","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":976,"title":977,"description":978,"published":979,"category":789,"image":980,"draft":687},"\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":982,"title":983,"description":984,"published":985,"category":789,"image":986,"draft":687},"\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":988,"title":989,"description":990,"published":985,"category":683,"image":991,"draft":687},"\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":993,"title":994,"description":995,"published":996,"category":683,"image":997,"draft":687},"\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":999,"title":1000,"description":1001,"published":1002,"category":683,"image":1003,"draft":687},"\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":1005,"title":1006,"description":1007,"published":1008,"category":789,"image":1009,"draft":687},"\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":1011,"title":1012,"description":1013,"published":1014,"category":683,"image":1015,"draft":687},"\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":1017,"title":1018,"description":1019,"published":1020,"category":683,"image":1021,"draft":687},"\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":1023,"title":1024,"description":1025,"published":1026,"category":683,"image":1027,"draft":687},"\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":1029,"title":1030,"description":1031,"published":1032,"category":683,"image":1033,"draft":687},"\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":530,"title":1035,"description":1036,"published":1037,"category":683,"image":1038,"draft":687},"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":1040,"title":1041,"description":1042,"published":1043,"category":683,"image":1044,"draft":687},"\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":1046,"title":1047,"description":1048,"published":1049,"category":683,"image":1050,"draft":687},"\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":1052,"title":1053,"description":1054,"published":1055,"category":683,"image":1056,"draft":687},"\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":1058,"title":1059,"description":1060,"published":1061,"category":789,"image":1062,"draft":687},"\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":1064,"title":1065,"description":1066,"published":1067,"category":789,"image":1068,"draft":687},"\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":1070,"title":1071,"description":1072,"published":1073,"category":789,"image":1074,"draft":687},"\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":1076,"title":1077,"description":1078,"published":1079,"category":683,"image":1080,"draft":687},"\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":1082,"title":1083,"description":1084,"published":1085,"category":683,"image":1086,"draft":687},"\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":1088,"title":1089,"description":1090,"published":1091,"category":683,"image":1092,"draft":687},"\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":1094,"title":1095,"description":1096,"published":1097,"category":683,"image":1098,"draft":687},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1100,"title":1101,"description":1102,"published":1103,"category":683,"image":1104,"draft":687},"\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. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1106,"title":1107,"description":1108,"published":1109,"category":683,"image":1110,"draft":687},"\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":1112,"title":1113,"description":1114,"published":1115,"category":683,"image":1116,"draft":687},"\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":1118,"title":1119,"description":1120,"published":1121,"category":683,"image":1122,"draft":687},"\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":535,"title":1124,"description":1125,"published":1126,"category":683,"image":1127,"draft":687},"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":1129,"title":1130,"description":1131,"published":1132,"category":683,"image":1133,"draft":687},"\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":1135,"title":1136,"description":1137,"published":1138,"category":789,"image":1139,"draft":687},"\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":1141,"title":1142,"description":1143,"published":1144,"category":683,"image":1145,"draft":687},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1147,"title":1148,"description":1149,"published":1150,"category":789,"image":1151,"draft":687},"\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":1153,"title":1154,"description":1155,"published":1156,"category":683,"image":1157,"draft":687},"\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":1159,"title":1160,"description":1161,"published":1162,"category":683,"image":1163,"draft":687},"\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":1165,"title":1166,"description":1167,"published":1168,"category":683,"image":1169,"draft":687},"\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":1171,"title":1172,"description":1173,"published":1174,"category":683,"image":1175,"draft":687},"\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":1177,"title":1178,"description":1179,"published":1180,"category":789,"image":1181,"draft":687},"\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":1183,"title":1184,"description":1185,"published":1186,"category":789,"image":1187,"draft":687},"\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":1189,"title":1190,"description":1191,"published":1192,"category":683,"image":1193,"draft":687},"\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":1195,"title":1196,"description":1197,"published":1198,"category":683,"image":1199,"draft":687},"\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":1201,"title":1202,"description":1203,"published":1204,"category":789,"image":1205,"draft":687},"\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":1207,"title":1208,"description":1209,"published":1210,"category":683,"image":1211,"draft":687},"\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":1213,"title":1214,"description":1215,"published":1210,"category":683,"image":1216,"draft":687},"\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":1218,"title":1219,"description":1220,"published":1221,"category":683,"image":1222,"draft":687},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","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":1224,"title":1225,"description":1226,"published":1227,"category":789,"image":1228,"draft":687},"\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":1230,"title":1231,"description":1232,"published":1233,"category":683,"image":1234,"draft":687},"\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":1236,"title":1237,"description":1238,"published":1233,"category":789,"image":1239,"draft":687},"\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":1241,"title":1242,"description":1243,"published":1244,"category":789,"image":1245,"draft":687},"\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":1247,"title":1248,"description":1249,"published":1244,"category":683,"image":1250,"draft":687},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","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",1794213638709]