Zum Inhalt springen

Sicherheitsgrundlagen

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.

Vlad Tkachenko7 Min. Lesezeit
Eine Seite App-Code mit acht hervorgehobenen schlüsselförmigen Werten, die meisten unauffällig, einer in Rot.

Kurz gesagt

  • Ein API-Schlüssel im Frontend ist fast immer die harmlose Sorte. Wir fanden einen nennenswerten Schlüssel in 1.332 von 30.998 Apps, und 1.080 davon trugen nur einen Google-API-Schlüssel.
  • Der Supabase-Schlüssel service_role, vor dem jedes Tutorial warnt, tauchte in 3 von 30.998 Apps auf. Ein geheimer Stripe-Schlüssel ebenfalls in 3.
  • Schlüssel, die schon ihrer Form nach Geld ausgeben oder Daten lesen, fanden sich in 54 Apps. Eine offene Supabase-Tabelle fand sich in 2.096.

Jemand öffnet deine App, drückt F12 und sagt dir, dass ein API-Schlüssel in deinem Frontend offenliegt. Das Wort dafür ist meistens „geleakt". Welcher Schlüssel es ist, sagt kaum jemand dazu, und die Ratgeber, die du danach findest, behandeln alle als denselben Notfall.

Es ist nicht derselbe Notfall, und wir können den Abstand inzwischen beziffern. Zwischen dem 12. und 14. August 2026 haben wir neun externe Prüfungen über 30.998 live erreichbare Apps laufen lassen, gebaut mit Lovable, Bolt, v0, Replit und Base44, und das JavaScript gelesen, das jede davon an einen Browser ausliefert. Das war darin.

Ist ein API-Schlüssel im Frontend wirklich ein Problem?

Meistens nicht, und die Verteilung dieses „meistens" ist schiefer, als wir erwartet hatten.

Wir fanden einen nennenswerten Schlüssel in 1.332 der 30.998 Apps. In 1.080 davon war das Einzige, was wir fanden, ein Google-API-Schlüssel, also genau die Zugangsdaten, die in deiner Seite stehen sollen. Was diesen einen schützt, ist eine Einstellung auf Googles Seite, und Verstecken war nie Teil der Abmachung.

Die übrigen 29.666 Apps lieferten nichts aus, was unsere Geheimnis-Prüfung als Problem behandelt. Diese Zahl braucht eine Einschränkung, um ehrlich zu sein. Veröffentlichbare Schlüssel sind darin nicht enthalten: Ein Supabase-anon- oder ein Stripe-pk_-Schlüssel gehört in den Browser, wir markieren ihn also als etwas, das du richtig gemacht hast, und er geht in diese Zählung nie ein.

Was wir gezählt haben und was nicht

Wir haben jede App so geladen, wie ein Besucher es tut, in einem echten Browser, und das heruntergeladene JavaScript gelesen. Alles Folgende ist eine Form, die in diesem Code stand.

Wir erkennen Schlüsselformate, die wir kennen. Stripe, OpenAI, Anthropic, AWS, Google und Supabase haben erkennbare Präfixe, und ein Supabase-JWT nennt seine eigene Rolle im mittleren Abschnitt als lesbaren Text. Zugangsdaten in einem Format, das wir nicht kennen, stehen nicht in diesen Zahlen, lies sie also als Untergrenze.

Wir haben keinen gefundenen Schlüssel benutzt. Kein einziges Mal, bei keiner App. Wir haben den Typ und einen maskierten Hinweis der Form sk_live_…a1b2 notiert, und der echte Wert wurde nirgends aufgeschrieben.

Keine App wird genannt. Nicht hier, nicht im Datensatz, nirgends, wo wir veröffentlichen.

Fast alle davon sind Apps auf der Publish-Domain eines Builders. Die vollständige Methode, die Stichprobe und jede Zahl hinter diesem Artikel stehen in unserem Scan-Bericht, einschließlich dessen, was wir nicht messen konnten.

Was die 30.998 Apps tatsächlich auslieferten

