Sicherheitsgrundlagen
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.

Kurz gesagt
- Wenn ein API-Key geleakt wurde, hängt der erste Schritt davon ab, welcher Key es ist. Publishable Keys gehören in dein Frontend und brauchen gar nichts.
- Bei einem echten Geheimnis klär zuerst, ob der Key Geld ausgeben kann. Das ist der einzige Teil hier, an dem eine Uhr läuft.
- Einen Key stoppen und einen Key ersetzen sind bei jedem Anbieter zwei verschiedene Schalter, und die meisten geben dir ein Fenster, in dem beide Keys funktionieren.
- Danach liest du das Log des Anbieters für den Zeitraum, in dem der Key draußen war, und lässt deine Git-Historie in Ruhe, bis der Key tot ist.
Die Nachricht kommt meistens aus einem Scan-Bericht, von GitHub, das dir mitteilt, in einem deiner Repositories sei ein Geheimnis aufgetaucht, oder von jemandem, der auf deiner Seite F12 gedrückt und dir einen Screenshot geschickt hat. Wie auch immer sie dich erreicht hat: du weißt jetzt, dass ein API-Key von dir geleakt wurde, und du weißt nicht, was zuerst zu tun ist.
Hier ist der Teil, den eine Anleitung nach der anderen falsch macht: Sie geben für jeden Key dieselbe Antwort, und die Antwort lautet immer rotieren. Manche dieser Keys sollen öffentlich sein und brauchen gar nichts. Von den übrigen lassen manche gerade still eine Rechnung wachsen, während du das liest, und andere haben ihren ganzen Schaden schon am Tag des Deploys angerichtet. Das sind drei verschiedene Situationen, und der erste Schritt ist in jeder ein anderer.
Ist der Key überhaupt ein Geheimnis?
Oft nicht, und die Zahlen sind schief genug, um das klar zu sagen.
Wir haben 31.056 live Apps gescannt und das JavaScript gelesen, das jede davon an den Browser ausliefert. Die Prüfung, die nach Zugangsdaten sucht, konnte bei allen antworten, und 1.332 kamen mit mindestens einem Key zurück, der eine Meldung wert war. 1.142 davon waren Google-API-Keys, und das ist der eine Typ darunter, der normalerweise genau dort sitzt, wo er hingehört.
Ein Google-API-Key in einer Webseite ist das, was Google Maps zum Laufen bringt. Der Key sagt, welches Projekt bezahlt, und was Fremde davon abhält, auf deine Rechnung zu gehen, ist die Einschränkung am Key statt seiner Geheimhaltung. Googles eigene Anleitung ist bei beiden Hälften deutlich: "Unrestricted API keys are insecure", und "You are financially responsible for charges caused by abuse of unrestricted API keys." Die Reparatur für so einen Key besteht darin, ihn in der Cloud Console zu öffnen und zwei Einschränkungen zu setzen, eine mit deiner Website und eine mit den APIs, die du tatsächlich aufrufst. Der Key selbst ändert sich nie.
Die andere Familie, die in den Browser gehört, sind die Publishable Keys. Ein
Stripe-Key pk_live_ und ein Supabase-Key sb_publishable_ oder anon sind
dafür gebaut, dass jeder Besucher sie liest.
Welche deiner Keys im Frontend sicher sind
ist die Vier-Zeichen-Version dieses Tests.
Wenn du deinen Bundle nicht von Hand durchgehen willst: Unser kostenloser Scan liest deine Live-Seite, listet die Keys auf, die er von außen sieht, und sagt dir, welcher Art jeder einzelne ist: App scannen. Das dauert rund 20 Sekunden und braucht kein Konto.
Mein API-Key wurde geleakt. Was mache ich zuerst?
Klär, ob an dem Key ein Zähler hängt.
Ein Key mit Zähler berechnet dir jede Anfrage. Die von Google, von OpenAI, von
Anthropic, und ein AWS-Key mit den falschen Rechten dahinter, sind alle Zähler:
Der Verkehr von jemand anderem landet auf deiner Rechnung, in einem Takt, den
die Person bestimmt und den du nicht siehst. Ein Key ohne Zähler liest oder
schreibt stattdessen deine Daten. Ein Supabase-Key service_role ist das
klarste Beispiel, und nichts daran kostet Geld pro Stunde.
Diese eine Frage legt die Reihenfolge fest.
Hat der Key einen Zähler, stopp ihn jetzt. Die Funktion, die ihn benutzt hat, ist kaputt, bis du den Ersatz deployst, und das ist der richtige Tausch, denn die Rechnung ist der einzige Teil hier, der weiter wächst, während du planst.
Liest der Key Daten und wurde er in deinem Bundle veröffentlicht, ist er längst gelesen worden. Jeder Besucher, der die Seite geladen hat, hat eine Kopie, und jeder Crawler, der genau nach dieser Zeichenfolge gesucht hat, ebenfalls. Es wird nichts schlimmer, während du die richtige Reihenfolge herausfindest, und worauf es dabei ankommt, ist, dich unterwegs nicht aus deiner eigenen App auszusperren.
Was jede Art von Key tatsächlich kann
| Key | Gibt Geld aus | Liest deine Daten | Lässt er sich stattdessen einschränken? | Geht die App vom Ersetzen kaputt? |
|---|---|---|---|---|
Supabase sb_publishable_ oder anon | Nein | Nur die Zeilen, die deine Regeln erlauben | Gehört in den Browser | Nicht zutreffend |
Stripe pk_live_ | Nein | Nein | Gehört in den Browser | Nicht zutreffend |
Google AIza… | Ja, auf deiner Cloud-Rechnung | Nein | Ja, und Google sagt, das zuerst zu versuchen | Einschränken nicht. Rotieren schon. |
| OpenAI- oder Anthropic-Key | Ja, im Takt eines Fremden | Dateien und Assistants im Projekt | Es gibt keine Publishable-Variante | Ja, bis ein Server von dir ihn hält |
Stripe sk_live_ oder rk_live_ | Ja | Ja, Kunden- und Zahlungsdaten | Ein Restricted Key ist die enge Version | Nein, es gibt ein Fenster von sieben Tagen |
AWS AKIA… samt geheimer Hälfte | Ja, auch Rechenzeit pro Stunde | Deine S3-Buckets | Deactivate, und das ist umkehrbar | Nein, du darfst zwei Keys gleichzeitig halten |
Supabase sb_secret_ oder service_role | Nein | Jede Zeile in jeder Tabelle | Nein | Ja, bei einem älteren Projekt |
Zwei Anmerkungen zu dieser Tabelle, denn beide ändern, was du als Nächstes tust.
Ein AWS Access Key besteht aus zwei Zeichenfolgen, einer Kennung, die mit AKIA
beginnt, und einer geheimen Hälfte, und AWS verlangt beide zusammen, um eine
Anfrage zu signieren. Eine AKIA-Zeichenfolge allein in einem Bundle ist also
nicht benutzbar, und der Grund, sie trotzdem als dringend zu behandeln, ist,
dass die beiden Hälften fast immer gemeinsam eingefügt werden. Öffne die Datei
und such nach der zweiten, bevor du entscheidest, in welchem Fall du bist.
Die Details pro Anbieter stehen beim jeweiligen Anbieter: ein OpenAI-Key, ein Google-API-Key, ein geheimer Stripe-Key und ein Supabase-service_role-Key, der als einziger ein eigenes Verfahren hat.
Den Key stoppen und den Key ersetzen sind zwei verschiedene Knöpfe
Jeder Anbieter in dieser Tabelle gibt dir beide, und wer in Panik ist, greift nach dem zweiten.
- Google. Einen Key einzuschränken ändert die Zeichenfolge nicht, deine App läuft also weiter. Ihre Sicherheitsanleitung stellt das vor alles andere: "First try to restrict your API keys", und Rotieren ist die dritte Option von oben, für den Fall, dass eine Einschränkung nicht möglich ist.
- Stripe. Expire key stoppt einen Key für sich allein, ganz ohne Ersatz. Ihre Haltung dazu, wann man das tut, enthält kein Zögern: "If a restricted or secret API key is exposed or compromised, rotate it immediately even if you aren't sure anyone saw it." Sie trennen außerdem die beiden Wörter, die alle durcheinander benutzen. Exposure ist, dass der Key irgendwo sichtbar wurde, wo er nicht hätte sein sollen. Compromise ist der Nachweis, dass ihn jemand benutzt hat.
- AWS. Deactivate ist der Schalter, und das Nützliche daran ist, dass er sich zurücknehmen lässt. AWS sagt, du sollst den alten Key gar nicht löschen, solange du noch prüfst: "we recommend that you do not immediately delete the first access key. Instead, choose Actions and then choose Deactivate." Wenn sich herausstellt, dass irgendetwas Vergessenes ihn noch braucht, schaltest du ihn wieder ein.
- Supabase, bei einem älteren Projekt. Es gibt einen Schalter, und der
erfasst beide Legacy-Keys.
anonundservice_rolesind mit demselben Geheimnis signiert, wer also den einen abschaltet, den er loswerden will, stoppt damit auch den, den sein Frontend benutzt. Die vier Schritte, die das vermeiden liest man besser vor dem Umlegen des Schalters als danach.
Das Log für den Zeitraum lesen, in dem der Key draußen war
Das Fenster öffnet sich mit dem Deploy, der den Key zuerst ausgeliefert hat, und schließt sich, als du ihn gestoppt hast. Auf diesen Zeitraum filterst du das Log des Anbieters.
Jeder Anbieter in der Tabelle führt eines. Stripe zeigt Request-Logs für einen einzelnen Key, über das Überlaufmenü neben diesem Key auf der Seite mit den API Keys. AWS setzt ohne jede Einrichtung ein Datum der letzten Nutzung an jeden Access Key in der IAM-Konsole und protokolliert die Aufrufe selbst in CloudTrail. Google zeichnet die Nutzung pro Key in der Cloud Console auf, und genau das sagt ihre eigene Anleitung dir auch, bevor du irgendetwas an einem Key änderst. Supabase führt API- und Datenbank-Logs für das Projekt, und wie man das Fenster bei einem Supabase-Key eingrenzt sagt, wonach man darin sucht.
Du suchst nach Verkehr, den du nicht erklären kannst: Anfragen an Tabellen oder Endpunkte, die deine App nie anfasst, Volumen zu Zeiten, in denen niemand sie benutzt hat, Löschungen, die niemand gemacht hat. Danach schau dir die Daten selbst an, denn eine Supportnachricht über einen Datensatz, der sich von allein geändert hat, ist die Art, wie das meiste davon tatsächlich entdeckt wird, und sie trifft Wochen später ein.
Oft kannst du es nicht mit Sicherheit sagen, und Stripe sagt dasselbe über die eigene Erkennung: "Stripe doesn't guarantee detection of all exposed or compromised keys." Also ist "nichts im Log" ein Ergebnis, und es lohnt sich, es mit dem Zeitraum daneben aufzuschreiben.
Rotieren, ohne die App lahmzulegen
Drei der vier Anbieter oben geben dir ein Fenster, in dem der alte und der neue Key beide funktionieren, und genau das verhindert einen Ausfall.
Stripe. "When you rotate a key in the Dashboard, both the old and new keys work for up to 7 days." Der Dialog hat außerdem eine Option Now, und ihre Dokumentation ist eindeutig: Wer sie wählt, bei dem wird der alte Key gelöscht. Das ist der Knopf für den Notfall mit Zähler statt für eine saubere Migration. Ihr Rat, wann man den alten gehen lässt, ist eine Messung statt eines Datums: Prüf seine Request-Logs und lass ihn erst auslaufen, wenn sein Anfragevolumen ein paar Stunden oder Tage lang bei null lag.
Google. Beim Rotieren entsteht der neue Key mit allen Einschränkungen des alten, und in ihren Worten: "both the old and new key are accepted", solange du deine Apps hinüberziehst. Wenn du den alten zu früh löschst und etwas kaputt geht, gibt es einen Weg zurück: Ein gelöschter Google-API-Key lässt sich innerhalb von 30 Tagen wiederherstellen.
AWS. Die Reihenfolge steht in ihrer Dokumentation und sie beginnt beim neuen Key: Leg den zweiten Access Key an, solange der erste noch aktiv ist, zieh jede Anwendung darauf um, prüf das Datum der letzten Nutzung am alten, deaktiviere ihn, und lösch ihn erst dann. Eine Obergrenze, mit der du planen musst: Ein IAM-Benutzer darf höchstens zwei Access Keys halten, eine dritte Anwendung auf einem alten Key hat also keinen Platz.
Supabase, bei einem älteren Projekt. Kein Fenster. Das direkte Rotieren der
Legacy-Keys anon und service_role wird nicht mehr unterstützt, einen davon
ungültig zu machen ist also eine Migration auf das neue Key-Paar, und die
Reihenfolge der vier Schritte ist das, was die App am Laufen hält.
Er steht immer noch in deiner Git-Historie
Das tut er, und die GitHub-Dokumentation dazu beginnt damit, dich zu etwas anderem zu schicken.
Ihre Seite zum Entfernen sensibler Daten verweist dich zurück auf den Key: "if the sensitive data you need to remove is a secret (e.g. password/token/credential), as is often the case, then as a first step you need to revoke and/or rotate that secret", und dann: "Once the secret is revoked or rotated, it can no longer be used for access, and that may be sufficient to solve your problem. Going through the extra steps to rewrite the history and remove the secret may not be warranted."
Der Grund dafür ist das, was ein Force Push nicht erreicht. Nachdem du deine Historie umgeschrieben hast, stehen die alten Commits immer noch "In any clones or forks of your repository" und "Directly via their SHA-1 hashes in cached views on GitHub". Der Support kann die Cache-Ansichten und die Verweise in Pull Requests löschen, wenn du fragst, und zieht dabei seine eigene Grenze: Er "will only assist in the removal of sensitive data in cases where we determine that the risk can't be mitigated by rotating affected credentials." Ein Fork behält seine Kopie so oder so, und GitHub kann dir die Kontaktdaten seines Besitzers nicht geben.
Die Reihenfolge, die sie beschreiben, ist also die praktische: den Key widerrufen und danach entscheiden, ob das Umschreiben der Historie die Nebenwirkungen wert ist. Widerrufen erreicht Kopien, die ein Umschreiben nicht erreicht, darunter die in einem Clone, von dem du nichts weißt, und die in einem Screenshot, den jemand behalten hat.
Wie der nächste gar nicht erst in den Bundle kommt
Ein Key kommt über einen Deploy in deinen Bundle, und Deploys hören nicht auf. Jeder davon ist eine weitere Gelegenheit, dass ein Wert, den du in ein Secrets-Feld eingetragen hast, in einer Datei landet, die der Browser herunterlädt. Deshalb beschreibt eine Prüfung von letztem Monat die App von letztem Monat.
Unser kostenloser Scan beantwortet die Frage, mit der du hergekommen bist.
- die neun Prüfungen gegen deine Live-URL, in rund 20 Sekunden
- jeder Key, den er von außen sieht, jeweils eingeordnet statt nur gefunden
- eine Note und die Funde, ohne Konto
Reeve Monitor führt diese Prüfungen erneut aus, ohne dass du fragst.
- alle neun Prüfungen jede Stunde, für bis zu drei Apps
- eine Nachricht, wenn sich ein Ergebnis ändert, damit der Key aus dem Deploy von letzter Nacht nicht darauf wartet, dass du nachsiehst
- ob die App erreichbar ist, alle 60 Sekunden
- ein monatlicher Bericht darüber, was er gesehen hat
Reeve Care hält eine Kopie deiner Supabase-Datenbank bereit, für die Keys, die schreiben können.
- jede Nacht eine verschlüsselte Kopie, verwahrt dort, wo dein Projekt nicht hinkommt
- jede Kopie wird geprüft, bevor sie zählt, indem die Zeilen jeder Tabelle gezählt werden
- eine Wiederherstellung mit einem Klick, wenn du sie brauchst
- auch deine hochgeladenen Dateien, sobald du eine Storage-Zugangsberechtigung verbindest
- alles, was Monitor tut
Ein geleakter Key, der nur lesen kann, lässt deine Daten dort, wo sie waren. Ein
service_role-Key oder ein AWS-Key mit Schreibrechten kann eine Tabelle leeren,
und kein noch so gründliches Rotieren danach bringt die Zeilen zurück.
Der Tag, an dem ein KI-Agent eine Produktionsdatenbank gelöscht hat
zeigt, wie sich das von innen anfühlt.
Was du jetzt tun solltest
Was zu tun ist
- Erkenn den Key, bevor du ihn anfasst. Ein Supabase-Key
anonodersb_publishable_und ein Stripe-Keypk_live_gehören dorthin, wo sie sind, und von den 1.332 Apps, bei denen wir einen meldenswerten Key gefunden haben, hatten 1.142 einen Google-API-Key, der eine Einschränkung statt einer Rotation braucht. - Frag, ob ein Zähler daran hängt. Wenn die Anfragen von jemand anderem auf deiner Rechnung landen, stopp den Key jetzt und lass die Funktion kaputtgehen.
- Benutz den Stopp-Schalter genauso wie den Ersatz-Schalter: Expire key bei Stripe, Deactivate bei AWS, eine Website- und API-Einschränkung bei Google.
- Ersetz ihn dann innerhalb des Fensters, das der Anbieter gibt. Stripe gibt dir sieben Tage mit beiden Keys live, Google akzeptiert beide, solange du migrierst, und AWS lässt dich zwei Access Keys gleichzeitig halten.
- Lies das Log des Anbieters für den Zeitraum zwischen dem Deploy und dem Stopp und schreib auf, was du gefunden hast, auch wenn es "nichts" ist.
- Lass die Git-Historie bis zum Schluss. Sobald der Key widerrufen ist, sagt GitHubs eigene Anleitung, dass sich das Umschreiben der Historie womöglich gar nicht lohnt.
Wenn du das Ganze lieber als Liste durchgehst: Die Sicherheits-Checkliste in 10 Minuten deckt das hier und die anderen Dinge ab, die man in einer frisch gestarteten App abschalten sollte.
FAQ
Mein API-Key wurde geleakt. Was mache ich zuerst?
Klär, ob der Key Geld ausgeben kann. Ein Key, der dir pro Anfrage etwas berechnet, kostet dich genau jetzt etwas, also stopp ihn sofort und nimm in Kauf, dass die Funktion dahinter ein paar Minuten lang kaputt ist. Ein Key, der nur Daten liest, ist längst gelesen worden, wenn er öffentlich war. Dann nimm dir die Zeit, den Austausch in einer Reihenfolge zu machen, die dich nicht aus deiner eigenen App aussperrt.
Zuerst widerrufen oder zuerst rotieren?
Zuerst widerrufen, wenn an dem Key ein Zähler hängt. Den alten Key stoppen und einen neuen ausstellen sind bei jedem Anbieter zwei getrennte Schalter, und nur der erste schließt das Loch. Die Ausnahme ist ein Key, den du stattdessen einschränken kannst: Google sagt dir, du sollst es bei einem Google-API-Key erst mit einer Website- und einer API-Einschränkung versuchen, bevor du ihn überhaupt rotierst.
Wie erkenne ich, ob jemand meinen Key benutzt hat?
Grenz das Fenster auf die Zeit zwischen dem Deploy, der den Key ausgeliefert hat, und dem Moment ein, in dem du ihn gestoppt hast, und lies das Log des Anbieters für diesen Zeitraum. Stripe zeigt Request-Logs pro Key, AWS zeigt ein Datum der letzten Nutzung am Access Key und protokolliert die Aufrufe in CloudTrail, Google zeichnet die Nutzung pro Key auf, und Supabase führt API- und Datenbank-Logs. Du suchst nach Anfragen an Dinge, die deine App nie anfasst, und nach Verkehr zu Zeiten, in denen niemand die App benutzt hat. Oft kannst du es nicht mit Sicherheit sagen, und das ist ein normales Ergebnis.
Geht meine App kaputt, wenn ich den Key rotiere?
Meistens nicht, wenn du das Fenster nutzt, das der Anbieter dir gibt. Bei Stripe funktionieren alter und neuer Key bis zu sieben Tage lang gemeinsam. Google stellt den neuen Key mit den Einschränkungen des alten aus und akzeptiert beide, solange du migrierst. Bei AWS darfst du zwei Access Keys gleichzeitig halten, der neue ist also schon live, bevor der alte geht. Die Ausnahme ist ein älteres Supabase-Projekt: dort nimmt der Schalter, der die Legacy-Keys abschaltet, deinen Frontend-Key mit.
Der Key steht in meiner Git-Historie. Reicht es, die Datei zu löschen?
Nein, und die Historie umzuschreiben ist wahrscheinlich auch nicht die Antwort. Die GitHub-Dokumentation sagt, du sollst das Geheimnis zuerst widerrufen oder rotieren, und dass sich der zusätzliche Aufwand, die Historie umzuschreiben, danach oft nicht mehr lohnt. Ein Force Push erreicht die Kopien in Forks und Clones nicht und die über den Commit-Hash erreichbaren Cache-Ansichten auch nicht. Den Key unbrauchbar zu machen deckt jede Kopie auf einmal ab.