Claude Code’un “Tekrar Sorma” düğmesi, onayladığınız komutu birebir .claude/settings.local.json dosyasına izin (allow) kuralı olarak kaydediyor. Bu komutta parola veya API anahtarı varsa, gizli bilgi artık proje klasörünüzde düz metin olarak duruyor ve dosya commit edilirse herkese açık hale geliyor. Güvenlik firması Apiiro, herkese açık GitHub’da bu şekilde 1.122 dosya ve bunlarda 1.379 gerçek gizli bilgi buldu. İşte kendi depolarınızı tek komutla kontrol etmenin, temizlemenin ve bunun tekrar yaşanmasını önlemenin yolu.
Ne oldu: Apiiro bulguları sayılarla
Apiiro, herkese açık GitHub’da Claude Code’un kişisel izin onaylarınızı sakladığı proje başına dosya olan .claude/settings.local.json kopyalarını aradı. Araştırma, 103.617 depoda 104.185 kopya buldu. iTnews’in araştırma hakkındaki yazısına göre bunlardan 1.122’sinde en az bir gerçek gizli bilgi vardı; toplamda 1.379 farklı gizli bilgi.
| Gizli bilgi türü | Adet |
|---|---|
| Veritabanı parolaları | 379 |
| Supabase service-role anahtarları | 122 |
| Herkese açık sunucular için SSH giriş bilgileri | 43 |
| GitHub, GitLab ve npm token’ları | 42 |
| AWS anahtarları | 23 |
Apiiro aramayı dosyanın eski git sürümlerine, paylaşılan .claude/settings.json dosyasına ve kayıtlı ajan günlüklerine genişlettiğinde sayı, 1.994 depoda 2.539 gizli bilgiye çıktı. Apiiro kimlik bilgilerinin hâlâ çalışıp çalışmadığını test etmedi, ancak bilgilendirdiği bir kuruluş anahtarın aktif olduğunu doğruladı.
Tarama sonuçları en çok endişelenmeniz gereken kısım. Gerçek gizli bilgi içeren 1.122 dosyanın 643’ünü TruffleHog, 564’ünü gitleaks işaretledi. 215 dosya ikisinden de kaçtı. Yani “gizli bilgi tarayıcımız var” demek temiz olduğunuzun kanıtı değil.
Olay, 582 puanla Hacker News’ün zirvesine yerleşti. Anthropic’te Claude Code’un başındaki Boris Cherny, başlıkta Claude Code’un tarihsel olarak gizli bilgileri temizlemediğini ve ekibin bunu incelediğini belirtti. Orijinal Apiiro araştırmasını okuyun.
“Tekrar Sorma” nasıl olur da gizli bilgileri bir dosyaya koyar?
Claude Code bir Bash komutu çalıştırmak istediğinde önce sorar. “Evet ve tekrar sorma” seçeneğini seçtiğinizde Claude Code, Anthropic’in ayarlar dokümantasyonunda anlatıldığı gibi kalıcı bir onayı .claude/settings.local.json dosyasına allow kuralı olarak yazar. Kural, komut metnini kaydeder. Komut şu olsaydı:
psql "postgresql://admin:Sup3rS3cret@db.example.com:5432/prod" -c "select count(*) from users"
ayarlar dosyanız artık şuna benzer bir içerik barındırıyordu:
{
"permissions": {
"allow": [
"Bash(psql \"postgresql://admin:Sup3rS3cret@db.example.com:5432/prod\" -c \"select count(*) from users\")"
]
}
}
Parola kuralın içinde, çünkü komutun içindeydi. Claude Code, onayladığınızı kelimesi kelimesine kaydeder.

