SSD Nodes Learn Hosting plans →
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-13

Yapay zeka ajanlarında API anahtarı güvenliği nasıl

Yapay zeka ajanlarına API anahtarı vermek yerine kapsamı sınırlandırılmış kısa ömürlü tokenlar kullanın. Prompt injection riskine karşı kimlik bilgisi ağ geçidi kurun.

Yapay zeka ajanlarından sırları uzak tutmak ne anlama gelir

Yapay zeka ajanı, komutları çalıştıran standart bir Linux sürecidir. Bu sürecin sahip olduğu her ortam değişkeni, çalıştırdığı kod tarafından okunabilir; dolayısıyla ajanın ortamındaki bir API anahtarı, ajanın erişebildiği herhangi bir sunucuya gönderebileceği bir anahtardır. Sırları ajandan uzak tutmak, ona anahtar yerine bir tutamaç (handle) 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 mekanizmanın gerçek değerle değiştireceği bir yer tutucu.

Bu, bir modelin kötü niyetli hale gelmesiyle ilgili bir hikaye değildir. Mekanizma çok daha basittir. Bir ajan; talimatlar içeren bir web sayfasını, bir README dosyasını veya bir sorun yorumunu okur ve bunları takip eder; çünkü bir dil modeli için sizin yazdığınız metin ile kendi getirdiği metin arasında hiçbir fark yoktur. Buna prompt injection denir. Bu gerçekleştiğinde, verilecek hasar tam olarak tek bir şeyle sınırlıdır: sürecin okuyabildiği veriler. Henüz bir sınır belirlemediyseniz, bir kodlama ajanını sunucuda güvenli bir şekilde çalıştırmak rehberi, bu kılavuzun üzerine inşa edildiği izolasyon basamaklarını ele almaktadır.

Tehdit modeli basit terimlerle

Bunu, aracınızın (agent) çalıştığı kullanıcı yetkileriyle çalıştırın.

tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'

Yazdırdığı her satır, yabancı bir sunucuya gönderilecek bir HTTP isteği kadar uzaktadır. Şimdi aracın yakınındaki diskte neler olduğ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'

Bir kabuk (shell) erişimine sahip aracın, verileri dışarı çıkarmak için zekice bir istismara ihtiyacı yoktur. Dört sıradan yol bu işi görür ve dördü de log kayıtlarında normal bir işlem gibi görünür:

  • Değerin sorgu dizisinde (query string) yer aldığı, herhangi bir sunucuya yönelik giden bir curl veya fetch isteği.
  • Aracın yazma yetkisine sahip olduğu bir depoya yönelik git commit ve git push işlemi.
  • Aracın kullanıcısı yetkileriyle rastgele kod çalıştıran bir paket yükleme betiği.
  • HTTP çıkışı engellendiğinde bile çalışan, değerin içinde bulunduğu bir ana bilgisayar adının DNS sorgusu.

Bu durumu sadece inceleme yaparak çözemezsiniz. Çözüm, erişim mesafesinde değerli hiçbir şeyin kalmadığından emin olmaktır.

Çalışma dizinindeki bir gizli anahtar, bağlam penceresindeki bir gizli anahtardır

Bir ajan dosyaları okur. Üzerinde çalıştığı depodaki bir .env dosyası okunacaktır ve okunduğu anda bağlam penceresine girer; bu da dosyanın transkripte, tuttuğunuz herhangi bir günlüğe ve ajanın bir sonraki adımda yazdığı her şeye dahil olduğu anlamına gelir.

Öncesinde, anahtar ajanın çalıştığı dizinde dururken:

cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billing

Sonrasında, dosya erişilemeyecek bir yere taşındığında:

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/.env

Ajanın kullanıcısı artık dosyayı açamaz, çünkü çalışma dizini artık dosyayı içermemektedir. Ajanın kendi yapılandırmasındaki reddetme kuralları ilk değil, ikinci bir katmandır. Claude Code, izin kurallarını projedeki .claude/settings.json dosyasından okur:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
  }
}

Bu, ajanın keşif yaparken bir dosyayı açması gibi dürüst hataları engeller. Ancak, enjekte edilmiş bir talimatın base64 .env çalıştırmasını engellemez, çünkü bu bir dosya okuma işlemi değil, bir kabuk komutudur. Aynı sınırlama, ajanın izinlerinden ziyade alışkanlıklarını şekillendiren her şey için geçerlidir: ajanı çalışan en küçük değişikliğe bağlı tutan bir beceri, bir çalıştırmanın işi olmayan dosyalara girmesini engeller ancak bu yine de modelin ikna edilerek vazgeçirilebileceği bir tavsiyedir. Yapılandırmayı bir korkuluk, dosya sistemi iznini ise duvar olarak değerlendirin. Aynı ayrım konteynerler içinde de geçerlidir: Docker Compose içindeki env dosyaları ve gizli anahtarlar, bu sorunun bir katman alttaki versiyonunu ele alır.

Her aracıya kendi yetkisiz kullanıcısını atayın

