Skip to main content

Entfernen vertraulicher Daten aus einem Repository

Vertrauliche Daten können aus dem Verlauf eines Repositorys entfernt werden, wenn eine sorgfältige Koordination mit allen Personen möglich ist, die es geklont haben, und du bereit bist, dich den Nebeneffekte zu widmen.

Entfernen vertraulicher Daten aus einem Repository

Wenn du den Verlauf deines Repositorys mithilfe von Tools wie git filter-repo änderst, ist die Kenntnis über die Auswirkungen wichtig. Das erfolgreiche erneute Generieren des Verlaufs erfordert eine sorgfältige Koordination mit Projektmitarbeitern und weist eine Reihe von Nebeneffekten auf, die behandelt werden müssen.

Es ist wichtig zu beachten, dass es sich bei den vertraulichen Daten, die du entfernen musst, häufig um ein Geheimnis handelt (z. B. Kennwort/Token/Anmeldeinformationen). Als ersten Schritt musst du dieses Geheimnis widerrufen und/oder rotieren. Sobald das Geheimnis widerrufen oder rotiert wurde, kann es nicht mehr für den Zugriff verwendet werden. Das reicht möglicherweise aus, um dein Problem zu lösen. Das Durchlaufen der zusätzlichen Schritte, um den Verlauf erneut zu generieren und das Geheimnis zu entfernen, ist möglicherweise nicht erforderlich.

Nebeneffekte beim erneuten Generieren des Verlaufs

Es gibt zahlreiche Nebeneffekte beim erneuten Generieren des Verlaufs. Diese schließen Folgendes ein:

  • Hohes Risiko einer erneuten Kontamination: Es ist bedauerlicherweise einfach, die vertraulichen Daten erneut in das Repository zu pushen und mehr Schaden anzurichten. Wenn ein Mitentwickler über einen Klon auf dem Stand vor dem erneuten Generieren verfügt und nach dem erneuten Generieren einfach git pull gefolgt von git push ausgeführt wird, werden die vertraulichen Daten zurückgegeben. Er muss seinen Klon verwerfen und erneut klonen oder mehrere Schritte sorgfältig befolgen, um seinen Klon zunächst zu bereinigen.
  • Risiko des Verlusts der Arbeit anderer Entwickler: Wenn andere Entwickler während der Bereinigungsversuche weiterhin Branches aktualisieren, die die vertraulichen Daten enthalten, musst du die Bereinigung wiederholen oder ihre Arbeit verwerfen.
  • Geänderte Commithashes: Durch das erneute Generieren des Verlaufs werden die Hashes der Commits, die die vertraulichen Daten eingeführt haben, und alle darauffolgenden Commits geändert. Alle Tools oder Automatisierungen, die von Commithashes ohne Änderungen abhängen, werden beschädigt oder weisen Probleme auf.
  • Herausforderungen beim Branchschutz: Wenn du Branchschutzmaßnahmen hast, die erzwungene Pushs verhindern, müssen diese Schutzmaßnahmen (zumindest vorübergehend) deaktiviert werden, damit die vertraulichen Daten entfernt werden.
  • Fehlerhafte Diff-Ansicht für geschlossene Pull Requests: Durch das Entfernen der vertraulichen Daten müssen die internen Verweise entfernt werden, die zum Anzeigen der Diff-Ansicht in Pull Requests verwendet werden, damit diese Diffs nicht angezeigt werden können. Das gilt nicht nur für den Pull Request, der die vertraulichen Daten eingeführt hat, sondern für jeden Pull Request, der auf einer Version des Verlaufs nach dem Mergen der vertraulichen Daten basiert, selbst wenn diese späteren Pull Requests keine Datei mit vertraulichen Daten hinzugefügt oder geändert haben.
  • Schlechte Interaktion mit offenen Pull Requests: Geänderte Commit-SHAs führen zu einem anderen Pull-Request-Diff, und Kommentare zum alten Pull-Request-Diff können ihre Gültigkeit verlieren und verloren gehen, was zu Verwirrung von Autoren und Prüfern führen kann. Wir empfehlen, alle geöffneten Pull Requests zusammenzuführen oder zu schließen, bevor du Dateien aus deinem Repository entfernst.
  • Verlorene Signaturen bei Commits und Tags: Signaturen für Commits oder Tags hängen von Commithashes ab. Da Commithashes durch das erneute Generieren des Verlaufs geändert werden, sind Signaturen nicht mehr gültig, und die Signaturen werden durch viele Tools zum erneuten Generieren des Verlaufs (einschließlich git filter-repo) einfach entfernt. Tatsächlich entfernt git filter-repo ebenfalls Commitsignaturen und Tagsignaturen für Commits vor dem Entfernen vertraulicher Daten. (Technisch gesehen kann das mit der Option --refs umgangen werden, um bei Bedarf git filter-repo anzuwenden. Du musst jedoch sicherstellen, dass du alle Verweise angibst, die vertrauliche Daten in ihrem Verlauf enthalten und die Commits enthalten, die die vertraulichen Daten in deinem Bereich eingeführt haben).
  • Andere werden direkt zu den vertraulichen Daten geführt: Git wurde mit kryptografischen Überprüfungen entwickelt, die in Commitidentifizierer integriert sind, damit böswillige Akteure nicht in einen Server gelangen und den Verlauf ändern können, ohne bemerkt zu werden. Das ist aus Sicherheitsperspektive hilfreich, aus der Perspektive vertraulicher Daten bedeutet das jedoch, dass das Löschen vertraulicher Daten einen aufwändigen Prozess darstellt. Zudem bedeutet es, dass bei Änderungen des Verlaufs Benutzer mit einem vorhandenen Klon, die mit dem Prozess vertraut sind, die Abweichungen des Verlaufs bemerken und sie verwenden können, um die vertraulichen Daten immer noch in ihrem Klon zu finden, die du aus dem zentralen Repository entfernt hast.