Neden GitHub’a düşüyor
Claude Code bu dosyayı git dışında tutmaya çalışır. Halihazırda yok sayılmayan bir depoda ilk kez .claude/settings.local.json yazdığında, global git hariç tutma (excludes) dosyanıza **/.claude/settings.local.json ekler. Ancak bu korumada boşluklar var:
- Dosyayı elle oluşturdunuz. Dokümantasyon açıkça şunu söyler: dosyayı kendiniz oluşturduysanız, onu
.gitignore’a eklemeniz gerekir. Cherny’nin HN’deki yorumuna göre sızan kopyalar elle oluşturulmuş ve sonra depoya alınmıştı. - Yok sayma kuralı tek bir makinede duruyor. Kural, deponun
.gitignoredosyasında değil, sizin global excludes dosyanızda. Bir ekip üyesi, bir CI işi veya klasörü kopyalayan yeni bir bilgisayar bu kuralı devralmaz. - Dosya zorla eklenmişti veya kuraldan önce takip ediliyordu.
git add -fyok sayma kurallarını geçersiz kılar ve bir dosya bir kez takip edilmeye başlandığında, yok sayma kuralları artık ona uygulanmaz. - Paylaşılan dosya. VS Code eklentisinde onay kartı, hedef dosyayı seçmenize izin verir; commit edilen
.claude/settings.jsondahil. Oraya kaydedilen bir kural herkese gider.
Depolarınızı tek komutla kontrol edin
Bulunduğunuz depoyla başlayın. Şu komutlar dosyanın şu anda takip edilip edilmediğini ve hiç commit edilip edilmediğini söyler:
git ls-files | grep -E '(^|/)\.claude/settings(\.local)?\.json$'
git log --all --name-only --format= | grep -E '\.claude/settings(\.local)?\.json$' | sort -u
İlk satır bir şey yazdırıyorsa, dosya mevcut ağacınızda demektir. İkinci satır bir şey yazdırıyorsa, dosya sonradan silinmiş olsa bile geçmişinizdedir.
Bir klasör altındaki tüm depoları tek seferde taramak için:
find ~/code -path '*/.claude/settings.local.json' -exec sh -c \
'cd "$(dirname "$1")/.." && git ls-files --error-unmatch .claude/settings.local.json >/dev/null 2>&1 && echo "TRACKED: $PWD"' _ {} \;
Bir GitHub organizasyonu için GitHub CLI, dosya adına göre kod arayabilir:
gh search code permissions --owner your-org --filename settings.local.json
Sonra bulduğunuz her dosyanın içine bakın. Tarayıcılar sızan dosyaların %19’unu kaçırdığı için yeşil bir tarama sonucuna güvenmek yerine kuralları kendiniz okuyun:
grep -nE 'Bash\(' .claude/settings.local.json | grep -iE 'pass|token|key|secret|://[^/]*:[^@]*@'
user:password@ içeren bir bağlantı dizesi, Authorization: Bearer başlığı, -p ardından yazılmış bir parola ya da sk-, ghp_, AKIA veya eyJ ile başlayan her şey bir kimlik bilgisidir. İkinci bir geçiş olarak — tek geçiş değil — depo üzerinde gitleaks çalıştırın.
Sızan bir ayarlar dosyası nasıl düzeltilir
Sıralama önemli. Önce anahtar değişimi gelir; çünkü dosyayı silmek, fork’larda, klonlarda ve önbelleklerde duran kopya için hiçbir şey yapmaz.
- Dosyanın içerdiği her kimlik bilgisini değiştirin. Dosyanın tüm geçmişini
git log -p --all -- .claude/settings.local.jsonile inceleyin, içindeki her gizli bilgiyi listeleyin ve her birini sağlayıcısında iptal edin. Apiiro’nun rehberi bu adımı ilk sıraya koyar. - Dosyayı takipten çıkarın ve deponun kendisinde yok sayın:
git rm --cached .claude/settings.local.json
echo '.claude/settings.local.json' >> .gitignore
git add .gitignore && git commit -m "Stop tracking Claude Code local settings"
git check-ignore -v .claude/settings.local.json
Son komut eşleşen .gitignore satırını yazdırmalı. Depodaki bir kural her klonu korur.
- Depo herkese açıksa veya geniş çapta paylaşıldıysa geçmişi temizleyin. git-filter-repo dosyayı her commit’ten kaldırır:
git filter-repo --invert-paths --path .claude/settings.local.json
git push --force --all
Bu, herkes için geçmişi yeniden yazar; bu yüzden önce ekibinizi uyarın. Fork’lara da ulaşmaz; yani bu bir temizlik işlemidir, 1. adımın yerine geçmez.
- Yerel dosyayı da temizleyin.
.claude/settings.local.jsondosyasını açın, gerçek bir gizli bilgi içeren her kuralı silin ve yerine bir desen (bir sonraki bölüm) koyun. - Push korumasını açın. GitHub secret scanning push protection, tanınan gizli bilgi biçimlerini içeren push’ları engeller. 215 dosyanın kaçtığı gösterdiği gibi her şeyi yakalamaz ama yaygın token biçimlerini durdurur.
Tekrar yaşanmasını önleyin
Çözümü söylemek basit: ajanınızın çalıştırdığı bir komuta asla gerçek bir gizli bilgi yazmayın ve tam komutlar yerine desenleri onaylayın.