Aracı sizin kullanıcı hesabınızla çalışırsa, SSH anahtarlarınızı, bulut kimlik bilgilerinizi ve komut geçmişinizi devralır. Ayrı bir kullanıcı oluşturmak tek bir komut gerektirir ve tüm bu riskleri ortadan kaldırır.

sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519

Son satır cat: /home/you/.ssh/id_ed25519: Permission denied ile başarısız olmalıdır. Eğer bir anahtar çıktısı veriyorsa, ev dizininiz grup veya herkes tarafından okunabilir durumdadır; chmod 700 ~ bu sorunu düzeltir. Aracı kullanıcısını sudo grubuna eklemeyin ve ona gerçekten ihtiyaç duyduğu tek komuttan daha geniş bir NOPASSWD kuralı tanımlamayın. VPS üzerinde en az yetkili kullanıcılar bölümü, grup ve sudoers yapılandırmasının ayrıntılarını ele almaktadır.

Bulut tabanlı bir VPS üzerinde bir sınır daha eklemekte fayda vardır. Örnek meta veri servisi, sabit bir yerel bağlantı adresinden yanıt verir ve genellikle talep eden her şeye rol kimlik bilgilerini sunar.

sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECT

Bunu aracının tarafından kontrol edin. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ hiçbir çıktı vermemeli ve sıfırdan farklı bir değerle çıkmalıdır; çünkü paket kutudan çıkmadan önce reddedilmiş olur.

Kimlik bilgisini sınırda enjekte edin

Bu sorunu gerçekten çözen model, kimlik bilgisi enjeksiyonudur. Ajan hiçbir zaman gerçek bir anahtarı tutmaz. İsteğini yerel bir ağ geçidi üzerinden gönderir ve ağ geçidi, istek dışarı çıkarken yer tutucuyu gerçek gizli veriyle değiştirir. Gizli veri, ağ geçidinin depolama alanında, farklı bir süreçte ve farklı bir kullanıcıya ait olarak barındırılır.

OneCLI, Apache-2.0 lisanslı bu yaklaşımın açık kaynaklı bir uygulamasıdır ve ajanın yanında bir container olarak çalışır. Temmuz 2026 itibarıyla proje bu kurulumu şu şekilde belgelemektedir:

git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --wait

Dashboard 10254 numaralı portu, ağ geçidi ise 10255 numaralı portu dinler. Gerçek kimlik bilgisini bir kez depolarsınız, ardından her ajana anahtar yerine bir yer tutucu değer ve kendi kapsamlı erişim belirtecini (token) verirsiniz; ajan bunu bir Proxy-Authorization başlığında gönderir. Ağ geçidi, giden isteği ana bilgisayar ve yol bilgisine göre eşleştirir, eşleşen kimlik bilgisinin şifresini çözer ve yerini değiştirir. Ajanın ortamında çalınmaya değer hiçbir veri bulunmaz.

Buradaki değer şifrelemeden gelmez. "Bu ajan neyi, ne zaman kullandı" sorusunun bir log sorgusuna dönüşmesinden gelir. Altı farklı ortamdan hangisinin anahtarın bir kopyasını tuttuğunu tahmin etmek yerine, tek bir denetim izini (audit trail) okursunuz.

Gizli veriyi ortama değil, sürece iletin

Agent'ı systemd altında çalıştırıyorsanız, ortam değişkenlerine (environment variables) hiç ihtiyacınız yoktur. LoadCredential=, gizli veriyi yalnızca ilgili servisin okuyabildiği özel bir dizine yerleştirir; bu dizin unit dosyasında %d olarak, süreç içinde ise $CREDENTIALS_DIRECTORY olarak sunulur. Değer hiçbir zaman /proc/<pid>/environ içinde görünmez, bu nedenle ps eww bunu görüntüleyemez ve servis durduğunda dizin ortadan kalkar.

Kimlik bilgisini önce makineye özel olarak şifreleyin. Aşağıdaki komutlar systemd belgelerinden alınmıştır ve Ubuntu 24.04 ile Debian 13 sürümlerini 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_key

Son komut sk-example-value çıktısını verir. Bu, şifrelenmiş dosyanın bu ana makinede çözülebildiğini kanıtlar. Ardından, unit dosyasından bu dosyaya referans verin:

[Service]
User=agent-review
LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred
Environment=AGENT_KEY_FILE=%d/api_key
ExecStart=/usr/local/bin/agent-worker

Agent kodunuz, değere ihtiyaç duyduğunda $AGENT_KEY_FILE adresindeki dosyayı açar. Dosya okuma işlemi anlıktır. Ortam değişkeni ise sürecin ömrü boyunca, oluşturduğu her alt süreçte varlığını korur.

Uzun ömürlü anahtarlar yerine kısa ömürlü belirteçleri tercih edin

Asla süresi dolmayan bir anahtar, aylar sonra bir günlük kaydında veya dökümde ortaya çıksa bile geçerliliğini korur. Servis bir oturum belirteci (session token) sunuyorsa, bu belirteci kullanın ve işin gerektirdiği en kısa ömrü atayın.

aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/agent-readonly \
  --role-session-name agent-review \
  --duration-seconds 900