Eine Tabelle, sortiert danach, wie oft wir das Jeweilige gesehen haben. Die Geheimnis-Prüfung wurde bei allen 30.998 Apps abgeschlossen, jede Zahl unten bezieht sich also auf alle.

Was wir im Browser-Code gefunden habenApps
Google-API-Schlüssel1.142
Ein Wert mit hoher Entropie neben einem Namen wie „secret"204
OpenAI-Schlüssel33
AWS-Zugriffsschlüssel9
Anthropic-Schlüssel5
Supabase-service_role-Schlüssel3
Geheimer Stripe-Schlüssel3
Eingeschränkter Stripe-Schlüssel2

Die Zeilen ergeben zusammen mehr als 1.332, weil eine App zwei davon tragen kann. Sortiert man dieselben 1.332 Apps in Gruppen, die sich nicht überschneiden, wird das Bild noch deutlicher: 1.080 hatten einen Google-Schlüssel und sonst nichts, 198 hatten einen Wert mit hoher Entropie, der echte Zugangsdaten sein kann oder auch nicht, und 54 hatten einen Schlüssel, der schon seiner Form nach ein echtes Geheimnis ist.

Jede App, in der wir überhaupt einen Schlüssel fanden, sortiert in drei Gruppen ohne Überschneidung. Der rote Abschnitt ist der, um den es in den Warnungen geht.

Die zweite Gruppe verdient eine genaue Beschreibung. Ein Wert mit hoher Entropie neben einem Wort wie secret oder password kann echte Zugangsdaten sein, er kann aber auch eine Sitzungskennung sein, ein Build-Hash oder ein öffentliches Token mit einem unglücklichen Namen. Wir melden das als nachsehenswert, und von außen kann niemand dir sagen, was davon es ist.

Die 54 in der dritten Gruppe sind die echte Sache. Alle bis auf zwei bekamen die Note D oder F, weil ein einziger kritischer Fund die Note bei D deckelt, egal was die App sonst richtig gemacht hat. Die größte einzelne Gruppe darin ist der OpenAI-Schlüssel mit 33, und für den gibt es keine Einstellung, die ihn im Browser unbedenklich machen würde.

Der Schlüssel, vor dem alle warnen, war der seltenste Fund

Drei Apps. So viele lieferten einen Supabase-service_role-Schlüssel aus, also den, der an jeder Tabellenregel vorbeigeht, die du geschrieben hast. Ein geheimer Stripe-Schlüssel tauchte ebenfalls dreimal auf.

Stell das neben die andere Hälfte desselben Durchlaufs. Von den gescannten Apps nannten 8.429 ein Supabase-Projekt, und beide Funde liegen innerhalb dieser einen Gruppe. Drei davon lieferten den service_role-Schlüssel aus. In 2.096 davon antwortete mindestens eine Tabelle auf eine Anfrage ganz ohne Login, und in 394 trug diese Tabelle einen Namen für Menschen: users, profiles, customers, orders.

Beide Zahlen stammen aus denselben 8.429 Supabase-Apps. Die obere Zeile ist der Fund, vor dem Betreiber gewarnt werden.

Die 2.096 sind eine Untergrenze. 4.749 der 8.429 haben unsere Datenbankprüfung nie beantwortet, aus Gründen, die wir von außen nicht sehen, und die notieren wir als unbekannt statt als sauber. Die drei service_role-Schlüssel sind eine exakte Zahl, weil ein Schlüssel aus Code gelesen wird, den jede App herausgibt.

Warum die Warnungen auf den falschen Schlüssel zeigen

Wir sehen nur die Außenseite dieser Apps, wir können dir also nicht sagen, warum. Zeigen können wir, welcher Fehler überlebt.

Den falschen Supabase-Schlüssel zu kopieren ist wirklich leicht. In einem älteren Projekt stehen anon und service_role nebeneinander im selben Dashboard-Bereich, sie sind gleich lang und gleich geformt, und es geht nichts kaputt, wenn du den falschen nimmst. Trotzdem passierte es nur dreimal in 30.998 Apps, weil dich nichts dorthin drängt. Beide Schlüssel bringen die App zum Laufen.

