Přeskočit na obsah
Bezpečnost 3 min čtení

MLflow ve verzích 2.1.0 až 3.14.x ignoroval zákaz pickle u modelů statsmodels

Bezpečnostní volba v MLflow měla zastavit načítání modelů uložených pomocí pickle, integrace statsmodels ji ale nekontrolovala. Upravený modelový artefakt proto mohl při načtení spustit kód i s nastavením MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False. Verze 3.15.0 kontrolu doplnila a projekt podrobnosti zveřejnil 1. září.

Titulní snímek prezentace Por que Python z roku 2008
Titulní snímek prezentace „Por que Python?“ z roku 2008. Foto: Érre, Wikimedia Commons (CC BY-SA 2.0)

Integrace statsmodels přeskočila společnou pojistku

MLflow ukládá modely v několika takzvaných flavors, tedy integracích pro konkrétní knihovny a formáty. Stejný model pak lze načíst přímo přes jeho integraci nebo společnou funkcí mlflow.pyfunc.load_model(). U modelů z knihovny statsmodels vedou obě cesty nakonec do funkce statsmodels.iolib.load_pickle().

Formát pickle není obyčejný balík dat. Při obnově objektu může zavolat funkci a tím spustit kód. Dokumentace Pythonu proto říká, že se mají načítat jen důvěryhodná data. Statsmodels u své funkce varuje stejně: model z nedůvěryhodného nebo neověřeného zdroje se nemá rozbalovat.

MLflow má pro takové nasazení proměnnou MLFLOW_ALLOW_PICKLE_DESERIALIZATION. Hodnota False má načítání pickle zastavit. Integrace pro scikit-learn, PyTorch nebo pmdarima ji kontrolovaly, statsmodels ne. Ve verzi 3.14.0 funkce _load_model() rovnou zavolá smio.load_pickle(path). Hodnota bezpečnostní volby se v souboru vůbec nečte.

Kód se spustil až při načtení artefaktu

Podmínka útoku je důležitá. Nestačí otevřít webové rozhraní nebo si prohlédnout kartu modelu. Útočník musí dostat upravený soubor MLmodel a škodlivý pickle do úložiště, ke kterému má oběť přístup. Potom musí nějaký proces zavolat mlflow.pyfunc.load_model() nebo mlflow.statsmodels.load_model() nad tímto artefaktem.

Bezpečnostní hlášení GHSA-gqvg-gmmx-x4hm upozorňuje, že výchozí server MLflow nemá zapnuté přihlašování. Z toho ale neplyne, že každý server na internetu dovolí komukoli podstrčit a načíst model: rozhodují práva k úložišti, způsob nasazení a to, kdo operaci načtení spustí. Hlášení hodnotí chybu známkou 8,8 z deseti a uvádí nutnou součinnost uživatele. Číslo CVE zatím přidělené nemá.

Rozsah ve stejném záznamu začíná verzí 2.1.0 a končí těsně před 3.15.0. Jako první opravenou verzi uvádí jen 3.15.0, nikoli některé vydání řady 2.x. Správci starší hlavní řady tak nemají v hlášení uvedenou opravenou větev, na které by mohli zůstat.

Verze 3.15.0 hlídá oba způsoby načtení

Opravu přinesl návrh změny #24686, přijatý 27. července. Kontrola teď stojí přímo na začátku _load_model(), tedy před voláním statsmodels. Při zakázané deserializaci vyhodí MLflow výjimku a k pickle se nedostane. Test zkouší obě veřejné cesty načtení, přímou funkci statsmodels i společné pyfunc.load_model().

Kód zachovává stejnou výjimku jako ostatní integrace MLflow: kontrolu nepoužije uvnitř Databricks Runtime a v prostředí Databricks Model Serving. Nejde o přehlédnutou větev nové opravy, ale o záměr, který opravný commit přebírá ze sourozeneckých integrací.

MLflow 3.15.0 vyšlo 31. července. Poznámky k vydání opravu uvádějí jedním řádkem mezi běžnými opravami modelů, bez známky závažnosti a bez odkazu na neveřejné hlášení. Veřejný popis chyby přibyl 1. září, tedy o 32 dní později. Oprava tak byla měsíc dostupná, ale její dopad se z poznámek k vydání určit nedal.

Původ modelu zůstává po aktualizaci rozhodující

Aktuální vydání 3.15.2 z 26. srpna už opravu obsahuje. Aktualizace zavře konkrétní mezeru v integraci statsmodels, ale z pickle neudělá bezpečný formát. Modelové artefakty dál patří do stejné kategorie jako spustitelný kód: úložiště potřebuje řízení zápisu a původ modelu se musí ověřit před načtením.

Přepínač s hodnotou False má smysl jako druhá pojistka. Tahle chyba ukazuje jeho mez: globálně pojmenovaná bezpečnostní volba chránila jen integrace, které ji skutečně zkontrolovaly. Vlastní nebo méně obvyklé loadery je proto potřeba prověřovat podle kódu, ne podle názvu proměnné.

Zdroje

Diskuse

Zatím tu nikdo nediskutuje. Můžete být první.

Napsat příspěvek

Diskutovat můžete i bez účtu. S registrací se ale příspěvek zveřejní hned a nemusíte pokaždé vyplňovat jméno. Účet už máte? Přihlaste se.

Nezveřejňujeme ho, slouží jen redakci.

Podporuje zápis Texy: **tučně**, *kurzíva*, odrážky, odkazy.

Dál k tématu

  1. Bezpečnost

    Codex spouštěl program z nastavení cizího repozitáře mimo vlastní sandbox

    OpenAI zveřejnila 1. září 2026 čtyři záznamy CVE ke svému agentnímu nástroji Codex. Tři z nich stojí na témže předpokladu: repozitář si s sebou nese vlastní soubor .git…

  2. Bezpečnost

    Knihovna ash_ai spouštěla text promptu jako zdrojový kód Elixiru

    Šest záznamů CVE zveřejněných 31. srpna míří na jedinou knihovnu: rozšíření ash_ai, které do elixirového frameworku Ash přidává práci s jazykovými modely. Nejzávažnější…

  3. Bezpečnost

    Browser-use web-ui ukládá klíče k modelům do nešifrovaných souborů

    Záznam CVE-2026-82640 zveřejněný 30. srpna popisuje, jak browser-use web-ui ukládá klíče k modelům do souborů JSON v čitelné podobě. Týká se vydání 2.0.0 až 3.0.0 a…

  4. Bezpečnost

    Integrace Sentry SDK mohla do verze 2.66.1 vypnout schvalování nástrojů

    Nové hlášení ze 30. srpna upozornilo, že integrace OpenAI Agents v Sentry SDK sestavovala každý nástroj znovu a nepřenášela jeho schvalování ani vstupní a výstupní…