В бэкенде Unsloth Studio - браузерного интерфейса популярной библиотеки для дообучения моделей - обнаружилась уязвимость, позволявшая выполнить произвольный код. Выбор модели в интерфейсе заставлял сервер скачать и запустить Python-модуль, лежащий в репозитории этой модели на HuggingFace. Ничего больше не требовалось: хватало чтения файла конфигурации, веса не загружались и вывод модели не выполнялся. Исправление вышло 18 июня 2026 года в версии 2026.6.9.
Уязвимость CVE-2026-1839
Unsloth - открытая библиотека для дообучения и квантования больших языковых моделей. Она делает работу, которая раньше требовала глубоких знаний системного уровня, доступной широкому кругу разработчиков. Studio - её веб-интерфейс, находящийся в бета-статусе. Значимость проекта для корпоративной разработки подтверждается косвенно: Databricks включает библиотеку в свою среду AI v5, а Hugging Face ставит Unsloth на третье место по числу производных моделей на своём хабе, после Qwen и Google. Уязвимость нашла компания Pillar Security, разработчикам о ней сообщили в начале июня 2026 года.
Причина уязвимости - в механизме, на котором держится заметная часть экосистемы машинного обучения. Репозиторий модели может содержать не только веса, конфигурацию и токенизатор, но и исполняемый код. Библиотека transformers поддерживает такое устройство намеренно: файл конфигурации вправе указать на пользовательский модуль, и тогда при загрузке с флагом доверия удалённому коду (trust_remote_code) этот модуль импортируется и запускается. Механизм нужен легитимным моделям - IBM Granite Speech и Vision, DeepSeek-OCR, ChatGLM и ранние выпуски Qwen без него не работают.
Проблема не в самом механизме, а в том, как им распорядился бэкенд Studio. Параметр доверия удалённому коду имел там значение "истина" по умолчанию. Путь, отвечавший за проверку возможностей модели, это значение не переопределял, а отдельная ветка для новой версии transformers задавала его жёстко. Собственный переключатель пользователя, по умолчанию запрещающий запуск чужого кода, до дела не доходил. Когда оператор выбирал модель, сервер скачивал конфигурацию и запускал указанный в ней модуль ещё до загрузки, обучения или экспорта. Проверка метаданных, назначение которой - просто разобрать объявленные поля, превращалась в запуск постороннего кода.
Произвольное выполнение кода шло с правами пользователя в процессе бэкенда. Для рабочей станции, где идёт разработка моделей, это означает доступ к токенам HuggingFace, ключам SSH и облачным учётным данным. Злоумышленник получал возможность менять веса и результаты обучения, закрепляться в системе и двигаться дальше по сети. Такие машины несут графические ускорители и привилегированные учётные данные, поэтому интерес к ним выше среднего. Если сервис привязан ко всем сетевым интерфейсам, запущен в Colab или обслуживает нескольких пользователей, размах последствий растёт.
В тестовом примере исследователи ограничились безобидными действиями: открывали калькулятор и дописывали строку в файл. Настоящая атака не обязана выглядеть опасной до запуска - модуль способен пройти любые проверки, а полезную нагрузку подтянуть позже, уже во время исполнения.
Уязвимый код при этом попадал в обычную сборку пакета. Studio описывали как бета-функцию, однако выбирать предварительный выпуск не требовалось: достаточно было поставить библиотеку командой pip install unsloth. Эксплуатация требовала запустить Studio и выбрать модель, подконтрольную атакующему.
Разработчики оспорили оценку. Они ссылались на то, что сканирование вредоносного кода на HuggingFace закрывает эту поверхность, а бета-статус интерфейса выводит его из рассмотрения. Сканирование действительно существует, но опирается в основном на списки известных сигнатур и плохих функций, и исследователи не раз его обходили - сменой формата архива, заменой опасного вызова на безопасный по названию, размещением полезной нагрузки до того места, где проверка ломается. Ответный аргумент о пароле тоже не попадает в цель: аутентификация решает, кто получит доступ к серверу, и ничего не говорит о том, что сервер сделает с выбранной моделью. Жертвой становится доверенный оператор, вошедший в систему под своим паролем.
Похожие случаи уже получали идентификаторы CVE в этом году: жёстко заданное доверие удалённому коду находили в LMDeploy и vLLM, где оно перебивало явный запрет пользователя, а также в скрипте обучения InstructLab. Unsloth Studio соединил обе ошибки в одном сценарии и сдвинул момент срабатывания ещё раньше - на выбор модели, шаг, который никто не воспринимает как опасный. Перекладывать исправление на HuggingFace бессмысленно: отключить механизм нельзя, не сломав работу множества моделей, а определить при загрузке, какой инструмент и с каким флагом обратится к репозиторию, невозможно. Граница доверия проходит там, где выполняется проверка, то есть внутри Studio.
В версии 2026.6.9 разработчики переработали этот путь: Studio больше не загружает произвольные модели напрямую с HuggingFace и не доверяет удалённому коду из локальных файлов. Независимая повторная проверка подтвердила, что вектор закрыт. Рекомендательный документ разработчики публиковать отказались, поэтому CVE уязвимости не присвоен.
Тем, кто пользуется Studio, стоит обновиться до 2026.6.9 или более поздней версии. Шире - относиться к репозиториям моделей как к недоверенному коду, а не к набору данных; следить, чтобы инструменты в рабочем конвейере не включали доверие удалённому коду без явного решения специалиста; фиксировать ревизии моделей по хешу коммита; предпочитать формат safetensors; изолировать загрузку моделей на машинах, где лежат учётные данные. Удобное значение по умолчанию безвредно ровно до появления первого вредоносного репозитория, а после него превращается в общий риск для всех, кто поставил обычную сборку.
Ссылки
- https://www.cve.org/CVERecord?id=CVE-2026-1839
- https://www.pillar.security/blog/look-dont-load-model-inspection-in-unsloth-studio-leads-to-critical-arbitrary-code-execution