Informationen zur Offenlegung vertraulicher Daten

Das Entfernen vertraulicher Daten aus einem Repository umfasst vier allgemeine Schritte:

  • Erneutes Generieren des Repositorys mithilfe von git-filter-repo
  • Aktualisieren des Repositorys auf GitHub mithilfe des lokal erneut generierten Verlaufs
  • Koordination mit Kollegen zum Bereinigen weiterer vorhandener Klone
  • Verhindern von Wiederholungen und Vermeiden zukünftiger Lecks vertraulicher Daten

Wenn du deinen Verlauf lediglich neu generierst und einen erzwungenen Push durchführst, sind die Commits mit vertraulichen Daten möglicherweise noch an anderer Stelle zugänglich:

  • In allen Klonen oder Forks Ihres Repositorys
  • Direkt über ihre SHA-1-Hashes in zwischengespeicherten Ansichten auf GitHub Enterprise Server
  • Durch allePull Requests, die darauf verweisen

Du kannst vertrauliche Daten nicht aus Klonen entfernen, die andere Benutzer von deinem Repository erstellt haben, aber du kannst zwischengespeicherte Ansichten und Verweise auf die vertraulichen Daten in Pull Requests auf GitHub Enterprise Server über den Ihrer Websiteadministratoren dauerhaft entfernen lassen.

Wenn der Commit, der die vertraulichen Daten eingeführt hat, in allen Forks vorhanden ist, kann weiterhin darauf zugegriffen werden. Sie müssen sich mit den Besitzern der Forks abstimmen und sie bitten, die vertraulichen Daten zu entfernen oder die Verzweigung vollständig zu löschen.

Berücksichtige diese Einschränkungen und Herausforderungen bei deiner Entscheidung, den Verlauf deines Repositorys neu zu generieren.

Löschen einer Datei aus dem Verlauf deines Repositorys mithilfe von git-filter-repo

Warning

Wenn Sie git filter-repo ausführen, nachdem Sie für Änderungen einen Stash ausgeführt haben, können Sie ihre Änderungen nicht mit anderen Stashbefehlen abrufen. Vor dem Ausführen von git filter-repo sollten Sie den Stash aufheben, den Sie für Ihre vorgenommenen Änderungen ausgeführt haben. Führe git stash show -p | git apply -R aus, um deinen letzten Stash aufzuheben. Weitere Informationen findest du unter Git Tools – Stashen und Bereinigen.