On beş dakika, AWS STS (security token service) tarafından kabul edilen minimum süredir ve genellikle tek bir aracı görevi için yeterlidir. GitHub için, aracı kullanıcıya kendi gh girişini verin ve üzerinde çalıştığı tek bir depo ile sınırlandırılmış, ayrıntılı bir belirteç atayın; böylece o oturum içindeki gh auth token komutu başka hiçbir şeye erişemeyen bir sonuç döndürür. Kısıtlamayı önce kaynak bazında, ardından zaman bazında yapın.

Doğrulama ve sürekli denetim

Bir aracının kurulumunda yapılan her değişiklikten sonra üç kontrolün çalıştırılması önerilir. Bu kontrolleri kendi kullanıcınızla değil, aracının kullanıcısı ile çalıştırın.

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 komut hiçbir çıktı üretmemelidir. İkinci komut ls: cannot open directory '/home/you/': Permission denied çıktısını vermelidir. Üçüncü komut, aracının ağ yolunun hangi kimliği sunduğunu gösterir; bu, gateway modelinin yanıtlamak için var olduğu sorudur: 401 ifadesi, aracının kendisine ait bir GitHub kimlik bilgisi taşımadığı, 200 ifadesi ise bir kimlik bilgisi taşıdığı anlamına gelir; dolayısıyla hangi token'ın kullanıldığını bilmeniz gerekir. Eğer aracıları gözetimsiz çalıştırıyorsanız, bir VPS üzerinde yapay zeka aracı maliyetlerini kontrol etme rehberi, bu erişim sınırlarıyla birlikte uygulanması gereken bütçe limitlerini kapsamaktadır.

FAQ

Modelin anahtarlarımı sızdırmayacağına güvenebilir miyim?

Hayır, çünkü bu tehdit modelinde saldırgan model değildir. Ajan; web sayfalarından, depolardan ve hata takip sistemlerinden metin okur ve bu metinler komutlar içerebilir. Modelin, sizin verdiğiniz talimatları getirdiği metinlerden ayırt etmesinin güvenilir bir yolu yoktur. Modelin doğru seçimi yapmasına dayanan her kontrol, enjekte edilen bir komut ikna edici olduğu anda başarısız olur; bu nedenle kontrolün işletim sistemi veya ağ katmanında yer alması gerekir.

Ajan sırları için ortam değişkenleri gerçekten bu kadar kötü mü?

Belirli bir yönden kötüdürler: miras alınırlar. Ajanın oluşturduğu her alt süreç; bir derleme betiği, test çalıştırıcısı ve paket kurulum kancası dahil olmak üzere değişkenlerin bir kopyasını alır. Değişkenler aynı kullanıcı tarafından /proc/<pid>/environ üzerinden de okunabilir; bu nedenle ajanın çalıştırdığı her şey, ajan onları iletmesine gerek kalmadan değişkenleri okuyabilir. Kullanım anında okunan bir dosya, LoadCredential= veya bir ağ geçidi ile, maruziyeti yalnızca o an ile sınırlandırır.

Sırları bir kasaya (vault) koymak bu sorunu tek başına çözer mi?

Sadece kısmen. Kasa, depolamayı düzeltir. Bir şeyin sırrı kasadan çekip ajana ortam değişkeni olarak verdiği son adımı düzeltmez; bu da sizi başladığınız noktaya geri döndürür. Önemli olan, yer değiştirme işlemini kimin yaptığıdır. Eğer sırrı ajan çekerse, sır ajanın elindedir. Eğer bir ağ geçidi veya init sistemi yer değiştirme işlemini ajanın süreci dışında gerçekleştirirse, ajan sırra hiçbir zaman sahip olmaz.

Bir ajanın halihazırda bir şey sızdırıp sızdırmadığını nasıl anlarım?

Genellikle olay gerçekleştikten sonra bunu anlayamazsınız; ağ geçidi kullanmanın temel argümanı da budur. Ağ geçidi olmadan kanıtlarınız; kabuk geçmişi, ajanın transkripti ve muhtemelen tutmadığınız giden bağlantı günlükleri arasında dağılmış durumdadır. Bir kimlik bilgisi ağ geçidi ile, her kimlik bilgisi kullanımı ajan kimliği ve zaman damgası içeren tek bir satırdır. Bir sızıntıdan şüpheleniyorsanız, önce anahtarı yenileyin, sonra araştırın. Yenileme işlemi kolaydır, kesinlik ise değildir.

Bugün yapmam gereken minimum şey nedir?

Her .env dosyasını ajanlarınızın çalıştığı dizinlerden taşıyın ve her ajan için ayrı, yetkisiz bir kullanıcı oluşturun. Bu iki değişiklik yaklaşık on dakika sürer ve kodun yanında durması için hiçbir neden olmayan bir kimlik bilgisi dosyasını ajanın okuması gibi en yaygın yolu kapatır. Ağ geçidi ve kısa ömürlü token'lar ilk adım değil, bir sonraki adımdır. Aynı başlangıç noktası, bir VPS üzerinde otonom ajan çalıştırma dahil olmak üzere her ajan çalışma zamanı için geçerlidir.