Parola, API anahtarı, bağlantı dizgisi — bunlara sır diyoruz ve kaynak kodunda durmamaları gerekiyor. Ama duruyorlar. Acelesi olan biri anahtarı yapılandırma dosyasına yazıyor, "sonra düzeltirim" diyor ve commit'liyor.
Asıl mesele şu: bir sır git'e girdiğinde silmek onu geri getirmiyor.
Dosyadan çıkarıp yeni bir commit atarsanız çalışma ağacı temizlenir, geçmiş
temizlenmez. git log -p komutunu yazan herkes o anahtarı okuyabilir. Depo
bir kere klonlandıysa artık başkasının diskinde de duruyor.
gitleaks tam da bunu arıyor: hem çalışma ağacını hem de geçmişin tamamını tarayıp sır gibi görünen şeyleri işaretliyor. Bu labda önce sızıntıyı bulacağız, sonra bir daha olmasını engelleyen kapıyı kuracağız.
Bu lab ne işe yarıyor
Git'e giren bir sır silmekle gitmiyor — çalışma ağacı temizleniyor, geçmiş temizlenmiyor ve depoyu klonlamış olan herkeste zaten bir kopya var. Yani bu bir temizlik işi değil, anahtar döndürme işi; asıl çözüm de sırrın hiç commit'lenememesini sağlayan kapı.
Bu labdan sonra şunları yapabileceksiniz:
- bir deponun yalnızca dosyalarını değil geçmişinin tamamını taramak
- bulguyu okuyup hangi anahtarın nerede sızdığını söylemek
- sırrı commit'ten önce durdurmak ve kapıyı çıkış koduna bağlamak
- istisnayı dosyayı atlamak yerine tek bir bulguya daraltmak
Bu lab nasıl işliyor
Bunu bir kez okuyun - bu eğitimdeki her lab aynı kurallarla yazıldı.
Komutları nereye yazacaksınız. Bir terminal açın ve bu depoyu kopyaladığınız klasöre gidin. Windows'ta PowerShell kullanın (Başlat menüsünde aratın), macOS veya Linux'ta Terminal. Labdaki bütün yollar depo kökünden yazıldı, yani bir adım aksini söylemedikçe orada kalın.
> ile başlayan satırlar açıklamadır, komut değildir. Onları yapıştırmayın.
Yalnızca gri kod kutularının içindeki metin yazılır.
📋 işareti "sıra sizde" demektir. Onu gördüğünüzde adımı önce kendiniz deneyin. Hemen altında cevabı saklayan kapalı bir "Nasıl yapılır?" oku var; onu denedikten sonra açın, önce değil. Lablar bilerek böyle yazıldı: kendi çözdüğünüz şeyi hatırlarsınız, yapıştırdığınızı değil.
Bir komut hata verirse bu normal olabilir. Bazı adımlar hatanın nasıl göründüğünü göstermek için bilerek başarısız olur. Bir şeyin bozuk olduğuna karar vermeden önce komutun üstündeki cümleyi okuyun.
Takılırsanız şu sırayla:
- Komutun üstündeki paragrafı tekrar okuyun - cevap genelde oradadır.
- "Nasıl yapılır?" okunu açın.
hints.mddosyasını açın, küçük bir yönlendirme verir.solution.mddosyasını açın, tam cevap orada. Kullanmak serbest; okumadan kopyalamak değil.
Bitirdiğinizde en alttaki Temizlik bölümünü çalıştırın. Lablar aynı portları ve container adlarını paylaşıyor; birinden kalan artık diğerini bozar.
Başlamadan önce
Süre: yaklaşık 40 dakika.
Docker Desktop çalışıyor olmalı. Kontrol edin:
docker version
Çıktıda bir Server: bölümü görüyorsanız hazırsınız. Onun yerine hata
alıyorsanız Docker Desktop'ı başlatın ve balina simgesi hareket etmeyi
bırakana kadar bekleyin.
Bütün komutları deponun kök dizininden çalıştırın; bu labdaki yollar ona göre yazıldı.
Kaynaklar
Sırlı depoyu kurmak
Gerçek bir sızıntıyı incelemek için gerçek bir geçmişe ihtiyacımız var. demo klasöründeki küçük imaj onu üretiyor — üç commit'lik bir depo, ikincisinde bir AWS sırrı, üçüncüsünde "temizlenmiş" hâli.
Önce imajı derleyin:
docker build -t sirli-depo ./labs/secret-scanning/demo
Sonra depoyu oluşturun:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo sirli-depo
Depo labs/secret-scanning/sirli-depo klasöründe oluştu. Oraya kendi
editörünüzle bakabilirsiniz — bu labda birkaç dosyayı elle yazacağız ve
hepsini o klasörde yazacağız.
⚠️ Windows kullanıyorsanız komutları PowerShell'de çalıştırın. Git Bash bu labdaki
-v ... :/depoifadesindeki/depokısmını bir Windows yoluna çevirip bozuyor (invalid volume specificationhatası). PowerShell'de böyle bir sorun yok.
Çalışma ağacını taramak
Elimizdeki dosyalara bakalım. dir komutu git'i hiç açmadan, yalnızca
diskteki dosyaları tarıyor:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 dir /depo --no-banner
Çıktının son satırı:
INF no leaks found
Temiz. Rapor böyle diyor, yani sorun yok — öyle mi?
Geçmişi taramak
Şimdi aynı depoya git tarafından bakalım. git komutu her commit'in
farkını tek tek geziyor:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 git /depo --no-banner -v
Bu sefer bulgu var:
Finding: aws_secret_access_key: 7Hk2pQnR4vTzL9mXbW3dYfJ6gC8sA1eU5oI0rNtP
Secret: 7Hk2pQnR4vTzL9mXbW3dYfJ6gC8sA1eU5oI0rNtP
RuleID: generic-api-key
Entropy: 5.321928
File: config.yml
Line: 5
Commit: ea9ceaadc754e297f774db4855aab331ae473cbb
Author: Lab
Email: [email protected]
Date: 2026-10-24T20:27:11Z
Fingerprint: ea9ceaadc754e297f774db4855aab331ae473cbb:config.yml:generic-api-key:5
Sizdeki
CommitveFingerprintdeğerleri farklı olacak — depo sizin makinenizde üretildiği için commit kimlikleri her seferinde değişiyor. Bunu birazdan kullanacağız, o yüzden çıktıyı açık tutun.
İki tarama arasındaki fark, bu labın tamamı: dosyalara bakmak yetmiyor, geçmişe bakmak gerekiyor. Geliştirici sırrı sildi, commit attı, işini bitirdiğini düşündü. Anahtar hâlâ orada.
📋 Anahtarın geçmişte gerçekten durduğunu kendi gözünüzle doğrulayın.
Nasıl yapılır?
Depodaki git geçmişine doğrudan bakabilirsiniz. Makinenizde git kurulu olmasına gerek yok, demo imajının içindekini kullanıyoruz:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo --entrypoint git sirli-depo -C /depo log -p -- config.yml
İkinci commit'in farkında anahtarı düz metin olarak göreceksiniz. Üçüncü commit onu siliyor ama silme işlemi de geçmişin bir parçası — eski hâli oradan okunabiliyor.
Sızıntı bulunduğunda ne yapılır
Buradaki refleks genelde yanlış oluyor. "Geçmişi temizleyelim" deniyor ve
git filter-repo ile commit'ler yeniden yazılıyor. Bu ikinci adım, hem
de isteğe bağlı olanı.
Birinci adım her zaman anahtarı döndürmektir (rotate). Sır, en az bir kez bir depoya girdiği andan itibaren yanmıştır: kim klonladı, kimin CI önbelleğinde kaldı, hangi yedeğe gitti bilinmiyor. Geçmişi temizlemek anahtarı geçersiz kılmıyor — yalnızca bulmayı zorlaştırıyor.
Yani sıra şu:
- anahtarı sağlayıcıda iptal edip yenisini üret
- yeni anahtarı bir sır kasasına koy, koda değil
- erişim kayıtlarına bak — o anahtarla ne yapılmış
- sonra, istenirse geçmişi yeniden yaz
Tarayıcının görmediği sır
Depoda docs/ornek.md adında bir dosya var. Editörünüzle açıp içine bakın —
labs/secret-scanning/sirli-depo/docs/ornek.md.
İki tane AWS anahtarı duruyor. Ama her iki tarama da onları hiç raporlamadı. Neden?
Çünkü AKIAIOSFODNN7EXAMPLE ve wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY,
AWS'nin kendi dökümanlarındaki örnek anahtarlar. Gitleaks'in varsayılan
yapılandırmasında bir izin listesi (allowlist) var ve bunlar orada. Tarayıcı
"bu anahtarı dünyadaki her README içeriyor, gerçek olamaz" diyor.
Bu doğru bir karar — aksi hâlde her dökümantasyon dosyası yanlış alarm üretirdi. Ama şunu da öğretiyor:
"Tarayıcı temiz dedi" ile "sır yok" aynı şey değil. Her tarayıcının bir izin listesi, bir kural kümesi ve bir eşiği var. Gördüğü şeyleri bulur, görmediklerini bulmaz.
📋 Bu durum sizin kurumunuzda nasıl ters teper? Kendi anahtar biçiminizin varsayılan kurallarda olmadığını düşünün.
Cevap
Gitleaks GitHub, AWS, Stripe, Slack gibi bilinen sağlayıcıların anahtar
biçimlerini tanıyor. Sizin SPS-4K7M2Q9XB3TR6WZA gibi kendi ürettiğiniz
anahtar biçiminizi tanımıyor — yüksek entropili olursa generic-api-key
kuralına takılabilir, olmazsa hiç görünmez.
Kendi biçimleriniz için kendi kuralınızı yazmanız gerekiyor. Bu labın sonundaki alıştırma tam olarak o.
Commit'ten önce durdurmak
Bulmak iyi, ama asıl istediğimiz sırrın geçmişe hiç girmemesi. Gitleaks bunun için henüz commit'lenmemiş, yalnızca hazırlanmış (staged) değişikliklere bakabiliyor.
Önce bir sır hazırlayalım. Editörünüzle sirli-depo klasörünün içinde
ci.yml adında bir dosya oluşturup şunu yazın:
ci:
token: ghp_K3nR7pQ2vXz9LmW4bYdF6gJ8sC1aU5oI0rNt
Bu jeton sahte, hiçbir yere bağlı değil — biçimi gerçeğine benziyor, gitleaks'in tanıması için o yeterli.
Dosyayı commit'e hazırlayın:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo --entrypoint git sirli-depo -C /depo add ci.yml
Şimdi kapıyı çalıştırın:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 git /depo --staged --no-banner -v
Secret: ghp_K3nR7pQ2vXz9LmW4bYdF6gJ8sC1aU5oI0rNt
RuleID: github-pat
WRN leaks found: 1
Bu sefer kural generic-api-key değil github-pat. Gitleaks jetonun
biçiminden hangi servise ait olduğunu biliyor — bu, bulguyu okuyan kişi için
çok daha kullanışlı: hangi anahtarı döndüreceğini biliyor.
Önemli olan tarafı: commit henüz atılmadı. Sır geçmişe hiç girmedi.
📋 Bu komutun bir kapı olarak işe yaraması için neyin doğru olması lazım?
Cevap
Çıkış kodunun sıfırdan farklı olması. Otomasyon raporu okumaz, çıkış kodunu
okur. Komutu -v olmadan çalıştırıp çıkış koduna bakın:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 git /depo --staged --no-banner
Windows PowerShell'de echo $LASTEXITCODE, macOS veya Linux'ta echo $?
yazın — 1 göreceksiniz. Sızıntı yoksa 0 döner.
Bu, komutu bir pre-commit kancasına veya CI işine koyabilmenizi sağlıyor:
kod 1 dönerse commit ya da build durur. Kapıyı kapı yapan şey rapor değil,
bu çıkış kodu.
Hazırladığımız sırrı geri alın, deponun temiz kalması lazım:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo --entrypoint git sirli-depo -C /depo restore --staged ci.yml
Sonra ci.yml dosyasını klasörden silin.
İstisna: bildiğiniz bir bulguyu susturmak
Her bulgu gerçek sır olmuyor. Test verisi, örnek yapılandırma, çoktan döndürülmüş bir anahtar — bunlar her taramada tekrar tekrar karşınıza çıkar ve bir süre sonra kimse raporu okumaz olur. Gürültü, kapıyı kapatan en yaygın sebep.
Gitleaks için istisna, bulgunun parmak izini (fingerprint) bir dosyaya yazmakla oluyor. Önce kendi parmak izinizi alın:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 git /depo --no-banner -v
Fingerprint: satırını kopyalayın. Şuna benziyor ama sizdeki farklı:
ea9ceaadc754e297f774db4855aab331ae473cbb:config.yml:generic-api-key:5
📋 Bu parmak izini deponun kökündeki .gitleaksignore dosyasına yazıp
taramayı tekrarlayın.
Nasıl yapılır?
Editörünüzle sirli-depo klasöründe .gitleaksignore adında bir dosya
oluşturun ve tek satır olarak kendi parmak izinizi yazın:
ea9ceaadc754e297f774db4855aab331ae473cbb:config.yml:generic-api-key:5
Sonra tekrar tarayın:
docker run --rm -v ./labs/secret-scanning/sirli-depo:/depo zricethezav/gitleaks:v8.30.1 git /depo --no-banner
no leaks found görüyorsunuz ve çıkış kodu artık 0.
Parmak izi commit kimliğini, dosyayı, kuralı ve satırı birlikte içeriyor. Yani istisna o bulguya özel: aynı dosyaya yeni bir sır girerse parmak izi değişir ve kapı yine kapanır. Bu, "şu dosyayı hiç tarama" demekten çok daha dar bir istisna.
İstisna kaydı bir karardır, bir temizlik değil. Yanına gerekçesini, sahibini ve son geçerlilik tarihini yazın. Sessizce susturulan bulgu, unutulan bulgudur.
Devam etmeden önce .gitleaksignore dosyasını silin.
Lab
Gitleaks sizin kurumunuzun anahtar biçimini bilmiyor. Sıra onu öğretmekte.
Siparişi işleyen servisin kendi API anahtarları SPS- ile başlıyor ve
ardından 16 karakter büyük harf ve rakam geliyor — örneğin
SPS-4K7M2Q9XB3TR6WZA. Depoya böyle bir anahtar koyun ve gitleaks'in onu
yakalamasını sağlayın.
Yapmanız gerekenler:
sirli-depoklasörüne bu biçimde bir anahtar içeren bir dosya ekleyin- önce tarayın — varsayılan kurallarla yakalanmadığını görün
- aynı klasörde bir
.gitleaks.tomlyazıp kendi kuralınızı tanımlayın - tekrar tarayın, bulgunun
RuleIDalanında kendi kural adınızı görün
Dikkat edilecek bir nokta var: kendi yapılandırma dosyanızı yazdığınızda gitleaks varsayılan kuralları kullanmayı bırakabilir. Yani kendi kuralınızı eklerken GitHub ve AWS anahtarlarını yakalayan kuralları kaybetmemeniz lazım.
Takıldınız mı? İpuçlarına bakın veya çözümü inceleyin.
Takılırsanız
Cannot connect to the Docker daemon - Docker Desktop çalışmıyor.
Başlatın ve balina simgesi hareket etmeyi bırakana kadar bekleyin.
port is already allocated - önceki bir labdan kalan konteyner o portu
hâlâ tutuyor. docker ps ile neyin çalıştığına bakın, eskisini
docker rm -f <ad> ile kaldırın.
The container name "/..." is already in use - aynı sebep, aynı çözüm:
docker rm -f <ad> deyip komutu tekrar çalıştırın.
Build sırasında unable to prepare context: path ... not found - yanlış
dizindesiniz. Bu labdaki her komut deponun kök dizininde olduğunuzu varsayıyor.
Çalışmak yerine kullanım metni basan docker run - bu labdaki bazı
komutlar, yanlış argümanın nasıl göründüğünü göstermek için kasıtlı olarak
başarısız oluyor. Bozuk sanmadan önce komutun çevresindeki açıklamayı okuyun.
Hâlâ takılıysanız: aşağıdaki Cleanup bölümü her şeyi sıfırlıyor, labı temiz bir makineyle baştan yapabilirsiniz.
Temizlik
Bu labın ürettiklerini kaldırın:
docker rmi sirli-depo
Demo deposu labs/secret-scanning/sirli-depo klasöründe duruyor. Bu klasör
.gitignore içinde, yani deponuza karışmıyor; isterseniz silebilirsiniz,
isterseniz bırakın — labı tekrar çalıştırdığınızda zaten sıfırdan üretiliyor.