Um zu veranschaulichen, wie git filter-repo funktioniert, zeigen wir Ihnen, wie Sie Ihre Datei mit vertraulichen Daten aus dem Verlauf Ihres Repositorys entfernen und .gitignore hinzufügen, um sicherzustellen, dass sie nicht versehentlich erneut committet wird.

  1. Installiere die neueste Version des Tools git filter-repo. Du kannst git-filter-repo manuell oder mithilfe eines Paket-Managers installieren. Verwenden Sie beispielsweise den Befehl brew install, um das Tool mit HomeBrew zu installieren.

    brew install git-filter-repo
    

    Weitere Informationen findest du in INSTALL.md im Repository newren/git-filter-repo.

  2. Wenn Sie keine lokale Kopie des Repositorys mit den vertraulichen Daten im Verlauf haben, müssen Sie das Repository auf Ihrem lokalen Computer klonen.

    $ git clone https://HOSTNAME/YOUR-USERNAME/YOUR-REPOSITORY
    > Initialized empty Git repository in /Users/YOUR-FILE-PATH/YOUR-REPOSITORY/.git/
    > remote: Counting objects: 1301, done.
    > remote: Compressing objects: 100% (769/769), done.
    > remote: Total 1301 (delta 724), reused 910 (delta 522)
    > Receiving objects: 100% (1301/1301), 164.39 KiB, done.
    > Resolving deltas: 100% (724/724), done.
    
  3. Navigiere zum Arbeitsverzeichnis des Repositorys.

    cd YOUR-REPOSITORY
    
  4. Führe den folgenden Befehl aus, und ersetze PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA durch den Pfad zur Datei, die du entfernen möchtest, nicht nur durch den Dateinamen. Diese Argumente werden:

    • erzwingen, dass Git den gesamten Verlauf eines jeden Branchs und Tags verarbeitet, ohne ihn auszuchecken

    • die angegebene Datei sowie alle leeren Commits entfernen, die als Ergebnis generiert wurden

    • einige Konfigurationen entfernen, wie zum Beispiel die Remote-URL, die in der Datei .git/config gespeichert ist Du solltest diese Datei zur späteren Wiederherstellung im Voraus sichern.

    • vorhandene Tags überschreiben

        $ git filter-repo --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
        Parsed 197 commits
        New history written in 0.11 seconds; now repacking/cleaning...
        Repacking your repo and cleaning out old unneeded objects
        Enumerating objects: 210, done.
        Counting objects: 100% (210/210), done.
        Delta compression using up to 12 threads
        Compressing objects: 100% (127/127), done.
        Writing objects: 100% (210/210), done.
        Building bitmaps: 100% (48/48), done.
        Total 210 (delta 98), reused 144 (delta 75), pack-reused 0
        Completely finished after 0.64 seconds.
      

      Important

      Wenn die Datei mit vertraulichen Daten in anderen Pfaden zu finden war (weil sie verschoben oder umbenannt wurde), müssen Sie diesen Befehl auch für diese Pfade ausführen.

  5. Stelle sicher, dass du alles entfernt hast, das du aus dem Repositoryverlauf entfernen möchtest.

  6. Das Tool git filter-repo entfernt Ihre konfigurierten Remotes automatisch. Verwenden Sie den Befehl git remote set-url, um Ihre Remotes wiederherzustellen, und ersetzen Sie dabei OWNER und REPO durch Ihre Repository-Details. Weitere Informationen finden Sie unter Remote-Repositorys verwalten.

    git remote add origin https://github.com/OWNER/REPOSITORY.git
    
  7. Sobald du mit dem Status deines Repositorys zufrieden bist und die entsprechenden Remotedaten festgelegt hast, führe einen erzwungenen Push deiner lokalen Änderungen durch, um dein Repository auf Ihre GitHub Enterprise Server-Instance zu überschreiben. Ein erzwungener Push ist erforderlich, um vertrauliche Daten aus deinem Commitverlauf zu entfernen.

    $ git push origin --force --all
    > Counting objects: 1074, done.
    > Delta compression using 2 threads.
    > Compressing objects: 100% (677/677), done.
    > Writing objects: 100% (1058/1058), 148.85 KiB, done.
    > Total 1058 (delta 590), reused 602 (delta 378)
    > To https://HOSTNAME/YOUR-USERNAME/YOUR-REPOSITORY.git
    >  + 48dc599...051452f main -> main (forced update)
    
  8. Um die vertrauliche Datei aus Deinen getaggten Releases zu entfernen, musst du auch einen Push für deine Git-Tags erzwingen:

    $ git push origin --force --tags
    > Counting objects: 321, done.
    > Delta compression using up to 8 threads.
    > Compressing objects: 100% (166/166), done.
    > Writing objects: 100% (321/321), 331.74 KiB | 0 bytes/s, done.
    > Total 321 (delta 124), reused 269 (delta 108)
    > To https://HOSTNAME/YOUR-USERNAME/YOUR-REPOSITORY.git
    >  + 48dc599...051452f main -> main (forced update)
    

