Modele AI bez malware: Pickle kontra SafeTensors
Pickle, SafeTensors, ONNX i checkpointy modeli AI: poznaj ryzyka wykonania kodu, bezpieczny pipeline importu oraz kontrolę łańcucha dostaw.
- AUTOR
- Karol Rapacz / Pentester (OSCP, PNPT)
- PUBLIKACJA
- 16 maja 2026
- CZAS CZYTANIA
- 18 min czytania
- TEMAT
- Łańcuch dostaw
Plik modelu AI wygląda jak dane, ale jego załadowanie może być operacją równie wrażliwą jak instalacja pakietu. Checkpoint może korzystać z pickle, repozytorium może zawierać niestandardowy kod, konfiguracja może wskazywać dynamicznie ładowaną klasę, a parser dużego tensora może zużyć pamięć albo trafić na błąd natywny. Dlatego format modelu jest elementem bezpieczeństwa łańcucha dostaw, lecz nigdy jego całością.
Najkrótsza odpowiedź: dla samych wag preferuj format bez wykonywalnej semantyki, taki jak SafeTensors, ale nie traktuj rozszerzenia
.safetensorsjako certyfikatu bezpieczeństwa repozytorium. Oddziel wagi od kodu, przypnij dokładną rewizję i digest, zweryfikuj podpis/provenance, skanuj wszystkie pliki, ładuj po raz pierwszy w izolowanym środowisku bez sekretów i egressu, a następnie publikuj zatwierdzony artefakt do własnego rejestru.
Dokumentacja torch.load ostrzega, aby nigdy nie ładować danych z niezaufanego źródła, ponieważ mechanizm korzysta z unpicklera. Hugging Face opisuje SafeTensors jako prosty format przechowywania tensorów zaprojektowany jako bezpieczniejsza alternatywa dla pickle i wspierający wydajny odczyt.
Model to więcej niż jeden plik z wagami
Typowe repozytorium może zawierać:
- tensory wag w jednym lub wielu shardach;
- plik indeksu mapujący tensor do sharda;
- konfigurację architektury i generacji;
- tokenizer, vocabulary, merges i dodatkowe modele preprocessingu;
- niestandardowy kod Python lub C++;
- skrypty konwersji, notebooki i zależności;
- adaptery LoRA, quantization config i biblioteki kerneli;
- model card, licencję i metadane pochodzenia.
Bezpieczne wagi nie neutralizują setup.py, złośliwego importu, podatnego tokenizera ani flagi w stylu trust_remote_code. Z drugiej strony repozytorium bez kodu może nadal zawierać ogromne wymiary tensorów prowadzące do wyczerpania zasobów albo model zachowujący się złośliwie przez backdoor. Potrzebny jest model zagrożeń dla całego pakietu.
Dlaczego pickle może wykonywać kod
Python pickle zapisuje instrukcje potrzebne do rekonstrukcji obiektów. Nie jest formatem wymiany z nieufnym nadawcą. Mechanizm może odwołać się do funkcji i klas dostępnych w środowisku, dlatego spreparowany strumień może uruchomić niepożądane zachowanie podczas ładowania.
W ekosystemie PyTorch historycznie popularne były pliki .pt, .pth, .bin i .ckpt. Rozszerzenie nie określa jednoznacznie formatu. Trzeba sprawdzić, jak artefakt jest faktycznie ładowany. Zmiana nazwy z model.pkl na weights.bin nie usuwa semantyki pickle.
Od PyTorch 2.6 torch.load() domyślnie używa weights_only=True, jeżeli nie podano własnego pickle_module. Dokumentacja Serialization semantics wyjaśnia, że ograniczony unpickler nie importuje dynamicznie dowolnych funkcji i klas. Jednocześnie PyTorch zaznacza ograniczenia: tryb nie gwarantuje ochrony przed DoS i nie eliminuje wszystkich potencjalnych problemów pamięci.
To ważna warstwa migracyjna, ale nie powód, aby ładować losowe checkpointy na maszynie z poświadczeniami chmurowymi. Gdy błąd sugeruje przełączenie na weights_only=False, nie rób tego automatycznie. Najpierw potwierdź pochodzenie i wykonaj konwersję w izolacji.
Co daje SafeTensors
SafeTensors oddziela niewielki nagłówek z metadanymi tensorów od ciągłego obszaru danych. Format nie służy do serializowania dowolnych obiektów Pythona i nie zawiera mechanizmu wykonywania funkcji podczas ładowania. Wspiera lazy loading oraz memory mapping, co jest użyteczne przy dużych modelach.
Hugging Face, EleutherAI i Stability AI zleciły zewnętrzny audyt biblioteki; podsumowanie i publiczny raport są dostępne w materiale SafeTensors security audit. Audyt nie znalazł krytycznej luki prowadzącej do arbitralnego wykonania kodu w ocenianej wersji i doprowadził do poprawek specyfikacji oraz walidacji.
SafeTensors ogranicza ważną klasę ryzyka, lecz nie gwarantuje:
- że wagi pochodzą od deklarowanego autora;
- że model nie zawiera backdoora lub niebezpiecznego zachowania;
- że inne pliki repozytorium są bezpieczne;
- że loader, runtime, sterownik lub kernel nie ma podatności;
- że wymiary i typy tensorów mieszczą się w budżecie zasobów;
- że licencja i dane treningowe pozwalają na użycie modelu.
Format odpowiada na pytanie „czy plik wag ma wykonywalną semantykę pickle?”, a nie „czy model jest godny zaufania?”.
ONNX, TorchScript i format wykonywalny
ONNX opisuje graf obliczeniowy i operatory. To inny model ryzyka niż pickle, ale parser i runtime wykonują złożony graf, często z kodem natywnym i opcjonalnymi custom operators. Nie należy utożsamiać „nie jest pickle” z „można bezpiecznie uruchomić dowolny plik”.
TorchScript, skompilowane silniki inference, biblioteki CUDA i custom ops również zwiększają powierzchnię wykonania. Artefakt może wymagać pluginu pobranego osobno. Każdy element powinien mieć ustalone pochodzenie, wersję, digest i właściciela aktualizacji.
Praktyczna klasyfikacja:
| Artefakt | Główne ryzyko | Preferowana kontrola |
|---|---|---|
| pickle/checkpoint | konstrukcja obiektów i wykonanie | nie ufać; izolowana konwersja |
| SafeTensors | parser, zasoby, złośliwe wagi | limity + provenance + ewaluacja |
| ONNX/graf | parser/runtime/custom ops | sandbox + allowlista operatorów |
| kod modelu | arbitralne wykonanie | review, pin, build, podpis |
| tokenizer/parser | błędy natywne i DoS | limity, aktualizacje, fuzzing |
| kontener inference | pełny software supply chain | SBOM, skan, podpis, least privilege |
Zagrożenia w repozytorium modeli
Typosquatting i podszycie pod autora
Atakujący publikuje nazwę podobną do popularnego modelu, kopiuje opis i dodaje złośliwy artefakt. Obrona wymaga weryfikacji organizacji, historii repozytorium, linku z oficjalnej dokumentacji i cryptographic digest — liczba pobrań nie jest dowodem.
Przejęcie konta lub tokenu wydawcy
Legalne repozytorium może zostać zmienione po kompromitacji. Pin do gałęzi main nie jest reprodukowalny. Używaj konkretnego commit ID/revision i własnego zatwierdzonego mirrora. Zdarzenia aktualizacji powinny przechodzić taki sam przegląd jak nowe zależności.
Złośliwa konwersja
Konwersja pickle do SafeTensors musi najpierw wczytać stary plik. Jeżeli wykonasz ją na laptopie dewelopera, ryzyko materializuje się przed powstaniem bezpieczniejszego outputu. Konwerter uruchamiaj w jednorazowym środowisku bez sieci, sekretów, montowań zapisywalnych i dostępu do hosta.
Remote code i zależności
Niektóre modele wymagają niestandardowej klasy. Flaga dopuszczająca zdalny kod jest świadomą decyzją o wykonaniu kodu dostawcy. Kod trzeba przypiąć do rewizji, przejrzeć, zbudować wewnętrznie i uruchomić z minimalnymi uprawnieniami. Bezpieczeństwo agentów programistycznych pokazuje, jak łatwo automatyzacja zamienia sugestię repozytorium w wykonanie.
Referencyjny pipeline importu modelu
1. Intake w strefie kwarantanny
Pobierz artefakt przez dedykowaną usługę. Nie otwieraj go automatycznie w notebooku. Zapisz URL, namespace, revision, czas, deklarowaną licencję, rozmiar i hash każdego pliku. Zablokuj automatyczne skrypty instalacyjne.
2. Weryfikacja pochodzenia
Sprawdź, czy źródło jest powiązane z oficjalnym wydawcą. Preferuj podpisany manifest lub provenance. Sam SHA-256 zapewnia identyfikację tylko wtedy, gdy oczekiwany digest dotarł innym, zaufanym kanałem. Hash opublikowany obok podmienionego pliku niczego nie dowodzi.
3. Klasyfikacja formatów
Wykryj format po strukturze, nie rozszerzeniu. Oznacz pickle, archiwa, wykonywalne biblioteki, custom ops i kod. Polityka może automatycznie dopuścić wybrane formaty do dalszej analizy, a resztę skierować do ręcznego review.
4. Statyczne skanowanie
Skanuj malware, sekrety, licencje, podatne zależności i niebezpieczne importy. Dla pickle narzędzia mogą analizować opcode’y bez wykonania, lecz wynik „brak znanego wzorca” nie gwarantuje bezpieczeństwa. Dla archiwów stosuj limity liczby plików, rozmiaru po rozpakowaniu i głębokości ścieżek.
5. Izolowana konwersja i smoke test
Jednorazowy worker bez egressu ładuje artefakt z read-only input, zapisuje wyłącznie do pustego output i kończy pracę. Nie otrzymuje kluczy, socketu Dockera, cache dewelopera ani danych produkcyjnych. Ustaw limity CPU, RAM, GPU, czasu, liczby procesów i rozmiaru plików. Po konwersji worker jest niszczony.
6. Ewaluacja bezpieczeństwa modelu
Sprawdź zachowanie na canary prompts, backdoory zgodne z modelem zagrożeń, nieoczekiwane połączenia, ładowane biblioteki i zużycie zasobów. AI red teaming ocenia zachowanie, którego format pliku nie może zagwarantować.
7. Publikacja do wewnętrznego rejestru
Utwórz niezmienny, podpisany manifest zawierający digest wag, kodu, konfiguracji, tokenizera, obrazu runtime i wyników kontroli. Produkcja może pobierać wyłącznie zatwierdzone wersje z rejestru, nie bezpośrednio z publicznego huba.
Powiązanie z SBOM, SLSA i podpisami
SBOM opisuje komponenty oprogramowania, ale typowy SBOM może nie oddać pochodzenia wag, datasetu, adapterów i parametrów konwersji. Dodaj manifest modelu z relacjami między tymi elementami. Traktuj tokenizer, custom ops i kontener inference jako zależności pierwszej klasy.
Sigstore i SLSA pomagają powiązać artefakt z tożsamością i procesem budowy. Podpis nie oznacza, że model jest dobry; pozwala egzekwować, że produkcja uruchamia dokładnie to, co przeszło zatwierdzony pipeline.
W środowisku chmurowym można dodatkowo związać wydanie klucza modelu z atestacją TEE. Wtedy provenance mówi „skąd pochodzi artefakt”, podpis „kto go zatwierdził”, a atestacja „jaki kod uruchamia go teraz”.
Hardening środowiska inference
Nawet zatwierdzony model uruchamiaj z ograniczeniami:
- osobna tożsamość workloadu i brak poświadczeń deweloperskich;
- read-only filesystem poza kontrolowanymi katalogami cache;
- brak domyślnego egressu lub ścisła allowlista;
- seccomp/AppArmor/SELinux i zakaz privileged containers;
- limity pamięci, GPU, procesów i czasu requestu;
- podpisane obrazy z minimalnym zestawem bibliotek;
- monitoring nowych procesów, bibliotek, połączeń i zmian plików;
- oddzielenie danych różnych tenantów.
Bezpieczeństwo obrazów kontenerów jest częścią tego samego łańcucha. Model może być bezpieczny, a runtime podatny — lub odwrotnie.
Aktualizacje bez utraty kontroli
Nie aktualizuj modelu automatycznie do najnowszej rewizji publicznego repozytorium. Nowa wersja uruchamia cały pipeline: intake, diff, skan, konwersję, ewaluację i podpis. Porównuj nie tylko pliki, lecz także zachowanie na stałym zestawie testowym, zużycie zasobów i wymagane zależności.
Przy rollbacku zachowaj niezmienny manifest starej wersji i kompatybilny runtime. Nie polegaj na tym, że tag upstream nadal wskazuje ten sam commit. Rejestr audytowy powinien odpowiadać: kto, kiedy, z jakiego źródła, jakim narzędziem i z jakim wynikiem zatwierdził artefakt.
Checklista importu
- Czy pobieramy konkretną rewizję i znamy digest każdego pliku?
- Czy źródło zostało zweryfikowane niezależnym kanałem?
- Czy pipeline wykrywa format po zawartości, a nie nazwie?
- Czy pickle i remote code zawsze trafiają do ręcznej decyzji oraz sandboxa?
- Czy konwersja działa bez sieci, sekretów i dostępu do hosta?
- Czy skanujemy tokenizer, konfigurację, custom ops i kontener, nie tylko wagi?
- Czy produkcja korzysta wyłącznie z wewnętrznego, podpisanego rejestru?
- Czy manifest łączy model, kod, konfigurację, runtime i wyniki testów?
- Czy aktualizacja i rollback są reprodukowalne?
SafeTensors to rozsądny domyślny wybór dla wag, ponieważ usuwa wykonywalną semantykę pickle. Nie usuwa jednak potrzeby weryfikacji pochodzenia, izolacji i testowania zachowania. Model AI jest złożonym artefaktem oprogramowania i danych, więc powinien przechodzić równie rygorystyczny proces jak krytyczny obraz kontenera. Zamów audyt bezpieczeństwa AI — sprawdzimy cały pipeline od publicznego huba do produkcyjnego inference.


