example-petstore.com

Voorbeelddomein · Geen echte dienst · Bezoekers met een browser zien deze pagina · API-verzoeken krijgen 410 Gone

Gids · Beveiliging

Een geheim uit de Git-geschiedenis verwijderen

Er is een sleutel, token of wachtwoord in een commit terechtgekomen. Het bestand in een nieuwe commit verwijderen helpt niet: de oude commit bevat het nog steeds, in elke clone en elke fork. Deze gids laat de juiste volgorde zien: eerst intrekken, dan de geschiedenis herschrijven, het hostingplatform opruimen en ervoor zorgen dat het niet opnieuw gebeurt.

Eerst: trek het geheim in

Beschouw een gecommit geheim als uitgelekt, ook in een privérepository: clones, forks, CI-logs en back-ups kunnen al een kopie bevatten, en geautomatiseerde scanners pikken nieuwe commits in openbare repository’s binnen enkele minuten op.

  1. Trek de sleutel, het token of het wachtwoord in of vervang het bij de dienst die het heeft uitgegeven.
  2. Zet de nieuwe in de configuratie of in een secrets manager, niet in de code.
  3. Controleer de logboeken van de dienst op gebruik dat je niet herkent.

Waar je sleutels intrekt bij bekende aanbieders: Gelekte sleutels: wat je nu doet. De geschiedenis herschrijven komt daarna, nooit in plaats daarvan.

De geschiedenis herschrijven of niet

Een ingetrokken geheim geeft geen toegang meer, en volgens GitHub kan dat voldoende zijn. Herschrijven is toch de moeite waard als:

  • het geheim niet in te trekken is, of het bestand andere gevoelige gegevens bevat, zoals persoonsgegevens of klantgegevens;
  • de repository openbaar is of openbaar wordt;
  • je wilt dat scanners het oude geheim niet langer melden.

Herschrijven verandert de ID van elke latere commit. Wie meewerkt, moet zijn werk rebasen, openstaande pull requests kunnen hun reviewopmerkingen kwijtraken en handtekeningen van commits verdwijnen. Spreek met iedereen die erbij betrokken is een moment af, en merge of sluit openstaande pull requests eerst.

Elke vindplaats opsporen

# Welke commits hebben de tekenreeks toegevoegd of verwijderd?
git log --all --oneline -S 'the-secret-value'

# In welke bestanden kwam hij voor?
git grep 'the-secret-value' $(git rev-list --all)

# Doorzoek de hele geschiedenis op bekende formaten van geheimen
gitleaks git -v

Noteer elk bestandspad waaronder het geheim voorkwam, ook eerdere namen als het bestand verplaatst of hernoemd is.

Herschrijven met git-filter-repo

git-filter-repo is de tool die GitHub aanbeveelt. Gebruik versie 2.47 of nieuwer, die de optie --sensitive-data-removal heeft, en werk in een verse clone.

# Installeren (of gebruik je pakketbeheerder)
brew install git-filter-repo        # macOS
pip install git-filter-repo         # overal waar Python draait

git clone https://github.com/YOUR-ORG/YOUR-REPO
cd YOUR-REPO

# Optie 1: een heel bestand uit de hele geschiedenis verwijderen
git-filter-repo --sensitive-data-removal --invert-paths --path config/secrets.yml

# Optie 2: het geheim overal vervangen waar het voorkomt
git-filter-repo --sensitive-data-removal --replace-text ../replacements.txt

Het vervangingsbestand bevat één waarde per regel. Standaard wordt elke treffer ***REMOVED***; met ==> kies je zelf de vervanging, en regex: zoekt op een patroon:

# ../replacements.txt (buiten de repository)
sk_live_51Hx0000000000000000000000
AKIA0000000000000000==>AWS_ACCESS_KEY_ID_REMOVED
regex:password\s*=\s*"[^"]+"==>password = "REMOVED"

Controleer het resultaat met git log --all -S 'the-secret-value': dat hoort niets te tonen. Overschrijf daarna de remote:

git push --force --mirror origin

Een branchbeveiliging die force pushes blokkeert, moet je daarvoor even uitschakelen. Na de push is het herschrijven niet meer ongedaan te maken.

GitHub opruimen

Na de force push zijn oude commits nog bereikbaar via pull requests, weergaven in de cache en forks.

  • Pull requests en weergaven in de cache: neem contact op met GitHub Support en geef het aantal betrokken pull requests door (grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs) en de “First Changed Commit(s)” die git-filter-repo toonde. GitHub helpt alleen als het vervangen van de sleutel het risico niet kan wegnemen.
  • Forks: commits in forks blijven daar staan. Vraag de eigenaars de fork te verwijderen of op te ruimen; GitHub geeft hun contactgegevens niet door.
  • Clones van collega’s: iedereen moet zijn branches op de nieuwe geschiedenis rebasen, niet mergen. Eén merge brengt de oude commits terug.

Op GitLab, Bitbucket of een eigen server gaat het op een vergelijkbare manier; kijk in de documentatie van dat platform hoe het oude objecten en weergaven in de cache verwijdert.

Alternatief: BFG

BFG Repo-Cleaner is een oudere tool op basis van Java die nog veel gebruikt wordt. Hij werkt op een mirror-clone en laat standaard de laatste commit ongemoeid. Haal het geheim daarom eerst in een gewone commit uit de huidige versie.

git clone --mirror https://github.com/YOUR-ORG/YOUR-REPO.git
java -jar bfg.jar --replace-text replacements.txt YOUR-REPO.git
cd YOUR-REPO.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push

Het volgende lek voorkomen

  • Push protection: op GitHub blokkeert secret scanning met push protection een push met een bekend formaat van een geheim, nog voor die de repository bereikt.
  • Een controle vóór elke commit: laat gitleaks of git-secrets draaien als pre-commit hook, en in CI voor wie die overslaat.
  • Configuratie, geen code: lees geheimen uit omgevingsvariabelen of een secrets manager, en zet .env en vergelijkbare bestanden in .gitignore vóór de eerste commit.
  • Kijk vóór je commit: stage bestanden een voor een en controleer git diff --cached, in plaats van git add . of git commit -a.

Ging die sleutel ook naar een voorbeeldadres zoals api.example-petstore.com? Dan is hij ook op een server beland waar je geen controle over hebt: API-clients en SDK’s configureren.

Bronnen