Vollständiges Entfernen der Daten aus GitHub

Nachdem du git filter-repo verwendet hast, um die vertraulichen Daten zu entfernen und deine Änderungen an GitHub Enterprise Server zu pushen, musst du einige weitere Schritte ausführen, um die Daten vollständig aus GitHub Enterprise Server zu entfernen.

  1. Kontaktieren Sie den Ihrer Websiteadministratoren, und bitten Sie darum, zwischengespeicherte Ansichten und Referenzen auf die sensiblen Daten in Pull Requests auf GitHub Enterprise Server zu entfernen. Gib den Namen des Repositorys und/oder einen Link zu dem Commit an, der entfernt werden soll. Weitere Informationen darüber, wie Site-Administratoren nicht erreichbare Git-Objekte entfernen können, findest du unter Befehlszeilenprogramme. Weitere Informationen dazu, wie Website-Administratoren erreichbare Commits identifizieren können, findest du unter Identifizieren erreichbarer Commits.

  2. Teile deinen Projektmitarbeitern, dass sie für alle Branches, die sie aus deinem alten (nicht mehr gültigen) Repositoryverlauf erstellt haben, ein Rebase, keinen Merge durchführen sollen. Durch einen Merge-Commit würde womöglich der gesamte unbrauchbare Verlauf wiederhergestellt, den zu entfernen du Dir gerade so viel Mühe gemacht hast.

Identifizieren erreichbarer Commits

Um unerwünschte oder sensible Daten vollständig aus einem Repository zu entfernen, muss der Commit, der die Daten zuerst eingeführt hat, in Zweigen, Tags, Pull-Requests und Forks vollständig referenzfrei sein. Ein einzelner Verweis an einer beliebigen Stelle verhindert, dass die automatische Speicherbereinigung die Daten vollständig löscht.

Sie können auf vorhandene Referenzen überprüfen, indem Sie die folgenden Befehle verwenden, wenn sie über SSH mit der Anwendung verbunden sind. Sie benötigen die SHA des Commits, der ursprünglich die vertraulichen Daten eingeführt hat.

ghe-repo OWNER/REPOSITORY -c 'git ref-contains COMMIT_SHA_NUMBER'
ghe-repo OWNER/REPOSITORY -c 'cd ../network.git && git ref-contains COMMIT_SHA_NUMBER'

Wenn einer dieser Befehle Ergebnisse zurückgibt, müssen Sie diese Referenzen entfernen, bevor der Commit erfolgreich die automatische Speicherbereinigung ausführen kann. Der zweite Befehl identifiziert Referenzen, die in Forks des Repositorys vorhanden sind (wenn das Repository keine Forks enthält, können Sie die Ausführung überspringen).

  • Ergebnisse, die mit refs/heads/ oder refs/tags/ beginnen, weisen auf Zweige bzw. Tags hin, die noch Verweise auf den beanstandeten Commit enthalten, was darauf hindeutet, dass das geänderte Repository nicht vollständig von dem Commit bereinigt wurde oder dass er nicht gepusht wurde.
  • Ergebnisse, die mit refs/pull/ oder refs/__gh__/pull beginnen, weisen auf Pull-Requests hin, die auf den beanstandeten Commit verweisen. Diese Pull-Requests müssen gelöscht werden, damit der Commit für die automatische Speicherbereinigung zulässig ist. Ein Pull-Request kann im Admin-Dashboard der Website unter https://HOSTNAME/stafftools/repositories/OWNER/REPOSITORY/PULL_REQUESTS/<PULL-REQUEST-NUMBER> gelöscht werden, wobei <PULL-REQUEST-NUMBER> durch die Nummer des Pull-Requests ersetzt wird.

