AI agent API anahtarlarını sızdırmadan nasıl çalıştırılır?
API key, tek bir tool call ile sızabilir. Gerçek anahtar yerine credential gateway arkasında kapsamı sınırlı, kısa ömürlü token kullanımı açıklanıyor.
Gizli bilgileri AI agent'larından uzak tutmak ne anlama gelir
Bir AI agent, komutları çalıştıran normal bir Linux işlemidir. Bu işlemin tuttuğu her ortam değişkeni, çalıştırdığı kod tarafından okunabilir. Bu nedenle agent'ın ortamındaki bir API key, agent'ın erişebildiği herhangi bir ana bilgisayara gönderebileceği bir anahtardır. Gizli bilgileri agent'tan uzak tutmak, agent'a anahtarın kendisi yerine bir erişim tanıtıcısı vermek anlamına gelir: kısa ömürlü, kapsamı sınırlandırılmış bir token veya ağ sınırında başka bir bileşenin gerçek değerle değiştirdiği bir yer tutucu.
Bu, modelin düşmanca davranmaya başlamasıyla ilgili değildir. Mekanizma daha sıradandır. Bir agent, talimatlar içeren bir web sayfasını, README'yi veya issue yorumunu okur ve bu talimatları uygular. Çünkü bir dil modeli için sizin yazdığınız metin ile getirdiği metin arasında fark yoktur. Buna prompt injection denir. Bu gerçekleştiğinde zararın kapsamını tam olarak tek bir unsur belirler: işlemin okuyabildiği veriler. Henüz bir sınır belirlemediyseniz, bir sunucuda kodlama agent'ını güvenli biçimde çalıştırma başlığı bu kılavuzun üzerine kurulduğu yalıtım katmanlarını açıklar.
Tehdit modelinin basit açıklaması
Bunu, aracınızın çalıştığı kullanıcı olarak çalıştırın.
tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'Yazdırdığı her satır, başka bir sunucuya yönelik tek bir HTTP isteği üzerinden gerçekleştirilebilir. Şimdi aracın yakınındaki diskte nelerin bulunduğuna bakın.
grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'Kabuğa erişimi olan bir aracının bu verileri dışarı aktarmak için karmaşık bir güvenlik açığından yararlanması gerekmez. Dört sıradan yol bunu sağlar ve bu yolların dördü de günlükte normal çalışma gibi görünür:
- Herhangi bir ana bilgisayara, değerin sorgu dizesinde bulunduğu bir giden
curlveyafetch. - Aracın yazma yetkisine sahip olduğu bir depoya yönelik
git commitvegit push. - Aracın kullanıcısı olarak rastgele kod çalıştıran bir paket kurulum betiği.
- Değeri içeren bir ana bilgisayar adının DNS sorgusu. HTTP çıkışı engellense bile bu sorgu dışarı çıkar.
Bunu yalnızca inceleme yaparak çözemezsiniz. Çözüm, erişim alanında değerli hiçbir şey bulunmamasını sağlamaktır.
Çalışma ağacındaki bir gizli bilgi bağlam penceresinde de gizli bilgidir
Bir ajan dosyaları okur. Çalıştığı depodaki bir .env dosyası okunur. Okunduktan sonra bağlam penceresine girer. Bu nedenle dosya dökümde, tutulan tüm günlüklerde ve ajanın bundan sonra yazdığı her içerikte yer alır.
Önceden anahtar, ajanın çalıştığı ağaçta bulunuyordu:
cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billingSonrasında dosya erişim dışına taşındı:
sudo install -d -m 750 -o root -g agent-review /etc/agent-review
sudo install -m 640 -o root -g agent-review ~/projects/billing/.env /etc/agent-review/billing.env
rm ~/projects/billing/.envAjanın kullanıcısı dosyayı artık açamaz. Çünkü çalışma ağacında dosya bulunmaz. Ajanın kendi yapılandırmasındaki reddetme kuralları ikinci katmandır. İlk katman değildir. Claude Code, projedeki .claude/settings.json dosyasından izin kurallarını okur:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
}
}Bu, ajanın dosyaları incelerken yanlışlıkla bir dosya açmasını engeller. Ancak enjekte edilmiş bir talimatın base64 .env çalıştırmasını engellemez. Çünkü bu bir shell komutudur ve dosya okuma işlemi değildir. Yapılandırma dosyasını güvenlik önlemi, dosya sistemi izinlerini ise bariyer olarak değerlendirin. Aynı ayrım container içinde de geçerlidir: Docker Compose içindeki env dosyaları ve gizli bilgiler bu sorunun bir katman alttaki sürümünü ele alır.
Her aracı ayrı bir ayrıcalıksız kullanıcıyla çalıştırın
Aracı sizin hesabınızla çalıştırırsanız SSH anahtarlarınızı, bulut kimlik bilgilerinizi ve kabuk geçmişinizi devralır. Ayrı bir kullanıcı oluşturmak tek bir komut gerektirir ve bunların tümüne erişimi kaldırır.
sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519Son satır cat: /home/you/.ssh/id_ed25519: Permission denied ile başarısız olmalıdır. Bunun yerine bir anahtar yazdırılırsa giriş dizininiz grup veya diğer kullanıcılar tarafından okunabilir durumdadır; chmod 700 ~ bunu düzeltir. Aracı kullanıcıyı sudo grubuna eklemeyin ve gerçekten ihtiyaç duyduğu tek komuttan daha geniş bir NOPASSWD kuralı vermeyin. Bir VPS'te en az ayrıcalıklı kullanıcılar, grup ve sudoers ayrıntılarını açıklar.
Bulut VPS üzerinde bir sınır daha eklenmelidir. Örnek meta veri hizmeti sabit bir link-local adreste yanıt verir ve istekte bulunan her şeye çoğu zaman rol kimlik bilgileri sağlar.
sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECTBunu aracının bulunduğu taraftan denetleyin. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ hiçbir şey yazdırmamalı ve sıfır olmayan bir çıkış koduyla sonlanmalıdır; çünkü paket sunucudan çıkmadan önce reddedilir.
Kimlik bilgisini sınırda enjekte edin
Bu sorunu gerçekten çözen yaklaşım, kimlik bilgisi enjeksiyonudur. Agent hiçbir zaman gerçek bir cryptographic key tutmaz. İsteğini yerel bir gateway üzerinden gönderir. Gateway, dışarı gönderirken bir yer tutucuyu gerçek secret ile değiştirir. Secret, gateway'in depolamasında, farklı bir process içinde ve farklı bir user'a ait olarak tutulur.
OneCLI, bunun Apache-2.0 lisanslı bir open source uygulamasıdır ve agent'ın yanında bir container olarak çalışır. Temmuz 2026 itibarıyla proje bu kurulumu belgelendirir:
git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --waitDashboard, 10254 portunu; gateway ise 10255 portunu dinler. Gerçek kimlik bilgisini bir kez depolarsınız. Ardından her agent'a key yerine bir yer tutucu değer ve kendi kapsamı belirlenmiş access token'ını verirsiniz. Agent, bu token'ı bir Proxy-Authorization header'ında gönderir. Gateway, dışarı giden isteği host ve path bilgilerine göre eşleştirir, eşleşen kimlik bilgisinin şifresini çözer ve kimlik bilgisini yer tutucunun yerine koyar. Agent'ın ortamında çalınmaya değer hiçbir bilgi bulunmaz.
Buradaki değer encryption değildir. Değer, "bu agent ne kullandı ve ne zaman kullandı" sorusunun bir log sorgusuna dönüşmesidir. Key'in altı ortamdan hangisinde kopyalandığını tahmin etmek yerine tek bir audit trail'i okursunuz.
Gizli bilgiyi ortama değil, sürece verin
Aracıyı systemd altında çalıştırıyorsanız ortam değişkenlerine hiç ihtiyacınız yoktur. LoadCredential= gizli bilgiyi yalnızca ilgili hizmetin okuyabileceği özel bir dizine yerleştirir. Bu dizin birim dosyasında %d, süreç içinde ise $CREDENTIALS_DIRECTORY olarak görünür. Değer /proc/<pid>/environ içinde hiçbir zaman görünmez. Bu nedenle ps eww değeri gösteremez. Dizin, hizmet durduğunda kaldırılır.
Önce kimlik bilgilerini makine için şifreleyin. Bu komutlar systemd belgelerinden alınmıştır ve Ubuntu 24.04 ile Debian 13'ü kapsayan systemd 250 veya daha yeni sürümlerde çalışır:
echo -n 'sk-example-value' > /tmp/plain.txt
sudo systemd-creds encrypt --name=api_key /tmp/plain.txt /etc/credstore/api_key.cred
shred -u /tmp/plain.txt
sudo systemd-run -P --wait -p LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred \
systemd-creds cat api_keySon komut sk-example-value çıktısını verir. Bu, şifrelenmiş dosyanın bu ana bilgisayarda çözülebildiğini doğrular. Ardından dosyaya birimden başvurun:
[Service]
User=agent-review
LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred
Environment=AGENT_KEY_FILE=%d/api_key
ExecStart=/usr/local/bin/agent-workerAracı kodu değere ihtiyaç duyduğunda $AGENT_KEY_FILE konumundaki dosyayı açar. Dosya okuma işlemi anlıktır. Ortam değişkeni, sürecin ömrü boyunca ve oluşturduğu tüm alt süreçlerde varlığını sürdürür.
Uzun ömürlü anahtarlar yerine kısa ömürlü belirteçleri tercih edin
Süresi hiç dolmayan bir anahtar, aylar sonra bir günlükte veya oturum kaydında ortaya çıktığında hâlâ geçerlidir. Hizmet bir oturum belirteci sunuyorsa oturum belirtecini kullanın ve işin izin verdiği en kısa geçerlilik süresini ayarlayın.
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/agent-readonly \
--role-session-name agent-review \
--duration-seconds 900On beş dakika, AWS STS (güvenlik belirteci hizmeti) tarafından kabul edilen minimum süredir ve genellikle tek bir aracı görevi için yeterlidir. GitHub için aracı kullanıcısına kendi gh oturum açma hesabını verin ve üzerinde çalıştığı tek depoyla sınırlı, ayrıntılı izin kapsamına sahip bir belirteç kullanın; böylece bu oturum içindeki gh auth token başka hiçbir kaynağa erişemeyen bir sonuç döndürür. Önce kaynak kapsamını, ardından süreyi sınırlayın.
Doğrulayın, ardından doğrulamayı sürdürün
Bir aracının kurulumunda yapılan herhangi bir değişiklikten sonra üç kontrol çalıştırılmalıdır. Bu kontroller, kendi hesabınızla değil aracının kullanıcısı olarak çalıştırılmalıdır.
sudo -u agent-review env | grep -iE 'key|token|secret'
sudo -u agent-review ls -la /home/you/ 2>&1 | head -3
sudo -u agent-review curl -s -o /dev/null -w '%{http_code}\n' --max-time 5 https://api.github.com/userİlk kontrol hiçbir çıktı üretmemelidir. İkincisi ls: cannot open directory '/home/you/': Permission denied çıktısını üretmelidir. Üçüncüsü, aracının ağ yolu üzerinden hangi kimliği sunduğunu gösterir. Ağ geçidi deseni bu soruyu yanıtlamak için kullanılır: 401, aracının kendisine ait bir GitHub kimlik bilgisi taşımadığı; 200 ise bir kimlik bilgisi taşıdığı anlamına gelir. Bu durumda hangi belirteç olduğunu bilmeniz gerekir. Araçları gözetimsiz çalıştırıyorsanız, bir VPS üzerinde AI aracısı maliyetlerini denetleme bu erişim sınırlarını tamamlayan bütçe sınırlarını açıklar.
FAQ
Modele anahtarlarımı sızdırmayacağına güvenebilir miyim?
Hayır. Çünkü bu tehdit modelinde saldırgan model değildir. Agent, web sayfalarından, depolardan ve issue tracker'larından metin okur. Bu metin talimatlar içerebilir. Model, talimatlarınızı getirdiği metinden güvenilir biçimde ayıramaz. Herhangi bir denetim, modelin doğru seçimi yapmasına bağlıysa ikna edici bir enjeksiyon talimatıyla ilk kullanımda başarısız olur. Bu nedenle denetim işletim sisteminde veya ağda uygulanmalıdır.
Agent secret'ları için environment variable'lar gerçekten bu kadar sakıncalı mı?
Belirli bir nedenle sakıncalıdır: devralınırlar. Agent'ın başlattığı her alt işlem, bir build script'i, test runner'ı ve herhangi bir package install hook dahil olmak üzere bu değişkenlerin bir kopyasını alır. Değişkenler, aynı kullanıcı tarafından /proc/<pid>/environ üzerinden de okunabilir. Bu nedenle agent'ın çalıştırdığı her şey, agent bunları aktarmadan okuyabilir. Kullanım anında, LoadCredential= veya bir gateway aracılığıyla okunan bir dosya, erişimi yalnızca o anla sınırlar.
Secret'ları bir vault'a koymak bu sorunu tek başına çözer mi?
Yalnızca kısmen. Vault, depolama sorununu çözer. Ancak son adımı çözmez: bir bileşen secret'ı vault'tan alıp agent'a environment variable olarak verir. Bu durumda başlangıçtaki duruma dönülür. Önemli olan substitution işlemini kimin yaptığıdır. Agent secret'ı alırsa secret agent'ın elindedir. Bir gateway veya init system substitution işlemini agent'ın process'i dışında yaparsa agent secret'ı hiçbir zaman elinde tutmaz.
Bir agent'ın daha önce bir şeyi sızdırıp sızdırmadığını nasıl öğrenebilirim?
Genellikle olaydan sonra bunu belirleyemezsiniz. Gateway kullanılması için temel gerekçe budur. Gateway olmadan kanıtlar shell history, agent'ın transcript'i ve muhtemelen tutmadığınız outbound connection log'ları arasında dağılır. Credential gateway kullanıldığında credential'ın her kullanımı agent identity'si ve timestamp içeren tek bir satırdır. Sızıntıdan şüpheleniyorsanız önce key'i rotate edin, sonra inceleyin. Rotation ucuzdur; kesinlik değildir.
Bugün yapmam gereken en az şey nedir?
Her .env dosyasını agent'ların çalıştığı dizinlerin dışına taşıyın ve her agent için bir unprivileged user oluşturun. Bu iki değişiklik yaklaşık 10 dakika sürer ve en yaygın yolu kapatır: agent'ın kodun yanında bulunması gerekmeyen bir credential dosyasını okuması. Gateway ve kısa ömürlü token'lar sonraki adımdır; ilk adım değildir. Aynı başlangıç noktası, VPS üzerinde bir autonomous agent'ı güvenli biçimde çalıştırma dahil olmak üzere tüm agent runtime'ları için geçerlidir.