BadHost CVE-2026-48710: критическая уязвимость Starlette и FastAPI
Уведомление безопасности · Май 2026

BadHost (CVE-2026-48710):
Односимвольная эксплуатация, угрожающая миллионам AI-агентов

Критическая уязвимость Starlette позволяет обходить аутентификацию одним символом в Host-заголовке. Обнаруженная при аудите vLLM, ошибка поражает FastAPI, LiteLLM, MCP-серверы и весь стек Python AI-инструментария.

Олег Максимов 27 мая 2026 10 мин чтения

Что такое BadHost?

22 мая 2026 года команда Starlette тихо выпустила версию 1.0.1 своего популярного ASGI-фреймворка — исправление уязвимости, обнаруженной исследователями безопасности из X41 D-Sec в ходе спонсированного OSTIF аудита vLLM. Ошибка, отслеживаемая как CVE-2026-48710 и названная BadHost, представляет собой Host-header injection, позволяющий обходить авторизацию на основе пути одним неверным символом в HTTP-заголовке Host.

Starlette получает примерно 325 миллионов загрузок в неделю. Это ядро маршрутизации FastAPI, который, в свою очередь, лежит в основе огромной экосистемы Python-инструментов для AI — от серверов моделей (vLLM, Text Generation Inference) до прокси-слоёв (LiteLLM), MCP-серверов и AI-фреймворков. Радиус поражения — это не просто проблема Python-фреймворка, а практически вся Python-инфраструктура AI, развёрнутая сегодня.

Краткая сводка

CVECVE-2026-48710 (BadHost)
Затронутые версииStarlette >= 0.8.3, < 1.0.1
CVSS6.5 (Moderate) — исследователи считают критической
ЭксплуатацияТривиальна. Один символ, без аутентификации.
ИсправлениеStarlette 1.0.1 (тихий выпуск)
ОбнаруженаВ vLLM в ходе аудита X41 D-Sec, спонсированного OSTIF
Сканерbadhost.org (бесплатный онлайн-сканер)

Как работает эксплойт

Уязвимость — классический пример несогласованной интерпретации между двумя уровнями HTTP-стека. Starlette восстанавливает запрошенный URL путём конкатенации HTTP-заголовка Host с путём запроса и повторного разбора результата. Значение Host не валидируется в соответствии с RFC 9112 или RFC 3986 перед этой реконструкцией.

Минимальный proof of concept:

curl -i -H 'Host: foo'  http://target/admin    # 403, заблокировано
curl -i -H 'Host: foo?' http://target/admin    # 200, доступ получен

Заголовок Host, содержащий /, ? или #, смещает границы пути, запроса и фрагмента при повторном разборе. В результате request.url.path перестаёт совпадать с путём, который ASGI-сервер реально получил и по которому выполнил маршрутизацию. Маршрутизатор работает с реальным путём. Middleware видит отравленный, пересобранный путь. Любое решение безопасности в middleware, основанное на пути, может быть обойдено, пока базовый маршрут всё ещё выполняется.

Как X41 D-Sec описывает ошибку

«Starlette восстанавливает запрошенный URL на основе HTTP-заголовка Host и запрошенного пути, но не выполняет никакой валидации значения Host. Это позволяет атакующим внедрять пути в часть host, добавляя их перед фактическим путём. Однако маршрутизация в Starlette основана на фактическом пути запроса. Эта несогласованная интерпретация HTTP-запросов может привести к таким проблемам, как обход аутентификации, когда аутентификация зависит от пути восстановленного URL.»

Серьёзность: низкая оценка, тяжёлые последствия

Официальное уведомление Starlette содержит оценку CVSS 6.5 (Moderate), характеризующую проблему строго на уровне библиотеки как несовпадение строк пути. Исправление было выпущено тихо, без предупреждения всей экосистемы. Эта оценка существенно занижает реальное влияние.

Secwest, независимо проанализировавшие уязвимость, написали: «Один символ, введённый в HTTP-заголовок Host, обходит авторизацию на основе пути в Starlette, ядре маршрутизации FastAPI.» Они предупреждают, что «оценка CVSS существенно занижает угрозу», поскольку оценивает ошибку изолированно на уровне библиотеки, а не учитывает реальные цепочки эксплуатации — обход аутентификации, SSRF и удалённое выполнение кода (RCE).

Исследователь X41 D-Sec Маркус Вервье охарактеризовал CVE-2026-48710 как имеющую критическую серьёзность, отметив, что аутентификация во многих реальных приложениях, использующих request.url, может быть тривиально обойдена, а в некоторых случаях цепочки эксплуатации ведут к удалённому выполнению кода.

Какие данные сейчас под угрозой?

Сканирование X41 D-Sec выявило 10 категорий уязвимых данных:

  1. Биофармацевтика / AI — базы клинических испытаний, данные M&A, SSRF
  2. Верификация личности — анализ лиц, KYB, персональные данные, кодовая база
  3. IoT / Промышленность — SSH к устройствам, удалённое выполнение кода
  4. Email / SaaS — полный доступ к почте (чтение/отправка/удаление), S3, вебхуки
  5. HR / Рекрутинг — персональные данные кандидатов, данные найма
  6. CMS / Маркетинг — списки подписчиков, массовые email-кампании
  7. Управление документами — чтение, загрузка, изменение отсканированных документов
  8. Облачный мониторинг — топология AWS, распределённые трассы, метрики
  9. Кибербезопасность — инвентаризация активов, доступ к Nuclei-сканеру
  10. Личные данные / Финансы — логи питания, расходы, подписки

Затронутые проекты: радиус поражения

CVE-2026-48710 выходит далеко за пределы самого Starlette. Через FastAPI — доминирующего потребителя Starlette и основу современных Python-сервисов для AI — уязвимость каскадно распространяется на:

FastAPI vLLM LiteLLM Proxy Text Generation Inference MCP-серверы AI Agent Frameworks OpenAI-shim Прокси Eval Панели Реестры моделей Админ-панели (FastAPI)

Ошибка была обнаружена в vLLM, а не в Starlette. Это само по себе говорит о глубине проникновения FastAPI/Starlette в цепочку поставок AI-инфраструктуры. Путь от «странности Starlette» до «эксплойт-примитива для LLM» — это буквально путь обнаружения.

Трёхуровневая стратегия защиты

Уровень 1: Обновление Starlette

Самое прямое исправление — обновить Starlette до версии 1.0.1 или новее. Патч игнорирует заголовки Host, содержащие недопустимые символы:

pip install --upgrade starlette>=1.0.1

Если вы используете FastAPI, убедитесь, что Starlette указан как прямая зависимость, а не только транзитивная через FastAPI:

# requirements.txt
starlette>=1.0.1
fastapi>=0.115.12

Уровень 2: Обратный прокси

RFC-совместимые обратные прокси (nginx, Caddy, Traefik, HAProxy) валидируют и нормализуют заголовок Host перед передачей ASGI-серверу. ASGI-серверы передают сырой заголовок во фреймворк — обратный прокси это предотвращает.

Проблема в том, что многие развёртывания AI-инфраструктуры — особенно в исследовательских и тестовых средах — работают напрямую через uvicorn без обратного прокси. Такие лабораторные развёртывания особенно распространены для vLLM, LiteLLM, eval-панелей и MCP-серверов.

Уровень 3: Исправление логики аутентификации

Избегайте path-based auth middleware, зависящего от request.url.path. Middleware, принимающее решения безопасности на основе восстановленного пути URL, по своей природе хрупко — аутентификация должна быть привязана к эндпоинту, а не к пути. Используйте:

Немедленные действия

Контекст безопасности: 2026 год

Уязвимость BadHost — последняя в серии критических инцидентов безопасности с открытым исходным кодом, сформировавших ландшафт угроз 2026 года. Ранее в этом месяце атака Mini Shai-Hulud на цепочку поставок npm скомпрометировала более 170 пакетов, включая TanStack и Mistral AI — подробнее в моём анализе: Атака Mini Shai-Hulud на npm 2026. Взлом GitHub через отравленное VS Code-расширение группой TeamPCP показал, что инструменты разработчика стали векторами атак. Инцидент с утечкой токена GitHub у Grafana завершает картину: безопасность сегодня означает защиту каждого слоя цепочки поставок — от npm-пакетов до ASGI-фреймворков и CI/CD-пайплайнов.

Нужна безопасная веб-разработка? Обращайтесь

FAQ

Что такое BadHost (CVE-2026-48710)?
BadHost (CVE-2026-48710) — критическая уязвимость в Starlette < 1.0.1, позволяющая атакующим обходить авторизацию на основе пути, внедряя один символ в HTTP-заголовок Host. Уязвимость затрагивает FastAPI, vLLM, LiteLLM, MCP-серверы и тысячи проектов Python для AI. Обнаружена X41 D-Sec в ходе аудита vLLM, спонсированного OSTIF.
Как работает эксплойт BadHost?
Starlette восстанавливает request.url, конкатенируя Host-заголовок с путём запроса — без валидации Host. Если Host содержит /, ? или #, request.url.path перестаёт совпадать с реальным путём маршрутизации. Любое middleware, принимающее решения безопасности на основе request.url.path, может быть обойдено одним символом.
Какие проекты затронуты CVE-2026-48710?
Любое Python-приложение на Starlette < 1.0.1 или FastAPI с path-based auth middleware. Затронутые проекты: vLLM (где обнаружена ошибка), LiteLLM proxy, FastAPI, Text Generation Inference, MCP-серверы, AI agent frameworks (Google ADK-Python, LangChain), панели оценки, реестры моделей, Ray Serve, BentoML и OpenAI-shim прокси.
Насколько серьезна уязвимость BadHost?
Официальная оценка CVSS — 6.5 (Moderate), но исследователи X41 D-Sec характеризуют её как критическую. CVSS оценивает ошибку изолированно на уровне библиотеки, игнорируя реальные цепочки эксплуатации — обход аутентификации, SSRF и удалённое выполнение кода (RCE). Бесплатный онлайн-сканер: badhost.org.
Как исправить BadHost (CVE-2026-48710)?
Три уровня: (1) Обновите Starlette до 1.0.1+. (2) Разверните обратный прокси (nginx, Caddy, Traefik, HAProxy). (3) Замените path-based auth middleware на endpoint-based — декоратор requires() от Starlette или Depends()/Security() от FastAPI. При необходимости middleware используйте scope["path"] вместо request.url.path.
Почему BadHost особенно опасен для AI-инфраструктуры?
Многие LLM-серверы (vLLM, TGI), прокси (LiteLLM), AI agent frameworks и MCP-шлюзы построены на FastAPI/Starlette с path-based auth. MCP-серверы особенно уязвимы из-за незащищённых OAuth-эндпоинтов и чувствительных учётных данных. Лабораторные развёртывания без обратного прокси — обычная практика в исследовательских средах.
Защищает ли встроенный Depends() FastAPI от BadHost?
Да. Встроенные Depends() и Security() от FastAPI используют сопоставление маршрутов, а не request.url.path, поэтому стандартная DI FastAPI не уязвима. Проблема затрагивает только пользовательское middleware, проверяющее request.url.path. Однако многие MCP-серверы и AI-фреймворки используют такое уязвимое middleware.

Оставайтесь защищёнными

BadHost (CVE-2026-48710) — сигнал тревоги для всей Python AI-экосистемы. Он показывает, что один символ — буквально один байт в HTTP-заголовке — может обойти безопасность миллионов AI-агентов, когда фреймворки и их потребители работают с несогласованными предположениями о парсинге HTTP.

Решение не сложное: обновите Starlette, разверните обратный прокси и откажитесь от path-based auth middleware. Но в экосистеме, где лабораторные развёртывания работают напрямую через uvicorn, а оценки CVSS могут скрывать реальную критичность, разрыв между «патч доступен» и «патч установлен» может быть опасно большим.

Если вы создаёте Python-приложение или AI-сервис и ищете разработчика, понимающего безопасность от уровня фреймворка до production — от управления зависимостями до безопасного развёртывания — свяжитесь со мной. Я full-stack разработчик с 20+ годами опыта создания безопасных, production-ready приложений.

Контакты

Давайте создадим что-то безопасное

Есть проект? Я помогу выбрать современный и безопасный стек технологий и реализую его правильно. Бесплатная первичная консультация.