trust_remote_code ma prostą obietnicę: jeśli model wymaga custom Python code, biblioteka pyta „czy ufasz temu zdalnemu kodowi?”, a odpowiedź „nie” powinna znaczyć „nic trwałego się nie stało”. CVE-2026-80047 pokazuje, że w jednej ścieżce Transformers było inaczej. W GenerativePreTrainedModel.load_custom_generate() kod z repozytorium był pobierany i kopiowany do lokalnego cache zanim wywołano resolve_trust_remote_code(). Consent następował po nieodwracalnym side effect.
load_custom_generate() zapisuje custom_generate/generate.py do ~/.cache/huggingface/modules przed sprawdzeniem trust.Co jest potwierdzone, a czego nie dopisywać
Potwierdzone: remote attacker-controlled Python file → fetched → persisted locally → before consent. Nie należy pisać „odmowa promptu natychmiast wykonuje RCE” — CERT/CC podkreśla, że execution jest nadal gated. Problem to unauthorized persistent code write, który może mieć późniejszy impact w środowisku z reused cache.
„Nie wykonałem kodu” nie oznacza „system jest czysty”
Developer ładuje złośliwy model, odmawia trust — na ekranie bezpiecznie. Ale lokalnie zostaje ~/.cache/huggingface/modules/.../generate.py. Jeżeli później inny workflow ufa temu modelowi, cache zostanie ponownie użyty albo inny pipeline przyjmie inny trust decision — stary attacker-controlled file może wejść do kolejnej ścieżki. CERT/CC wskazuje reused cache jako potencjalny mechanizm późniejszego unintended execution.
Meta-wzorzec: decyzja po side effect
To nie klasyczny race condition, lecz side effect at T1, consent decision at T2, T1 < T2. Security decision działa, ale za późno, by zapobiec pierwszej części skutku. Ten sam meta-wzorzec co authorization przed tenant resolution, validation przed canonical path resolution czy sandbox przed second render. Ważny wniosek dla AI/ML: cache staje się security state — remediation nie kończy się na upgrade Transformers, jeśli plik został już zapisany.
Patch vs cleanup; dlaczego trust_remote_code=False nie wystarcza
Dwie różne rzeczy: (1) fix future behavior — gdy vendor da poprawkę consent before fetch/write; (2) remove historical artifacts — inspect/clear ~/.cache/huggingface/modules. Patch nie cofa przeszłych side effects (jak credential rotation po wycieku czy CI cache invalidation). A jeśli aplikacja zakłada „trust_remote_code=False → no remote code reaches disk", CVE obala właśnie to założenie: execution blocked ≠ remote code ingestion blocked — to różnica między execution control a content acquisition control.
Statusy i finding
Nie RCE (brak execution evidence) i nie harmless (bo odmówiono). Lepsze: UNAUTHORIZED_CODE_PERSISTENCE + EXECUTION_NOT_CONFIRMED. Bieżąca mitygacja (CERT/CC): unikać load_custom_generate() dla untrusted repos, inspekcja/cleanup cache, trust check przed fetch/write; dodatkowo ephemeral cache per build, isolated execution, allowlist repos, monitoring nowych plików w HF module cache. Nie wolno wymyślać fixed version.
Wniosek
CVE-2026-80047 to świetny przykład dla AI security i VE: security decision musi poprzedzać pierwszy nieodwracalny side effect. Inaczej UI mówi „odmówiono”, podczas gdy system już zmienił persistent state — a cache jest częścią assetu i remediation.
Powiązane na blogu
- Sandbox działał, render drugi raz — kontrola we właściwym momencie pipeline
- Malware w npm, nie CVE — cache/artefakt jako część stanu bezpieczeństwa
Źródła
- CERT/CC — VU#456290 (01.09.2026) — kb.cert.org
- CVE.org — CVE-2026-80047 — cve.org
- Hugging Face Transformers — github.com
Nota redakcyjna: stan informacji 2 września 2026. CERT/CC wskazuje affected Transformers 4.49.0–5.8.1 oraz brak vendor-provided patch/advisory w momencie publikacji 01.09. Artykuł świadomie rozróżnia persistent unauthorized file write od potwierdzonego immediate RCE po odmowie consent.