Hinter der offenen Tabelle steht eine Kraft. Row Level Security wird angeschaltet, die App zeigt keine Daten mehr, eine Policy, die alle erlaubt, wird geschrieben, damit es wieder geht, und von diesem Moment an meldet das Dashboard die Tabelle als geschützt. Anschalten ist nicht dasselbe wie geschützt sein. Unser Scan bewertet diese Tabelle als kritischen Fund an einem Tag, an dem dein Dashboard dir den Schalter auf an und eine vorhandene Policy zeigt.

Wie du einen offenliegenden API-Schlüssel kostenlos findest

Fang von Hand an, das kostet fünf Minuten und braucht nichts Installiertes. Öffne deine Live-Seite, sieh dir den Seitenquelltext an und suche nach vier Zeichenfolgen: AIza für einen Google-Schlüssel, sk_ für ein Stripe- oder Modellanbieter-Geheimnis, service_role für den Supabase-Schlüssel, der deine Regeln ignoriert, und eyJ für jedes Supabase-Token. Alles, was zurückkommt, liegt bereits in den Händen jedes Besuchers, den du hast.

Damit hast du die Seite selbst. Was dabei fehlt, ist das JavaScript, das die Seite danach nachlädt, und genau deshalb öffnet unser eigener Scanner eine App in einem echten Browser und liest die Bundles statt des HTML. Die Suche von Hand kann dir außerdem nicht sagen, ob das gefundene eyJ-Token der anon-Schlüssel oder der geheime ist, denn die beiden sind gleich lang und gleich geformt.

Unser kostenloser Scan deckt beides ab. Er lädt deine App in einem echten Browser, liest den Code, der tatsächlich ankommt, dekodiert jedes Supabase-Token und meldet die darin geschriebene Rolle, sodass ein veröffentlichbarer Schlüssel als korrekt markiert zurückkommt und nicht in einer Wand aus Rot verschwindet. Note, Punktzahl und die Anzahlen stehen nach etwa 20 Sekunden ohne Konto auf dem Bildschirm. Gib eine E-Mail-Adresse an, und du bekommst zusätzlich die ausführliche Liste, mit einer Lösung für deinen Builder, die du direkt einfügen kannst.

Drei Dinge tut er nicht, und das sind die Gründe, warum er auf einer Live-App gefahrlos läuft: Er meldet sich nie an, er schreibt nie etwas, und er behält nie einen gefundenen Schlüssel. Ein offengelegtes Geheimnis wird als maskierter Hinweis wie sk_live_…a1b2 gespeichert, der echte Wert wird verworfen. Scanne deine App, oder lies zuerst, was jede der neun Prüfungen ansieht.

Was zu tun ist, in der Reihenfolge, die die Zahlen nahelegen

Was zu tun ist

  • Identifiziere den Schlüssel, bevor du reagierst. Bei Stripe und bei neueren Supabase-Schlüsseln beantwortet das Präfix es; bei einem älteren Supabase-Schlüssel entscheidet das Feld role im Token.
  • Ist es ein Google-Schlüssel, schränke ihn ein, statt ihn zu verstecken. Websites-Beschränkung, deine Domain, nur die APIs, die du nutzt, dazu ein Tageslimit für das Kontingent. Kostenlos, etwa fünf Minuten, keine Codeänderung.
  • Ist es ein echter geheimer Schlüssel, rotiere ihn zuerst. Ihn aus dem Code zu löschen schließt nichts, denn der alte Wert steht weiterhin in deiner Versionshistorie und in zwischengespeicherten Kopien deiner Seite.
  • Geh danach deine Tabellenregeln durch, denn dort liegt laut den Zahlen die eigentliche Angriffsfläche. Fang bei den Tabellen mit Menschen an.
  • Prüfe nach jeder Offenlegung eines geheimen Schlüssels Abrechnung und Protokolle. Das Rotieren stoppt, was als Nächstes passiert, und sagt nichts darüber, was schon passiert ist.