Gizli bilgilere atıfta bulunun, yazmayın. Kabuk, bir değişkeni çalışma anında açar; ancak allow kuralı metni yazıldığı gibi saklar. Yani psql "$DATABASE_URL" komutu, kurala parolayı değil $DATABASE_URL’i kaydeder:
{
"permissions": {
"allow": ["Bash(psql \"$DATABASE_URL\" *)", "Bash(npm run test *)"],
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
deny kuralları doğrudan Anthropic’in ayarlar dokümanlarından alınmıştır; Claude Code’un .env dosyalarınızı okumasını engeller, böylece bir anahtar oradan bir komuta yapıştırılamaz.
Kuralları dar tutun. Araştırmayı alıntılayan HN yorumcuları, dosyaların %5’inin herhangi bir kabuk komutuna izin verdiğini ve %43’ünün Bash(python:*) gibi yorumlayıcı kuralları olduğunu söyledi. Böyle bir kural, ajanın her şeyi Python üzerinden çalıştırmasına izin verir; yani fazladan adımlarla “her şeye izin ver” kuralıdır.
Auto modu ve bir sandbox düşünün. Cherny, elle yazılmış izin kuralları yerine auto modu önerdi ve Anthropic’in açık kaynaklı bir sandbox geliştirdiğini söyledi. Birkaç yorumcu, auto modun bir güvenlik sınırı değil bir sınıflandırıcı olduğunu belirtti; bu yüzden onu yukarıdaki alışkanlıklarla birlikte kullanın.
Ajanları üretim gizli bilgilerinden uzak tutun. En güvenli anahtar, ajanın hiç görmediği anahtardır. Bu konudaki desenleri AI ajanlarının API anahtarlarını görmeden nasıl kullanacağı yazımızda, saldırganların sızan AI anahtarlarıyla yaptıklarını ise çalınan AI API anahtarları ve LLMjacking yazımızda ele almıştık.
Apidog CLI ile kodlama ajanınızın anahtar yazmadan API çağırmasını sağlayın
Bir anahtarın onaylanmış bir komuta düşmesinin yaygın yollarından biri hızlı bir API çağrısıdır: bir endpoint’i kontrol etmek için curl -H "Authorization: Bearer sk-...". Bu işi yerine Apidog CLI’ya devredebilirsiniz. Anahtar bir Apidog ortam değişkeninde durur, test senaryonuz ona {{API_KEY}} olarak atıfta bulunur ve ajanınızın çalıştırdığı komut yalnızca proje, senaryo ve ortam ID’leri içerir. Kaydedilecek gizli bir şey yoktur.
Kurulumu bir kez yapın — ajan üzerinden değil kendi terminalinizde — böylece erişim token’ınız hiçbir onaydan geçmez:
npm install -g apidog-cli@latest
apidog auth login
npx -y skills add https://apidog.com # pick Claude Code when prompted
Sonra Claude Code’a tek bir prompt verin:
List the environments in Apidog project 123456, then run test scenario 7890
against the staging environment and summarise any failed assertions.
The API key is stored in that environment as {{API_KEY}}. Never pass a key,
token or password on the command line, and never use --env-var for secrets.
Ajan, “Tekrar Sorma” ile güvenle onaylanabilecek şu tür komutları çalıştırır:
apidog environment list --project 123456
apidog run -t 7890 --project 123456 -e <envId> -r cli,json
İki dürüst uyarı. Birincisi, apidog run değişkenin paylaşılan değerini kullanır; bu değer Apidog’a senkronize edilir ve proje üyeleri tarafından görülebilir, bu yüzden oraya üretim root anahtarı değil kapsamı daraltılmış bir test anahtarı koyun. Değerleri diskte tutmak isterseniz, apidog run ayrıca --variables <path> parametresini alır; onu deponun dışındaki bir dosyaya yönlendirin. İkincisi, --env-var "key=value" parametresi komut satırından değişken geçmek için vardır ve tam da bu desen sızdırır; bu yüzden ajanınıza gizli bilgiler için bunu kullanmamasını söyleyin.
Enterprise planındaki ekipler ayrıca Apidog Vault Secrets ile HashiCorp Vault, Azure Key Vault veya AWS Secrets Manager’dan gizli bilgileri çekebilir ve Enterprise SaaS Secret Scanner, Apidog isteklerine, script’lerine ve değişkenlerine kaydedilen anahtarları işaretler. GitHub depolarını taramaz; bu yüzden yukarıdaki kontrolleri de sürdürün. Tam kurulum rehberi için Claude Code’da Apidog CLI nasıl kullanılır ve Apidog’da ortamları ve gizli değişkenleri yönetme yazılarına bakın. Apidog’un Free planı 4 kullanıcıya kadar kapsar.
SSS
Claude Code’un settings.local.json dosyası varsayılan olarak gitignore edilir mi?
Kısmen. Claude Code bir git deposunda dosyayı oluşturduğunda, global git excludes dosyanıza **/.claude/settings.local.json ekler. Bu yalnızca kendi makinenizi korur ve dosyayı elle oluşturduysanız ya da zorla eklediyseniz geçerli değildir. Satırı deponun kendi .gitignore dosyasına da ekleyin.
Dosyayı silmek sızan anahtarı kaldırır mı?
Hayır. Anahtar git geçmişinde, fork’larda ve herkese açık olduğu süreçte yapılan her klonda durur. Önce anahtarı değiştirin, sonra dosyayı takipten çıkarın ve geçmişi git-filter-repo ile temizleyin.
gitleaks veya TruffleHog bu sızıntıları yakalar mı?
Güvenilir şekilde hayır. Apiiro’nun örneğinde, gerçek gizli bilgi içeren 1.122 dosyanın 215’i her iki araç tarafından da kaçırıldı. Bir tarayıcı çalıştırın, sonra dosyadaki Bash(...) kurallarını kendiniz okuyun.
Bu bir model sorunu mu, yoksa Claude Code sorunu mu?
Apiiro bunu Opus 5.5 ve Fable 5.1 ile yeniden üretti ve bir model özelliği değil, Claude Code özelliği olarak nitelendirdi. Onay, komutu yazan model ne olursa olsun komut metnini saklar.
Claude Code’da komutları güvenle nasıl onaylarım?
Bash(npm run test *) gibi desenleri onaylayın ve gizli bilgilere $DATABASE_URL gibi ortam değişkenleriyle atıfta bulunun. Read(./.env) ve Read(./.env.*) için deny kuralları ekleyin.