Wenn Verweise in allen Forks gefunden werden, sehen die Ergebnisse ähnlich aus, beginnen jedoch mit refs/remotes/NWO/. Um die Fork anhand des Namens zu identifizieren, können Sie den folgenden Befehl ausführen.

ghe-nwo NWO

Die vertraulichen Daten können aus den Branches eines Repositorys entfernt werden, indem sie in den Klon eines Repositorys übertragen werden, aus dem bereinigten Repository abgerufen werden, und anschließend ein Rebase aller Branches und Tags erneut ausgeführt wird, die zusätzlich zum relevanten Branch oder Tag die vertraulichen Daten aus dem bereinigten Repository enthalten. Alternativ können die Forks vollständig gelöscht werden, und bei Bedarf kann das Repository nach Abschluss der Bereinigung des Stamm-Repositorys erneut verzweigt werden.

Nachdem Sie die Verweise des Commits entfernt haben, führen Sie die Befehle erneut aus, um die Überprüfung durchzuführen.

Wenn keine Ergebnisse aus einem der ref-contains Befehle vorliegen, können Sie die automatische Speicherbereinigung mit dem --prune Flag ausführen, um die nicht referenzierten Commits zu entfernen, indem Sie den folgenden Befehl ausführen.

ghe-repo-gc -v --prune OWNER/REPOSITORY

Sobald die automatische Speicherbereinigung den Commit erfolgreich entfernt hat, sollten Sie das Site-Admin-Dashboard des Repositorys unter https://HOSTNAME/stafftools/repositories/OWNER/REPOSITORY aufrufen, Netzwerk auswählen und dann auf Git-Cache ungültig machen klicken, um alle zwischengespeicherten Daten zu entfernen.

Versehentliche Commits künftig vermeiden

Indem du verhinderst, dass Mitwirkende versehentlich Commits ausführen, kannst du die Offenlegung vertraulicher Informationen verhindern. Weitere Informationen findest du unter Best Practices zum Verhindern von Datenlecks in deiner Organisation.

Es gibt ein paar Schritte, mit denen du es vermeiden kannst, Elemente zu committen oder zu pushen, die nicht freigegeben werden sollten:

  • Wenn es wahrscheinlich ist, dass die vertraulichen Daten in einer Datei gefunden werden, die nicht von Git nachverfolgt werden soll, füge die entsprechenden Dateinamen zu .gitignore hinzu, und stelle sicher, dass du diese Änderung an .gitignore pushst, damit weitere Entwickler geschützt sind.
  • Vermeide die Hartcodierung von Geheimnissen im Code. Verwende Umgebungsvariablen oder Geheimverwaltungsdienste wie Azure Key Vault, AWS Secrets Manager oder HashiCorp Vault, um Geheimnisse zur Laufzeit zu verwalten und zu injizieren.
  • Erstelle einen Hook vor dem Commit, um nach vertraulichen Daten zu suchen, bevor diese an beliebiger Stelle committet oder gepusht werden, oder verwende in einem Hook vor dem Commit ein bekanntes Tool wie git-secrets oder gitleaks. (Bitte alle Projektmitarbeiter darum, den von dir ausgewählten Hook vor dem Commit einzurichten.)
  • Verwende ein visuelles Programm wie GitHub Desktop oder gitk, um die Änderungen zu committen. In visuellen Programmen ist meist leichter erkennbar, welche Dateien durch einen Commit hinzugefügt, gelöscht und geändert werden.
  • Vermeide die allgemeingültigen Befehle git add . und git commit -a für die Befehlszeile – verwende stattdessen git add filename und git rm filename, um die Dateien einzeln bereitzustellen.
  • Verwende git add --interactive, um die Änderungen in jeder Datei einzeln zu überprüfen und zu stagen.
  • Verwende git diff --cached, um die für den Commit gestageten Änderungen zu überprüfen. Das ist genau der Unterschied, den git commit erzeugt, solange du nicht das -a Flag verwendest.
  • Aktivieren Sie den Push-Schutz für das Repository, um Push-Vorgänge mit hardcodierten Geheimnissen zu erkennen und zu verhindern, die sie in der Codebasis festgeschrieben werden. Weitere Informationen finden Sie unter Informationen zum Pushschutz.

Weiterführende Themen