Arbeite die ganze Liste in einer Sitzung durch mit der 10-Minuten-Sicherheitscheckliste, die den Schlüssel und die Tabellenregeln neben den anderen Dingen abdeckt, die in einer frisch veröffentlichten App zu schließen sind. Und wenn dich die Datenbankhälfte dieses Artikels beunruhigt: Sie hat eine eigene Erhebung, kann jeder deine Supabase-Datenbank lesen.

FAQ

Woran erkenne ich, ob mein API-Schlüssel geleakt ist?

Öffne deine Live-Seite, sieh dir den Seitenquelltext an und suche nach den Formen: AIza für einen Google-Schlüssel, sk_ für ein Stripe- oder Modellanbieter-Geheimnis und eyJ für ein Supabase-JWT. Alles, was dabei auftaucht, liegt bereits in den Händen jedes Besuchers. Unser kostenloser Scan macht denselben Blick von außen und meldet in etwa 20 Sekunden, was er sehen kann, ohne Konto für die Note.

Ist ein fest eingebauter API-Schlüssel immer ein Sicherheitsproblem?

Nein, und genau diese Annahme bringt Leute dazu, die Warnung irgendwann zu überhören. Manche Schlüssel werden absichtlich veröffentlicht: ein Supabase-anon-Schlüssel, ein Stripe-pk_-Schlüssel und ein Firebase-Web-Config-Schlüssel gehören alle in den Browser, und was deine Daten schützt, sind die Regeln dahinter. Ein geheimer Schlüssel ist der umgekehrte Fall und gehört auf einen Server. Das Präfix sagt dir, welchen der beiden du vor dir hast.

Jemand sagt, mein Supabase-Schlüssel sei offengelegt. Ist das der schlimme?

Mit hoher Wahrscheinlichkeit nicht. Beide Supabase-Schlüssel sehen gleich aus, lies also die Rolle im Token oder prüfe das Präfix: anon und sb_publishable_ sollen öffentlich sein, service_role und sb_secret_ nicht. Wir fanden einen service_role-Schlüssel in 3 von 30.998 Apps, die Chancen stehen also deutlich für den harmlosen. Ist es doch der geheime, rotiere ihn heute noch im Supabase-Dashboard.

Worüber sollte ich mir stattdessen Sorgen machen?

Über die Tabellenregeln in deiner Datenbank. Von den Apps, bei denen wir diese Prüfung abschließen konnten, hatte mehr als die Hälfte mindestens eine Tabelle, die auf eine Anfrage ganz ohne Login geantwortet hat, und in 394 davon trug die offene Tabelle einen Namen für Menschen: users, profiles, customers, orders. Das ist weit häufiger als jeder geleakte Schlüssel und viel leiser, weil die App in beiden Fällen genau gleich funktioniert.

Ich habe den Schlüssel aus meinem Code entfernt. Ist die Tür jetzt zu?

Nicht von allein. Der alte Wert steht weiterhin in deiner Versionshistorie und in jeder zwischengespeicherten Kopie der Seite, wer ihn also schon eingesammelt hat, kann ihn weiter benutzen. Was die Tür wirklich schließt, ist das Rotieren des Schlüssels im Dashboard des Anbieters, und das ist der erste Schritt, nicht der letzte. Danach prüfe Abrechnung und Protokolle auf Nutzung, die du nicht erklären kannst.

Geschrieben von

Vlad Tkachenko

Gründer, Reeve

Ich schaue mir den ganzen Tag Apps an, die mit Lovable, Bolt, v0, Cursor und Replit gebaut wurden, und die kurze Liste von Fehlern, die darin immer wieder auftauchen.

Mehr über den Autor

Weiterlesen

Alle Artikel

Unsicher, wie es um deine eigene App steht?

Starte einen kostenlosen Scan und erhalte in rund 20 Sekunden eine verständliche Note von A bis F. Ohne Konto, ohne Karte.

App kostenlos scannen

Automatisierte externe Prüfung, kein vollständiges Audit. Das Fehlen von Funden ist keine Garantie für Sicherheit.