Pickle mı Safetensors mı? Model Dosya Formatlarında Kod Çalıştırma Riski
7 formatın deserialization risk tablosu
Bir model dosyasını yüklemek çoğu zaman "veri okumak" değil, "kod çalıştırmak" demektir. Pickle tabanlı formatlar dosyayı açtığınız anda keyfi komut çalıştırabilir; safetensors ise tasarımı gereği bunu yapamaz. Aradaki farkı opcode ve operatör düzeyinde görmek, tedarik zinciri güvenliğinin en somut kararıdır.
Model dosya formatı güvenliği nedir?
Model dosya formatı güvenliği, bir yapay zeka modelinin diske serileştirilme biçiminin — ağırlıkların, meta verinin ve bazı formatlarda gömülü mantığın hangi kodlamayla saklandığının — o dosya yüklendiğinde saldırgan kontrollü kod çalıştırılmasına izin verip vermediğini inceleyen alt disiplindir. Kritik ayrım şudur: bazı formatlar dosyayı yüklemeyi saf veri okuma işlemi olarak tutar; bazıları ise yükleme sırasında rastgele fonksiyon çağırmaya izin veren bir serileştirme protokolü kullanır. İkinci gruptaki bir dosyayı torch.load() veya joblib.load() ile açmak, pratikte tanımadığınız bir betiği çalıştırmakla eşdeğerdir.
Bu yüzden model indirmek, klasik bir tedarik zinciri kararıdır: modeli nereden aldığınız kadar, hangi formatta aldığınız da saldırı yüzeyini belirler. Güvenilmeyen bir kaynaktan gelen pickle tabanlı bir ağırlık dosyası, imzalı bir paket kadar ciddiye alınması gereken bir yürütülebilir eserdir.
Pickle neden kod çalıştırır?
Python'un pickle modülü bir serileştirici değil, küçük bir sanal makinedir. Dosya, bir yığın (stack) makinesi için opcode akışıdır; pickle.load() bu opcode'ları sırayla yorumlar. Sorun, protokolün nesne yeniden inşasını fonksiyon çağrısıyla modellemesidir.
GLOBAL/STACK_GLOBAL: bir modül ve isim çiftinden herhangi bir Python nesnesini (örneğinos.system,builtins.eval,subprocess.Popen) yığına yükler.REDUCE: yığındaki çağrılabiliri, yine yığındaki argümanlarla çağırır — yani gerçek yürütme burada gerçekleşir.- Bir sınıfın
__reduce__/__reduce_ex__metodu, o nesnenin nasıl "yeniden kurulacağını" tanımlar; saldırgan buraya(os.system, ("komut",))döndürerek yükleme anında komut çalıştırır.
Yani zararlı bir pickle, geçerli ve çoğu zaman fonksiyonel bir model dosyasıdır; sadece opcode akışına yükleme sırasında tetiklenen birkaç çağrı gizlenmiştir. Python resmi belgeleri bu davranışı doğrudan uyararak belirtir: güvenilmeyen veriyi asla unpickle etmeyin.
Pickle ailesi: joblib ve PyTorch .bin de aynı riski taşır
Yaygın bir yanılgı, riskin yalnızca .pkl uzantılı dosyalarda olduğudur. Gerçekte pickle bir ailedir ve popüler formatların çoğu onun üstüne kuruludur:
- joblib: scikit-learn ekosisteminde standarttır; ayrı bir güvenlik modeli yoktur, altında pickle protokolünü kullanır. "Ayrı format" gibi görünse de aynı REDUCE/GLOBAL tetikleyicilerine açıktır.
- PyTorch .bin / .pt:
torch.savevarsayılan olarak pickle sarmalayıcısı üretir;torch.loadbunu unpickle eder. PyTorch, güvenlik gerekçesiyleweights_only=Trueseçeneğini 2.6 sürümünden itibaren varsayılan hâline getirdi — bu mod, izin listesi dışındaki genel çağrılabilirleri reddederek saldırı yüzeyini daraltır. Ancak eski kod ve eski ağırlıklar hâlâ sınırsıztorch.loadile yükleniyor.
Kısaca: uzantıya değil, altta yatan serileştirme protokolüne bakın. .bin, .pt, .pkl, .joblib ve .ckpt pratikte aynı tehdit sınıfındadır.
Safetensors gerçekten güvenli mi?
Evet — ve nedeni mimari bir tercihtir, iyi niyet değil. Safetensors formatı iki parçadan oluşur: başta bir JSON başlığı (tensör adları, veri tipleri, şekiller ve bayt aralıkları) ve ardından ham tensör baytları. Format içinde çağrılabilir nesne, opcode, fonksiyon referansı ya da "nesneyi yeniden kur" mekanizması yoktur. Yükleyici yalnızca başlığı ayrıştırır, aralıkları okur ve baytları tensöre eşler. Kod çalıştıracak bir yol tanım gereği bulunmadığı için, güvenilmeyen bir safetensors dosyasını yüklemek uzaktan kod çalıştırma vektörü açmaz.
Bu, safetensors'un her riski sıfırladığı anlamına gelmez. Bozuk bir başlık ayrıştırıcıyı zorlayabilir, kötü şekillendirilmiş uzunluk alanları hizmet reddi (DoS) veya aşırı bellek ayırma denemesi doğurabilir. Ama bunlar bellek güvenliği ve girdi doğrulama sınıfındaki sorunlardır — pickle'daki "yükleme = yürütme" sınıfından niteliksel olarak farklıdır. Pratik sonuç nettir: bir modelin safetensors sürümü mevcutsa, pickle sürümünü tercih etmek için hiçbir güvenlik gerekçesi yoktur.
GGUF, ONNX ve TensorFlow SavedModel: abartısız risk seviyeleri
Bu üç formatı "hepsi tehlikeli" ya da "hepsi güvenli" diye tek kefeye koymak yanlış olur; her birinin risk profili farklıdır.
- GGUF (llama.cpp ekosistemi): büyük ölçüde veri-only bir formattır. Meta veri anahtar-değer çiftleri ve nicemlenmiş tensörler taşır; içinde serileştirilmiş çağrılabilir mantık yoktur. Buradaki gerçekçi risk, kod çalıştıran opcode değil, ayrıştırıcıdaki bellek güvenliği hatalarıdır (hatalı uzunluk/ofset alanlarının tetiklediği taşmalar). Yani risk kaynağı formatın kendisi değil, onu okuyan C/C++ ayrıştırıcısının sağlamlığıdır.
- ONNX: standart operatör grafiği veri-only'dur. Risk koşulludur: model özel bir operatöre (custom op) referans veriyorsa ve çalışma ortamı bu operatörü sağlayan yerel bir uzantıyı yüklüyorsa, yürütme o yerel kodda gerçekleşir. Yani tehlike ONNX baytlarında değil, güvenilmeyen özel operatör kütüphanelerini kaydetme pratiğindedir.
- TensorFlow SavedModel: en incelikli olanıdır. Serileştirilmiş grafik, dosya sistemine erişen operatörler (örneğin
ReadFile/WriteFile) veya kerasLambdakatmanı gibi gömülü Python mantığı içerebilir. Bu yollar, güvenilmeyen bir SavedModel'i yüklemeyi/çalıştırmayı gerçek bir kod ve dosya erişimi riskine dönüştürür. Bu yüzden SavedModel'i pickle'a yakın, ancak koşullu bir risk sınıfında değerlendiriyoruz.
Yedi formatlı model dosyası risk tablosu
Aşağıdaki tablo, bir modeli yüklerken sorulması gereken üç soruyu tek bakışta toparlıyor: kod çalıştırma yolu var mı, hangi mekanizma üzerinden, statik bir tarayıcı bunu yakalayabilir mi. Türkçe kaynaklarda az işlenen bu karşılaştırmayı, yükleme öncesi karar vermek için başvuru olarak kullanabilirsiniz.
| Format | Kod çalıştırma yolu? | Mekanizma (opcode/operatör) | Tarayıcı yakalar mı? | Risk |
|---|---|---|---|---|
| pickle (.pkl) | Evet | REDUCE / GLOBAL / STACK_GLOBAL, __reduce__ | Kısmen (statik opcode taraması) | Yüksek |
| joblib (.joblib) | Evet (pickle ailesi) | Aynı pickle opcode'ları | Kısmen | Yüksek |
| PyTorch .bin / .pt | Evet (pickle sarmalı) | pickle opcode + persistent_load | Kısmen; weights_only daraltır | Yüksek |
| safetensors | Hayır (tasarım gereği) | Yok — JSON başlığı + ham tensör | Gerek yok (başlık DoS'u ayrı) | Düşük |
| GGUF | Büyük ölçüde hayır (veri-only) | Yok; ayrıştırıcı bellek hataları | Sınırlı (yapı doğrulama) | Düşük-Orta |
| ONNX | Koşullu | Özel operatör / yerel runtime uzantısı | Kısmen (custom-op referansı) | Orta |
| TF SavedModel | Evet (koşullu) | Lambda katmanı / dosya op'ları (ReadFile) | Sınırlı | Orta-Yüksek |
"Tarayıcı yakalar mı?" kolonundaki "kısmen" ifadesi kasıtlıdır: statik pickle tarayıcıları bilinen tehlikeli global referanslarını (os, subprocess, builtins) yakalar, ancak dolaylı gadget zincirleri ve obfüskasyon tekniklerine karşı garanti vermezler. Tarama, güvenli varsayılanın (safetensors) yerine geçmez; onu tamamlar.
Zararlı model dosyasını tespit etmek: gerçek tetik listesi
AltaySec'in hf-dataset-scan CI tarayıcısını kurarken çıkardığımız pratik ders şuydu: pickle taramasında "yakalanacak şey" soyut değil, oldukça somut bir işaret kümesidir. Aşağıdaki liste, bir pickle akışını yüklemeden statik olarak incelerken alarm ürettiğimiz gerçek deserialization tetikleyicileridir (AltaySec'in kendi tarayıcı kuralları):
GLOBAL/STACK_GLOBALileos,posix,nt,subprocess,sys,socket,builtinsmodüllerine referans,builtins.eval,builtins.exec,builtins.compile,__import__gibi çağrılabilirlerin yüklenmesi,REDUCEopcode'unun tehlikeli bir global ile aynı yığın bağlamında görünmesi,- PyTorch dosyalarında
persistent_loadüzerinden depolama yeniden eşleme gadget'ları, - bilinen zararlı sınıf/fonksiyon imzaları ve şüpheli modül-isim çiftleri.
Bu tarayıcı kod eserini değil, gömülü veriyi hedefler; ama aynı ilke model ağırlıklarına birebir taşınır. CI hattınıza koyacağınız kural basittir: güvenilmeyen kaynaktan gelen pickle tabanlı bir dosya, yükleme öncesi statik taramadan geçmeden üretime giremez. Daha geniş tedarik zinciri bağlamı için HuggingFace model hub tedarik zinciri riskleri ve model imzalama ve provenance yazılarımız bu taramayı imza doğrulamayla birleştirir.
Pratik savunma: format hijyeni ve çalışma zamanı sınırları
Doğru refleks, tek tek CVE kovalamak değil, format hijyenini varsayılan hâle getirmektir:
- Safetensors'u varsayılan seçin. Bir modelin safetensors sürümü varsa, pickle sürümünü indirmeyin. Mümkünse depo politikanızı safetensors'a kilitleyin.
- PyTorch'ta
weights_only=Truekullanın. Eski ağırlıkları yüklerken bile bu mod, izin listesi dışı çağrılabilirleri reddederek en yaygın vektörü kapatır. - Yükleme öncesi tarayın. Pickle/joblib/.bin dosyalarını üretime almadan önce statik opcode taramasından geçirin ve sonucu CI kapısı yapın.
- Yüklemeyi izole edin. Kaçınılmaz olarak güvenilmeyen bir pickle'ı açmanız gerekiyorsa, ağ ve dosya sistemi erişimi kısıtlı bir sandbox içinde, en az yetki ilkesiyle yapın.
- Provenance zincirini doğrulayın. İmza ve kaynak doğrulaması, formatın taşıdığı riski tümüyle ortadan kaldırmasa da güvenilmeyen eserin üretime sızma olasılığını düşürür.
Çalışma zamanında, model çıktısı ve araç çağrılarını denetleyen bir LLM güvenlik duvarı katmanı (AltaySec Guardian gibi) bu tedarik zinciri kontrollerinin tamamlayıcısıdır; ama tekrar edelim: çalışma zamanı savunması, yükleme anında kod çalıştıran bir dosyayı hiç almamış olmanın yerine geçmez. Model formatı güvenliğinde en ucuz kazanç, riski daha üretilmeden formatta budamaktır. Kurumsal bir model tedarik politikası kurmak için bizimle iletişime geçebilirsiniz.
Kaynaklar
- Python belgeleri — pickle güvenlik uyarısı
- Hugging Face — Pickle Scanning ve güvenlik
- Hugging Face — Safetensors dokümantasyonu
- PyTorch — torch.load ve weights_only güvenliği
- Trail of Bits — fickling (pickle statik analiz aracı)
- picklescan — model dosyası zararlı pickle tarayıcısı
- OWASP — LLM03:2025 Supply Chain
- AltaySec Ekosistem — hf-dataset-scan
