[{"data":1,"prerenderedAt":1136},["ShallowReactive",2],{"blog-de-supabase-invalid-login":3,"blog-index-de":607},{"id":4,"title":5,"body":6,"category":565,"cover":566,"coverAlt":567,"description":568,"draft":569,"extension":570,"faq":571,"image":587,"keywords":588,"meta":595,"navigation":596,"ogTitle":597,"path":598,"published":599,"seo":600,"stem":601,"tldr":602,"updated":599,"__hash__":606},"blog_de\u002Fblog\u002Fsupabase-invalid-login.md","\"Invalid login credentials\" in Supabase: die drei Ursachen",{"type":7,"value":8,"toc":552},"minimark",[9,13,24,27,35,40,43,64,94,97,101,104,110,116,122,131,137,141,148,161,168,174,177,255,262,266,269,272,275,288,292,295,306,332,335,339,342,345,348,357,368,378,385,390,394,397,433,436,442,445,449,452,461,475,484,504,508,539],[10,11,12],"p",{},"Jemand schreibt dir, dass er sich nicht in deine App einloggen kann, und ist\nsicher, dass das Passwort stimmt. Du probierst seine Adresse selbst und bekommst\ndieselbe rote Zeile unter dem Formular:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Invalid login credentials\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Supabase antwortet \"Invalid login credentials\" bei einem falschen Passwort. Mit\ngenau denselben Worten antwortet es zwei anderen Menschen: jemandem, dessen\nE-Mail in deiner App kein Konto hat, und jemandem, der sich mit Google\nregistriert hat und nie ein Passwort hatte. Deine App aus Lovable, Bolt, v0,\nCursor, Claude Code oder Replit arbeitet so, wie sie gebaut ist. Sie gibt drei\nverschiedenen Situationen eine Antwort.",[10,28,29,30,34],{},"Hier liegt der Teil, den die naheliegende Lösung falsch macht: ",[31,32,33],"strong",{},"Die vage Meldung\nist Absicht, und wer sie hilfreicher macht, reißt ein Loch."," Was hilft, ist\nherauszufinden, welchen der drei Fälle du vor dir hast. Das sagt dir dein eigenes\nDashboard, während das Formular weiter so wenig sagt wie jetzt.",[36,37,39],"h2",{"id":38},"was-bedeutet-invalid-login-credentials-in-supabase","Was bedeutet \"Invalid login credentials\" in Supabase?",[10,41,42],{},"Supabase Auth, der Teil von Supabase, der Leute anmeldet, hat eine E-Mail und\nein Passwort abgelehnt und behält den Grund für sich.",[10,44,45,46,53,54,57,58,63],{},"Die Meldung steht im Code des Auth-Servers selbst. In\n",[47,48,52],"a",{"href":49,"rel":50},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Ftoken.go",[51],"nofollow","der Funktion, die eine Anmeldung mit Passwort verarbeitet",",\nkommt derselbe Fehler an drei Stellen zurück: wenn kein Nutzer diese E-Mail hat,\nwenn für den Nutzer kein Passwort gespeichert ist und wenn das Passwort nicht\npasst. Jedes Mal ist die Antwort HTTP 400 mit dem Code ",[21,55,56],{},"invalid_credentials",",\nden Supabases\n",[47,59,62],{"href":60,"rel":61},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fdebugging\u002Ferror-codes",[51],"Referenz der Fehlercodes","\nals \"Login credentials or grant type not recognized.\" beschreibt.",[10,65,66,67,70,71,74,75,78,79,81,82,84,85,88,89,93],{},"In deiner App kommt er als ",[21,68,69],{},"AuthApiError"," aus ",[21,72,73],{},"signInWithPassword"," an, mit\n",[21,76,77],{},"error.code"," gleich ",[21,80,56],{},". Dieselbe Referenz sagt, Fehler immer\nan ",[21,83,77],{}," und ",[21,86,87],{},"error.name"," zu erkennen, und das zählt später, wenn du\nentscheidest, was dein Formular sagt. Wenn deine Nutzer angemeldet waren und dann\nhinausgeworfen wurden, ist das ein anderer Fehler mit\n",[47,90,92],{"href":91},"\u002Fblog\u002Fsupabase-users-logged-out","einer eigenen Seite",".",[10,95,96],{},"Stell dir dein Anmeldeformular als Tastenfeld neben der Haustür eines Gebäudes\nvor. Jemand tippt einen Code ein, und eine Lampe antwortet. Grün öffnet die Tür.\nRot leuchtet bei einem falschen Code, bei einem Code, den nie jemand bekommen\nhat, und bei einem Bewohner, der immer mit einem Ausweis durch die Seitentür\ngekommen ist und nie einen Code hatte.",[36,98,100],{"id":99},"die-drei-menschen-hinter-der-meldung","Die drei Menschen hinter der Meldung",[10,102,103],{},"Jeder der drei braucht eine andere Lösung, deshalb lohnt es sich zu wissen, wen\ndu vor dir hast.",[10,105,106,109],{},[31,107,108],{},"Das falsche Passwort."," Das Konto existiert, es hat ein Passwort, und die\nEingabe passt nicht dazu. Dazu gehören ein Passwort, das auf einem anderen Gerät\ngeändert und seitdem vergessen wurde, und ein Passwortmanager, der ein altes\neinträgt.",[10,111,112,115],{},[31,113,114],{},"Die Adresse ohne Konto."," Niemand in deinem Projekt hat sich mit dieser E-Mail\nregistriert. Es kann eine zweite Adresse sein (die berufliche, wenn die Person\nsich mit der privaten registriert hat) oder ein Tippfehler bei der\nRegistrierung, der jetzt als ihre E-Mail gespeichert ist.",[10,117,118,121],{},[31,119,120],{},"Das Konto ohne Passwort."," Die Person hat sich mit Google, GitHub oder einem\nanderen Anmeldeknopf registriert, und Supabase hat nie ein Passwort für sie\ngespeichert. Kommt sie zurück und tippt eins ein, gibt es nichts zum Vergleichen.\nDer Auth-Server prüft, ob ein Passwort gespeichert ist, bevor er sich das\neingegebene ansieht, und ein Konto ohne bekommt dieselbe 400.",[10,123,124,125,130],{},"Wer sich mit einem Magic Link registriert hat, dem Anmeldelink per E-Mail, ist\neine Spielart des ersten Falls. Supabases\n",[47,126,129],{"href":127,"rel":128},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Fmagic_link.go",[51],"Code für Magic Links","\nlegt das Konto mit einem zufälligen Passwort an, das nie jemandem gezeigt wird,\nalso ist jedes Passwort, das die Person eintippt, ein falsches.",[132,133],"diagram",{"alt":134,"caption":135,"src":136},"Drei Menschen gehen auf dasselbe Tastenfeld zu: einer mit einem Schlüssel, der nicht passt, einer in gestrichelter Umrisslinie, weil es für ihn kein Konto gibt, und einer mit einem Ausweis statt eines Schlüssels. Ihre drei Wege treffen sich am Tastenfeld, seine einzige Lampe leuchtet rot, und eine einzige gleiche Antwort kommt heraus.","Ein falsches Passwort, eine unbekannte Adresse und ein Konto ohne Passwort landen bei derselben Prüfung und bekommen alle dieselbe Antwort.","\u002Fblog\u002Fsupabase-invalid-login\u002Fthree-people-one-light-1600x760.png",[36,138,140],{"id":139},"wie-finde-ich-heraus-welcher-fall-es-war","Wie finde ich heraus, welcher Fall es war?",[10,142,143,144,147],{},"Frag deine eigene Datenbank. Jedes Konto in deinem Projekt ist eine Zeile in\neiner Tabelle namens ",[21,145,146],{},"auth.users",", und diese Zeile sagt, wie sich die Person\nanmeldet.",[10,149,150,151,156,157,160],{},"Supabases ",[47,152,155],{"href":153,"rel":154},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fusers",[51],"Leitfaden zu Nutzern","\nbeschreibt das Feld, auf das es ankommt: ",[21,158,159],{},"app_metadata.providers"," ist laut\nSupabase die Liste der Anbieter, mit denen sich der Nutzer anmelden kann. Ein\nNutzer kann mehrere Identitäten haben, also kann eine Person sowohl ein Passwort\nals auch Google haben. Ob überhaupt ein Passwort gespeichert ist, steht in der\nSpalte, die der Server selbst prüft.",[10,162,163,164,167],{},"Öffne den ",[31,165,166],{},"SQL Editor"," in deinem Supabase-Dashboard und führ das mit der\nAdresse aus, die dir die Person genannt hat:",[14,169,172],{"className":170,"code":171,"language":19},[17],"select email,\n       raw_app_meta_data->'providers' as signs_in_with,\n       coalesce(encrypted_password, '') \u003C> '' as has_password,\n       email_confirmed_at\nfrom auth.users\nwhere lower(email) = lower('person@example.com');\n",[21,173,171],{"__ignoreMap":23},[10,175,176],{},"Die Abfrage liest eine Zeile und zeigt nie ein Passwort, nur ob es eins gibt.",[178,179,180,193],"table",{},[181,182,183],"thead",{},[184,185,186,190],"tr",{},[187,188,189],"th",{},"Was zurückkommt",[187,191,192],{},"Was es bedeutet",[194,195,196,205,232,244],"tbody",{},[184,197,198,202],{},[199,200,201],"td",{},"Keine Zeile",[199,203,204],{},"In diesem Projekt hat kein Konto diese Adresse. Frag, welche andere Adresse die Person benutzt haben könnte",[184,206,207,229],{},[199,208,209,212,213,216,217,220,221,224,225,228],{},[21,210,211],{},"has_password"," ist ",[21,214,215],{},"false",", und ",[21,218,219],{},"signs_in_with"," nennt ",[21,222,223],{},"google",", ",[21,226,227],{},"github"," oder Ähnliches",[199,230,231],{},"Die Person hat sich mit diesem Knopf registriert und nie ein Passwort gehabt",[184,233,234,241],{},[199,235,236,212,238],{},[21,237,211],{},[21,239,240],{},"true",[199,242,243],{},"Das eingegebene Passwort ist falsch, oder die Person hat sich per Magic Link registriert und kennt ihres nicht",[184,245,246,252],{},[199,247,248,251],{},[21,249,250],{},"email_confirmed_at"," ist leer",[199,253,254],{},"Die E-Mail ist noch nicht bestätigt, was eine andere Meldung ergibt, sobald das Passwort stimmt",[10,256,257,258,261],{},"Wenn du lieber klickst als tippst, listet ",[31,259,260],{},"Authentication → Users"," im\nDashboard dieselben Konten.",[36,263,265],{"id":264},"das-konto-das-nie-ein-passwort-hatte","Das Konto, das nie ein Passwort hatte",[10,267,268],{},"Schick die Person zurück zu dem Knopf, den sie benutzt hat, oder lass sie über\ndeinen Link zum Zurücksetzen ein Passwort setzen.",[10,270,271],{},"Am Tastenfeld ist das der Bewohner, der immer die Seitentür genommen hat. Für ihn\nist kein Code hinterlegt, also wird jeder Code abgelehnt, den er probiert.",[10,273,274],{},"Die erste Reparatur liegt auf deiner Anmeldeseite. Wenn die Registrierung \"Mit\nGoogle fortfahren\" anbietet, braucht die Anmeldeseite denselben Knopf, damit\njemand, der sich damit registriert hat, ihn sieht, wenn er zurückkommt.",[10,276,277,278,283,284,287],{},"Möchte die Person zusätzlich ein Passwort, erledigt das dein Link \"Passwort\nvergessen?\" schon. Supabases\n",[47,279,282],{"href":280,"rel":281},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Frecover.go",[51],"Code zum Zurücksetzen des Passworts","\nschickt die Wiederherstellungs-E-Mail an jedes Konto, das er findet, ohne zu\nprüfen, wie das Konto entstanden ist. Ein Google-Nutzer, der dem Link folgt und\nein neues Passwort setzt, kann sich danach auf beide Arten anmelden. Das setzt\nvoraus, dass deine App die Seite hat, die das neue Passwort setzt, also\n",[21,285,286],{},"supabase.auth.updateUser({ password })"," aufruft. Landet der Link auf einer\nSeite, die nie nach einem fragt, ist die Person einmal angemeldet und hat\nweiterhin kein Passwort.",[36,289,291],{"id":290},"email-not-confirmed-heißt-das-passwort-war-richtig","\"Email not confirmed\" heißt, das Passwort war richtig",[10,293,294],{},"Es ist eine andere Meldung mit einem anderen Code, und sie erreicht nur jemanden,\nder die Passwortprüfung schon bestanden hat.",[10,296,297,298,301,302,305],{},"In derselben Funktion des Auth-Servers kommt die Prüfung auf eine bestätigte\nE-Mail nach der Passwortprüfung. ",[21,299,300],{},"Email not confirmed",", Code\n",[21,303,304],{},"email_not_confirmed",", geht also nur an jemanden, der eine existierende E-Mail\nund ihr richtiges Passwort eingegeben hat. Supabases Fehlerreferenz formuliert es\nals \"Signing in is not allowed for this user as the email address is not\nconfirmed.\" Am Tastenfeld ist das eine andere Lampe: Der Code war richtig, und\ndie Tür bleibt zu, bis der Papierkram für den Einzug erledigt ist.",[10,307,308,309,312,313,318,319,322,323,327,328,93],{},"Du siehst sie, wenn ",[31,310,311],{},"Confirm email"," beim Email-Anbieter deines Projekts\neingeschaltet ist. Laut Supabases\n",[47,314,317],{"href":315,"rel":316},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fgeneral-configuration",[51],"Konfigurationsleitfaden","\nmüssen Nutzer dann ihre E-Mail-Adresse bestätigen, bevor sie sich zum ersten Mal\nanmelden. Die Lösung ist die E-Mail, die noch nicht angeklickt wurde: Sag der\nPerson, dass sie Posteingang und Spam-Ordner prüfen soll, und biete an, sie mit\n",[21,320,321],{},"supabase.auth.resend({ type: 'signup', email })"," erneut zu schicken. Kommen\ndiese E-Mails gar nicht an, ist\n",[47,324,326],{"href":325},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","das E-Mail-Limit"," das Erste, was du\nausschließen solltest. Kommen sie an und der Link sagt dann \"Email link is\ninvalid or has expired\",\n",[47,329,331],{"href":330},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","hat ihn wahrscheinlich etwas vor der Person geöffnet",[10,333,334],{},"Weil diese Meldung erst nach einem richtigen Passwort erscheint, gibt der\nHinweis auf das Postfach einem Fremden nichts, was er nicht schon hatte.",[36,336,338],{"id":337},"warum-die-meldung-vage-bleibt","Warum die Meldung vage bleibt",[10,340,341],{},"Weil die hilfreiche Version Fremden verraten würde, wer deine Nutzer sind.",[10,343,344],{},"Stell dir vor, das Tastenfeld würde antworten \"In Wohnung 4B wohnt niemand\". Wer\nvorbeigeht, könnte die Liste der Wohnungen durchgehen und erfahren, welche\nbewohnt sind.",[10,346,347],{},"Dein Formular funktioniert genauso. Würde es \"Kein Konto mit dieser E-Mail\"\nsagen, könnte jeder mit einer Liste von Adressen jede einzeln eintippen und\nerfahren, welche deinen Nutzern gehören. Ein Datenleck bei irgendeiner anderen\nWebsite hinterlässt so eine Liste, manchmal mit den Passwörtern, die die Leute\ndort benutzt haben. Wer weiß, welche Adressen deine Nutzer sind, weiß, wessen\nalte Passwörter es sich lohnt, in deiner App zu probieren, und wer eine E-Mail\nöffnen dürfte, die aussieht, als käme sie von dir.",[10,349,350,351,356],{},"Supabase wendet dieselbe Regel überall an, wo eine Adresse eingegeben wird. Sein\n",[47,352,355],{"href":353,"rel":354},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Fsignup.go",[51],"Registrierungscode","\nkann, wenn er ein Konto für eine schon registrierte und bestätigte E-Mail\nanlegen soll, einen erfundenen Nutzer mit zufälliger ID zurückgeben, über eine\nFunktion, deren Kommentar sagt, sie solle verhindern, dass nach außen dringt, ob\nein Nutzer registriert ist. Das Zurücksetzen des Passworts beantwortet eine\nunbekannte Adresse mit demselben leeren Erfolg wie eine bekannte.",[10,358,359,360,363,364,367],{},"Auf der Seite der Registrierung gibt es einen Schalter, den du kontrollierst.\nDer erfundene Nutzer kommt zurück, wenn die Bestätigung sowohl für E-Mail- als\nauch für Telefon-Registrierungen verlangt wird. Ist eine der beiden\nausgeschaltet (die für Telefon zählt auch dann, wenn deine App nie eine\nAnmeldung per Telefon nutzt), bekommt eine registrierte Adresse\n",[21,361,362],{},"User already registered",", Code ",[21,365,366],{},"user_already_exists",", und dein\nRegistrierungsformular wird selbst zum Listenprüfer.",[10,369,370,371,374,375,377],{},"Die hilfreiche Meldung muss außerdem irgendwoher kommen. Supabase sagt deiner App\nnicht, ob eine E-Mail ein Konto hat, also muss deine App es selbst herausfinden,\num \"Kein Konto mit dieser E-Mail\" anzuzeigen. Das heißt eine Abfrage, die für\neinen nicht angemeldeten Besucher funktioniert: ein Lesen deiner Tabelle\n",[21,372,373],{},"profiles",", das nur gelingt, wenn jeder die E-Mails darin lesen kann, oder eine\nDatenbankfunktion, die ",[21,376,146],{}," für jeden durchsucht, der fragt. So oder so\nwird die Liste deiner Nutzer von außen lesbar.",[10,379,380,381,93],{},"Das Erste davon lässt sich von außen sehen, und genau so sucht unser kostenloser\nScan danach. Er fragt jede Tabelle, die deine App nennt, wie viele Zeilen ein\nBesucher ohne Login bekommen könnte, liest nur die Anzahl und braucht etwa 20\nSekunden, ohne Konto: ",[47,382,384],{"href":383},"\u002Fsecurity-scanner","scanne deine App",[132,386],{"alt":387,"caption":388,"src":389},"Ein Stapel E-Mail-Adressen läuft durch zwei Anmeldeformulare. Das obere Formular nennt fehlende Konten, und der Stapel kommt in zwei Haufen geteilt heraus, einer abgehakt und einer durchgestrichen, der abgehakte gelb markiert. Das untere Formular gibt jeder Adresse dieselbe Antwort, und der Stapel kommt als ein gleichmäßiger Haufen heraus.","Ein Formular, das ein fehlendes Konto nennt, sortiert jede Adressliste in deine Nutzer und alle anderen. Eine Antwort für alle lässt die Liste, wie sie war.","\u002Fblog\u002Fsupabase-invalid-login\u002Fthe-list-checker-1600x720.png",[36,391,393],{"id":392},"was-stattdessen-auf-deine-anmeldeseite-gehört","Was stattdessen auf deine Anmeldeseite gehört",[10,395,396],{},"Lass die Meldung vage und biete jeden Weg zurück auf derselben Seite an.",[398,399,400,407,413,419],"ul",{},[401,402,403,406],"li",{},[31,404,405],{},"Eine Meldung für alle drei Fälle",", in einfachen Worten, mit den anderen\nWegen daneben: \"E-Mail und Passwort passen nicht zusammen. Wenn du dich mit\nGoogle registriert hast, nutze den Knopf unten.\" Sie hilft dem Google-Nutzer\nund verrät einem Fremden nichts, was deine Registrierungsseite nicht auch\nzeigt.",[401,408,409,412],{},[31,410,411],{},"Jede Methode deiner Registrierungsseite."," Der Google-Knopf, der Magic Link\nund das Passwortfeld, alle auch auf der Anmeldeseite.",[401,414,415,418],{},[31,416,417],{},"Ein Link \"Passwort vergessen?\" zu einer Seite, die eins setzt."," Supabase\nbeantwortet dort jede Adresse gleich, also kann er sichtbar sein, und so\nkommt eine Person ohne Passwort zu einem.",[401,420,421,426,427,429,430,432],{},[31,422,423,424,93],{},"Entscheidungen nach ",[21,425,77],{}," Zeig deine vage Meldung bei\n",[21,428,56],{}," und \"Prüf dein Postfach\" mit einem Knopf zum erneuten\nSenden bei ",[21,431,304],{},". Supabases Fehlerreferenz sagt, Fehler am\nCode statt am Meldungstext zu erkennen, und warnt, dass sich HTTP-Statuscodes\nunerwartet ändern können.",[10,434,435],{},"Im Code sind das zwei Zweige:",[14,437,440],{"className":438,"code":439,"language":19},[17],"const { error } = await supabase.auth.signInWithPassword({ email, password })\nif (error?.code === 'email_not_confirmed') showCheckYourInbox(email)\nelse if (error) showSignInHelp()\n",[21,441,439],{"__ignoreMap":23},[10,443,444],{},"Wenn ein Builder deine Anmeldeseite schreibt, kannst du diese vier Punkte als\nAnweisung einfügen, auch den darüber, was die Seite für sich behalten muss.",[36,446,448],{"id":447},"damit-deine-anmeldeseite-so-bleibt-wie-du-sie-verlassen-hast","Damit deine Anmeldeseite so bleibt, wie du sie verlassen hast",[10,450,451],{},"Zwei Dinge können nach heute noch schiefgehen: Ein späterer Prompt schreibt die\nSeite \"hilfreicher\" um, und eine Änderung an anderer Stelle verliert die Konten,\nin die die Seite Leute einloggt.",[10,453,454],{},[31,455,456,460],{},[47,457,459],{"href":458},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft weiter von außen:",[398,462,463,466,469,472],{},[401,464,465],{},"alle neun Prüfungen jede Stunde, für bis zu drei Apps, darunter, wie viele Zeilen ein Besucher ohne Login in den Tabellen zählen kann, die deine App nennt",[401,467,468],{},"eine E-Mail an dem Tag, an dem ein erneuter Scan deine App schlechter benotet als der vorige",[401,470,471],{},"ob die App erreichbar ist, alle 60 Sekunden",[401,473,474],{},"ein monatlicher Bericht in einfacher Sprache über das, was er gesehen hat",[10,476,477],{},[31,478,479,483],{},[47,480,482],{"href":481},"\u002Fsupabase-backups","Reeve Care"," hält eine Kopie deiner Supabase-Datenbank,\nsamt Konten:",[398,485,486,489,492,495,498,501],{},[401,487,488],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[401,490,491],{},"das Auth-Schema, in dem die Konten deiner Nutzer liegen, damit sie mit allem anderen zurückkommen",[401,493,494],{},"jede Kopie geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[401,496,497],{},"auch deine hochgeladenen Dateien, sobald du einen Storage-Zugang verbindest",[401,499,500],{},"eine Wiederherstellung per Klick, mit einer Sicherheitskopie des aktuellen Stands vorab",[401,502,503],{},"alles, was Monitor tut",[36,505,507],{"id":506},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[509,510,511],"key-takeaways",{},[398,512,513,519,522,525,528,536],{},[401,514,515,516,518],{},"Führ die Abfrage auf ",[21,517,146],{}," mit der Adresse aus, die dir die Person genannt hat, und lies ab, welcher der drei Fälle es ist.",[401,520,521],{},"Keine Zeile: Frag, mit welcher anderen Adresse sich die Person registriert haben könnte.",[401,523,524],{},"Kein Passwort: Verweis sie auf den Google- oder GitHub-Knopf, den sie benutzt hat, oder auf deinen Link zum Zurücksetzen.",[401,526,527],{},"Ein Passwort, und trotzdem abgelehnt: Schick ihr den Link zum Zurücksetzen.",[401,529,530,531,533,534,93],{},"Zeig eine vage Meldung bei ",[21,532,56],{}," und \"Prüf dein Postfach\" nur bei ",[21,535,304],{},[401,537,538],{},"Bau nie eine Prüfung ein, die einem Besucher sagt, ob eine E-Mail ein Konto hat.",[10,540,541,542,546,547,551],{},"Wenn das Problem einen Schritt früher beginnt und neue Konten gar nicht erst\nangelegt werden, deckt\n",[47,543,545],{"href":544},"\u002Fblog\u002Fdatabase-error-saving-new-user","Database error saving new user"," dieses\nEnde des Formulars ab. Die ",[47,548,550],{"href":549},"\u002Fchecklist","10-Minuten-Sicherheits-Checkliste"," deckt\nab, was in einer frisch gestarteten App sonst oft offen bleibt.",{"title":23,"searchDepth":553,"depth":553,"links":554},3,[555,557,558,559,560,561,562,563,564],{"id":38,"depth":556,"text":39},2,{"id":99,"depth":556,"text":100},{"id":139,"depth":556,"text":140},{"id":264,"depth":556,"text":265},{"id":290,"depth":556,"text":291},{"id":337,"depth":556,"text":338},{"id":392,"depth":556,"text":393},{"id":447,"depth":556,"text":448},{"id":506,"depth":556,"text":507},"Sicherheitsgrundlagen","\u002Fblog\u002Fsupabase-invalid-login\u002Fcover-1200x630.png","Ein Tastenfeld neben einer Tür, dessen einzige Lampe rot leuchtet, und davor ein Ausweis, für den das Tastenfeld keinen Schlitz hat.","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.",false,"md",[572,575,578,581,584],{"q":573,"a":574},"Warum sagt Supabase \"Invalid login credentials\", obwohl das Passwort stimmt?","Weil das Passwort vielleicht zu einem Konto gehört, das es nicht gibt, oder das Konto gar kein Passwort hat. Prüf, ob die E-Mail die ist, mit der sich die Person registriert hat, und ob sie sich mit Google oder einem anderen Anmeldeknopf registriert hat, denn dann hat das Konto kein Passwort. Eine Abfrage auf auth.users im SQL Editor zeigt, welcher Fall es ist.",{"q":576,"a":577},"Heißt \"Invalid login credentials\", dass das Konto nicht existiert?","Manchmal. Supabase gibt dieselbe Meldung mit demselben Code, invalid_credentials, zurück, wenn kein Konto diese E-Mail hat, wenn das Konto kein Passwort hat und wenn das Passwort falsch ist. Die Meldung allein sagt dir nicht, welcher Fall es ist, und so ist sie gebaut.",{"q":579,"a":580},"Warum kann sich jemand, der sich mit Google registriert hat, nicht mit Passwort anmelden?","Weil sein Konto ohne Passwort angelegt wurde. Supabase prüft, ob überhaupt ein Passwort gespeichert ist, bevor es das eingegebene vergleicht, und ein Konto ohne bekommt \"Invalid login credentials\". Die Person kann weiter den Google-Knopf nutzen oder über den Link zum Zurücksetzen deiner App ein Passwort setzen: Supabase schickt diese E-Mail an jedes Konto, das es findet, egal wie es entstanden ist.",{"q":582,"a":583},"Soll mein Anmeldeformular sagen, dass die E-Mail nicht registriert ist?","Nein. Diese Meldung verrät jedem, der eine Adresse eintippt, ob sie einem deiner Nutzer gehört, und wer eine Liste geleakter Adressen hat, kann alle prüfen. Deine App bräuchte außerdem eine Abfrage, die Fremden diese Frage beantwortet, und das ist ein zweites Loch. Lass die Meldung vage und zeig die anderen Wege zur Anmeldung.",{"q":585,"a":586},"Was ist der Unterschied zwischen \"Invalid login credentials\" und \"Email not confirmed\"?","Supabase gibt \"Email not confirmed\" erst zurück, nachdem das Passwort geprüft und für richtig befunden wurde. Die richtige Person hat also das richtige Passwort eingegeben, und das Konto wartet darauf, dass sie den Link in ihrer Bestätigungs-E-Mail anklickt. Es ist sicher, ihr zu sagen, dass sie ihr Postfach prüfen soll, und anzubieten, die E-Mail erneut zu schicken.","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",[589,590,591,592,56,593,594],"invalid login credentials supabase","invalid login credentials","supabase login funktioniert nicht","email not confirmed supabase","supabase user enumeration","supabase google nutzer kein passwort",{},true,"\"Invalid login credentials\" in Supabase","\u002Fblog\u002Fsupabase-invalid-login","2026-10-28",{"title":5,"description":568},"blog\u002Fsupabase-invalid-login",[603,604,605],"Supabase antwortet \"Invalid login credentials\" drei verschiedenen Menschen: jemandem mit falschem Passwort, jemandem, dessen E-Mail kein Konto hat, und jemandem, der sich mit Google registriert und nie ein Passwort hatte.","Das ist Absicht. Ein Anmeldeformular, das sagt, welcher der drei Fälle es war, verrät jedem mit einer Liste von E-Mail-Adressen, welche davon deinen Nutzern gehören.","Du kannst die drei selbst unterscheiden, mit einer Abfrage auf auth.users. Deine Anmeldeseite sollte die Meldung vage lassen und jeden Weg anbieten, auf dem das Konto entstanden sein kann.","sN7ebkkuj6Ln-eChSAG6Qnmpg31vAUYMzuRb_-a-YLI",[608,614,620,626,632,638,644,650,656,661,667,674,680,681,687,693,699,705,711,717,723,728,733,739,745,751,757,762,768,774,780,786,792,798,804,810,816,822,828,834,840,846,852,858,864,870,875,881,887,893,899,905,911,917,923,929,935,941,947,953,959,965,971,977,983,989,995,1001,1007,1013,1019,1025,1031,1037,1043,1049,1055,1061,1067,1073,1079,1085,1091,1097,1102,1108,1114,1120,1125,1131],{"path":609,"title":610,"description":611,"published":612,"category":565,"image":613,"draft":569},"\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":615,"title":616,"description":617,"published":618,"category":565,"image":619,"draft":569},"\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":621,"title":622,"description":623,"published":624,"category":565,"image":625,"draft":569},"\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":627,"title":628,"description":629,"published":630,"category":565,"image":631,"draft":569},"\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":633,"title":634,"description":635,"published":636,"category":565,"image":637,"draft":569},"\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":639,"title":640,"description":641,"published":642,"category":565,"image":643,"draft":569},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","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":645,"title":646,"description":647,"published":648,"category":565,"image":649,"draft":569},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"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":651,"title":652,"description":653,"published":654,"category":565,"image":655,"draft":569},"\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":330,"title":657,"description":658,"published":659,"category":565,"image":660,"draft":569},"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":662,"title":663,"description":664,"published":665,"category":565,"image":666,"draft":569},"\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":668,"title":669,"description":670,"published":671,"category":672,"image":673,"draft":569},"\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":675,"title":676,"description":677,"published":678,"category":565,"image":679,"draft":569},"\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":598,"title":5,"description":568,"published":599,"category":565,"image":587,"draft":569},{"path":682,"title":683,"description":684,"published":685,"category":565,"image":686,"draft":569},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":688,"title":689,"description":690,"published":691,"category":565,"image":692,"draft":569},"\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":694,"title":695,"description":696,"published":697,"category":565,"image":698,"draft":569},"\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":700,"title":701,"description":702,"published":703,"category":565,"image":704,"draft":569},"\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":706,"title":707,"description":708,"published":709,"category":565,"image":710,"draft":569},"\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":712,"title":713,"description":714,"published":715,"category":565,"image":716,"draft":569},"\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":718,"title":719,"description":720,"published":721,"category":565,"image":722,"draft":569},"\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":325,"title":724,"description":725,"published":726,"category":565,"image":727,"draft":569},"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":91,"title":729,"description":730,"published":731,"category":565,"image":732,"draft":569},"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":734,"title":735,"description":736,"published":737,"category":565,"image":738,"draft":569},"\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":740,"title":741,"description":742,"published":743,"category":565,"image":744,"draft":569},"\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":746,"title":747,"description":748,"published":749,"category":565,"image":750,"draft":569},"\u002Fblog\u002Fsupabase-invalid-jwt","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":752,"title":753,"description":754,"published":755,"category":565,"image":756,"draft":569},"\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":544,"title":758,"description":759,"published":760,"category":565,"image":761,"draft":569},"\"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":763,"title":764,"description":765,"published":766,"category":565,"image":767,"draft":569},"\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":769,"title":770,"description":771,"published":772,"category":565,"image":773,"draft":569},"\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":775,"title":776,"description":777,"published":778,"category":565,"image":779,"draft":569},"\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":781,"title":782,"description":783,"published":784,"category":565,"image":785,"draft":569},"\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":787,"title":788,"description":789,"published":790,"category":565,"image":791,"draft":569},"\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":793,"title":794,"description":795,"published":796,"category":565,"image":797,"draft":569},"\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":799,"title":800,"description":801,"published":802,"category":565,"image":803,"draft":569},"\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":805,"title":806,"description":807,"published":808,"category":565,"image":809,"draft":569},"\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":811,"title":812,"description":813,"published":814,"category":565,"image":815,"draft":569},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","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":817,"title":818,"description":819,"published":820,"category":565,"image":821,"draft":569},"\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":823,"title":824,"description":825,"published":826,"category":565,"image":827,"draft":569},"\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":829,"title":830,"description":831,"published":832,"category":565,"image":833,"draft":569},"\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":835,"title":836,"description":837,"published":838,"category":565,"image":839,"draft":569},"\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":841,"title":842,"description":843,"published":844,"category":565,"image":845,"draft":569},"\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":847,"title":848,"description":849,"published":850,"category":565,"image":851,"draft":569},"\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":853,"title":854,"description":855,"published":856,"category":672,"image":857,"draft":569},"\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":859,"title":860,"description":861,"published":862,"category":672,"image":863,"draft":569},"\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":865,"title":866,"description":867,"published":868,"category":672,"image":869,"draft":569},"\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":871,"title":872,"description":873,"published":868,"category":565,"image":874,"draft":569},"\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":876,"title":877,"description":878,"published":879,"category":565,"image":880,"draft":569},"\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":882,"title":883,"description":884,"published":885,"category":565,"image":886,"draft":569},"\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":888,"title":889,"description":890,"published":891,"category":672,"image":892,"draft":569},"\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":894,"title":895,"description":896,"published":897,"category":565,"image":898,"draft":569},"\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":900,"title":901,"description":902,"published":903,"category":565,"image":904,"draft":569},"\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":906,"title":907,"description":908,"published":909,"category":565,"image":910,"draft":569},"\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":912,"title":913,"description":914,"published":915,"category":565,"image":916,"draft":569},"\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":918,"title":919,"description":920,"published":921,"category":565,"image":922,"draft":569},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":924,"title":925,"description":926,"published":927,"category":565,"image":928,"draft":569},"\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":930,"title":931,"description":932,"published":933,"category":565,"image":934,"draft":569},"\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":936,"title":937,"description":938,"published":939,"category":565,"image":940,"draft":569},"\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":942,"title":943,"description":944,"published":945,"category":672,"image":946,"draft":569},"\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":948,"title":949,"description":950,"published":951,"category":672,"image":952,"draft":569},"\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":954,"title":955,"description":956,"published":957,"category":672,"image":958,"draft":569},"\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":960,"title":961,"description":962,"published":963,"category":565,"image":964,"draft":569},"\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":966,"title":967,"description":968,"published":969,"category":565,"image":970,"draft":569},"\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":972,"title":973,"description":974,"published":975,"category":565,"image":976,"draft":569},"\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":978,"title":979,"description":980,"published":981,"category":565,"image":982,"draft":569},"\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":984,"title":985,"description":986,"published":987,"category":565,"image":988,"draft":569},"\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":990,"title":991,"description":992,"published":993,"category":565,"image":994,"draft":569},"\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":996,"title":997,"description":998,"published":999,"category":565,"image":1000,"draft":569},"\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":1002,"title":1003,"description":1004,"published":1005,"category":565,"image":1006,"draft":569},"\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":1008,"title":1009,"description":1010,"published":1011,"category":565,"image":1012,"draft":569},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","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":1014,"title":1015,"description":1016,"published":1017,"category":565,"image":1018,"draft":569},"\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":1020,"title":1021,"description":1022,"published":1023,"category":672,"image":1024,"draft":569},"\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":1026,"title":1027,"description":1028,"published":1029,"category":565,"image":1030,"draft":569},"\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":1032,"title":1033,"description":1034,"published":1035,"category":672,"image":1036,"draft":569},"\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":1038,"title":1039,"description":1040,"published":1041,"category":565,"image":1042,"draft":569},"\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":1044,"title":1045,"description":1046,"published":1047,"category":565,"image":1048,"draft":569},"\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":1050,"title":1051,"description":1052,"published":1053,"category":565,"image":1054,"draft":569},"\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":1056,"title":1057,"description":1058,"published":1059,"category":565,"image":1060,"draft":569},"\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":1062,"title":1063,"description":1064,"published":1065,"category":672,"image":1066,"draft":569},"\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":1068,"title":1069,"description":1070,"published":1071,"category":672,"image":1072,"draft":569},"\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":1074,"title":1075,"description":1076,"published":1077,"category":565,"image":1078,"draft":569},"\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":1080,"title":1081,"description":1082,"published":1083,"category":565,"image":1084,"draft":569},"\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":1086,"title":1087,"description":1088,"published":1089,"category":672,"image":1090,"draft":569},"\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":1092,"title":1093,"description":1094,"published":1095,"category":565,"image":1096,"draft":569},"\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":1098,"title":1099,"description":1100,"published":1095,"category":565,"image":1101,"draft":569},"\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":1103,"title":1104,"description":1105,"published":1106,"category":565,"image":1107,"draft":569},"\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":1109,"title":1110,"description":1111,"published":1112,"category":672,"image":1113,"draft":569},"\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":1115,"title":1116,"description":1117,"published":1118,"category":565,"image":1119,"draft":569},"\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":1121,"title":1122,"description":1123,"published":1118,"category":672,"image":1124,"draft":569},"\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":1126,"title":1127,"description":1128,"published":1129,"category":672,"image":1130,"draft":569},"\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":1132,"title":1133,"description":1134,"published":1129,"category":565,"image":1135,"draft":569},"\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",1794213638704]