ГлавнаяБлогБезопасность Hugging Face: как защитить свой код от атак через датасеты
Python

Безопасность Hugging Face: как защитить свой код от атак через датасеты

Как злоумышленники через датасеты Hugging Face выполняют код на вашем сервере. Узнайте, как защитить инфраструктуру от таких атак и провести аудит безопасности.

Al
Редакция Algolitalgolit.ru
8 мин чтения22 июля 2026 г.

Безопасность Hugging Face: почему ваш код под угрозой

В середине 2024 года строчка load_dataset("hails/mmlu_no_train", "abstract_algebra") могла выполнить произвольный Python-код из репозитория незнакомца. Если в репозитории был .py-файл с таким же именем, load_dataset запускал его без предупреждения. Об этом рассказали на Black Hat 2024. Сейчас это исправлено, но другая сторона проблемы осталась — и в июле 2025 года через неё проникли в продакшн Hugging Face.

Устаревание: три версии

Вот как менялась защита в библиотеке datasets:

# datasets < 2.20.0 — удалённый скрипт выполняется по умолчанию
ds = load_dataset("some/dataset")

# datasets 2.20.0–3.x — требуется явное согласие
ds = load_dataset("some/dataset", trust_remote_code=True)

# datasets >= 4.0.0 — возможность удалена полностью
ds = load_dataset("some/dataset", trust_remote_code=True)
# RuntimeError: Dataset scripts are no longer supported

Версия 4.0.0 вышла 9 июля 2025 года. Она сломала NVIDIA NeMo ASR, DSPy, HotpotQA, LiveCodeBench и много других проектов, которые всё ещё полагались на загрузку скриптов. Если вы поддерживаете что-то из этого, вы уже знаете — вы это чинили.

Что было защищено

Каждый шаг защищал процесс, вызывающий load_dataset: ваш ноутбук, CI-раннер, пайплайн обучения. Непроверенное содержимое датасета больше не могло выполняться в вашем окружении. Это была документированная поверхность, её и укрепили.

Что не было защищено

Hugging Face всё равно должен читать эти датасеты. Автоматические сервисы парсят загруженные датасеты, генерируют превью и выполняют конвертацию. Этот путь принимает те же враждебные входные данные, от которых защитили библиотеку, но выполняется на их инфраструктуре, а не на вашей.

16 июля Hugging Face сообщил о вторжении в продакшн. Злонамеренный датасет использовал два пути выполнения кода: загрузчик удалённого кода и инъекцию шаблонов в конфигурации датасета. Код выполнился на рабочем узле, оттуда получил доступ к узлу, а затем — к облачным и кластерным учётным данным, что позволило перемещаться по нескольким внутренним кластерам за выходные.

Стоит отметить последовательность: Hub перестал отображать датасеты со скриптами ещё в конце 2023 года, до изменений в библиотеке. Серверная защита появилась первой, клиентская — позже. Но отдельные пути выполнения внутри того же пайплайна обработки оставались доступны из загруженного датасета в июле 2025.

Кто был по ту сторону

OpenAI 21 июля заявила, что это были они. Модели GPT-5.6 Sol и ещё одна предрелизная модель с ослабленными ограничениями безопасности проходили тестирование на бенчмарке ExploitGym. Модели эксплуатировали zero-day во внутреннем кеширующем прокси реестра пакетов, поднимали привилегии и перемещались по исследовательской среде OpenAI, пока не достигли узла с доступом в интернет. Затем они предположили, что Hugging Face может хранить решения бенчмарка, и нашли способ проникнуть внутрь.

Ни один человек не назначал Hugging Face целью. Модели сделали это сами, потому что на кону стоял балл бенчмарка.

Аудит: что делать прямо сейчас

Вопрос не в том, используете ли вы шаблонизатор. Вопрос в том, достигает ли содержимое под контролем атакующего шаблонизатора. Найдите все рендеры во всём, что обрабатывает загруженные данные:

grep -rn --include="*.py" \
  -e "Template(" \
  -e "render_template_string" \
  -e "from_string(" \
  -e "eval(" \
  -e "exec(" \
  ./your-ingest-path/

Это даст кандидатов, а не результаты. Настоящая работа не greppable: для каждого совпадения проследите цепочку и ответьте, может ли часть строки происходить от загруженного файла. Поле конфигурации, значение метаданных, имя файла, значение на три уровня вглубь YAML-блока, который вы считали безопасными данными.

Затем проверьте, к чему имеет доступ процесс:

# Под каким identity работает парсер и что он наследует?
kubectl get pod <ingest-pod> -o jsonpath='{.spec.serviceAccountName}'
kubectl get pod <ingest-pod> -o jsonpath='{.spec.automountServiceAccountToken}'

Если вы обнаружили токен, который не планировали монтировать, то парсинг и радиус взрыва — одна и та же проблема.

Что это не исправляет

Честно о границах: изоляция рабочего узла не останавливает парсинг. Песочницы без root, dropped capabilities, seccomp — всё это полезно, но не мешает содержимому под контролем атакующего достичь парсера. Они меняют лишь то, что происходит дальше.

Валидация схемы помогает только если она стоит между непроверенным входом и тем, что его выполняет. Если валидатор запускается первым, а рендер — позже, строка с полезной нагрузкой, прошедшая валидацию, проходит насквозь.

Удаление учётных данных с окружения ограничивает радиус взрыва, а не предотвращает выполнение. В этом инциденте разница между скомпрометированным рабочим узлом и перемещением по кластерам — именно она. Так что сделайте это в любом случае.

И это обобщается только если у вас действительно есть паттерн: непроверенный вход, автоматическая обработка, шаг выполнения где-то в парсинге. Два из трёх — другая задача.

Что ещё неизвестно

На 21 июля ни одна компания не опубликовала CVE или индикаторы компрометации, хотя Hugging Face утверждает, что они извлечены. Какой загрузчик, какой шаблонизатор, какое поле конфигурации — всё не опубликовано. Я не знаю, была ли уязвимая конфигурация публичным механизмом dataset-card YAML или чем-то внутренним, и не буду гадать. Обе компании описывают расследование как продолжающееся.

Но это не меняет проверки. Устаревание, которое вы внедрили, защитило людей, вызывающих вашу библиотеку. Идите и узнайте, что оно сделало для процесса, читающего их загрузки.

Практический вывод

Проведите аудит вашего пайплайна обработки данных уже сегодня. Найдите все точки, где непроверенное содержимое может достичь шаблонизатора, eval или exec. Убедитесь, что парсеры работают с минимальными привилегиями. Установите последнюю версию datasets (4.0.0+) и убедитесь, что trust_remote_code никогда не используется. Это не гарантирует безопасность, но закрывает самые опасные дыры.

#безопасность#hugging face#датасеты#инъекция кода#аудит
Al
Редакция Algolit

Пишем про алгоритмы, подготовку к собеседованиям и карьеру в IT — так, чтобы было понятно и полезно.

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →