28 апреля Wiz Research раскрыла подробности CVE-2026-3854 — уязвимости в внутренней git-инфраструктуре GitHub с оценкой CVSS 8.7. Суть в одной фразе: любой аутентифицированный пользователь мог выполнить произвольные команды на бэкенд-серверах GitHub одним git push с обычного git-клиента. Никаких эксплойт-китов, никакой экзотики — штатный клиент и штатная команда.
Корень проблемы — служебный заголовок X-Stat, который прокси-компонент GitHub передаёт между внутренними сервисами при push. Поля в нём разделяются точкой с запятой, а значения push-опций (тех самых, что передаются через git push -o) подставлялись в заголовок без экранирования разделителя. Дальше работает семантика «последний выигрывает»: подсунув в push-опцию точку с запятой и имя чужого поля, атакующий переопределял доверенные значения. В боевой цепочке эксплуатации переопределялись три поля — rails_env (обход песочницы), custom_hooks_dir (подмена каталога, где ищутся хуки) и repo_pre_receive_hooks с path traversal. Итог — выполнение произвольного бинарника от имени системного пользователя git.
Масштаб последствий разный. Для GitHub.com, где инфраструктура мультитенантная и storage-ноды общие, выполнение кода означало кросс-тенантный доступ: чтение миллионов чужих репозиториев, публичных и приватных, независимо от организации. Для GitHub Enterprise Server — полная компрометация сервера со всеми репозиториями и внутренними секретами.
Хронология в пользу GitHub: Wiz нашла баг 4 марта и подтвердила RCE на GHES 3.19.1, в тот же день сообщила вендору, и в тот же день GitHub выкатил фикс на GitHub.com. 10 марта уязвимости присвоили CVE и выпустили патчи для GHES, публичное раскрытие отложили до 28 апреля. Проблема в том, что на момент публикации, по данным Wiz, около 88% инстансов GHES всё ещё оставались уязвимыми.
Что делать практикующему разработчику. Пользователям GitHub.com — ничего, всё закрыто ещё в марте, действий не требуется. А вот если у вас self-hosted GHES, это работа на сегодня, а не на спринт: уязвимы все версии до 3.19.1 включительно, патчи — 3.14.24, 3.15.19, 3.16.15, 3.17.12, 3.18.6 и 3.19.3. Версию видно в админ-консоли или по /setup/api/configcheck. Обходного пути на уровне конфига нет: отключить push-опции штатной настройкой нельзя, единственное решение — обновиться. И, поскольку эксплуатация требовала лишь аутентифицированного доступа (то есть подходил любой сотрудник или подрядчик с правом push), после апгрейда стоит исходить из худшего: провести аудит pre-receive-хуков и содержимого custom_hooks_dir на предмет посторонних файлов и ротировать секреты, которые лежали на инстансе.
Комментарии