GitLab закрыл переполнение кучи в Git, которое вело к выполнению команд в Gitaly

GitLab

GitLab выпустила патчи 19.3.8, 19.4.6 и 19.5.4 для Community Edition и Enterprise Edition. Они закрывают CVE-2026-105437 - переполнение буфера в куче в Git, который входит в поставку платформы. При определённых условиях ошибка позволяет выполнить произвольные команды в среде Gitaly, то есть на сервере, а не в браузере жертвы. Для попытки атаки достаточно учётной записи с правом отправки веток и открытия запроса на слияние. Обновляться нужно тем, кто держит self-managed установки начиная с версии 16.2.

Условия атаки

Ошибка находится не в веб-приложении GitLab, а в самом Git. GitLab собирает собственную сборку Git и запускает её внутри Gitaly - сервиса, который обслуживает операции с репозиториями: приём изменений, клонирование, слияния. Поэтому выполнение кода в Gitaly означает выполнение кода на сервере.

Срабатывает всё на трёхстороннем слиянии. GitLab запускает его автоматически, когда пользователь открывает или обновляет merge request: сервер проверяет, можно ли слить ветки без конфликтов.

Где именно ошибка

При слиянии Git формирует итоговый файл и хранит его размер в переменной типа int. Это 32-битное целое, верхняя граница около 2 ГиБ. Размер маркера конфликта Git берёт из атрибута conflict-marker-size, который задаётся в .gitattributes. Маркеры записываются в результат многократно, отдельным блоком на каждый конфликт.

Отсюда простая арифметика. Большой размер маркера плюс много мелких конфликтов дают суммарный объём больше 4 ГиБ. int переполняется, и Git продолжает писать данные за границей выделенного буфера. Это и есть переполнение кучи: память под результат выделена, но запись выходит за её пределы.

Важная деталь - источник значения. Атрибут приходит из закоммиченного .gitattributes, то есть его задаёт автор ветки, а не администратор сервера. Отдельных прав для этого не требуется.

Кто может атаковать

Атакующему достаточно учётной записи, которая может отправлять ветки в проект и открывать merge request. По описанию GitLab шаги выглядят так: добавить .gitattributes с большим conflict-marker-size, создать две ветки с множеством мелких конфликтов и инициировать проверку слияния. Никакого взаимодействия с другим пользователем не нужно.

Последствия зависят от того, что находится рядом с процессом Gitaly. Это доступ к репозиториям, переменным CI, токенам развёртывания и внутренней сети. Именно поэтому выпуск получил статус критического, хотя формальная оценка ниже.

Здесь стоит отделить факт от предположения. GitLab указывает, что выполнение команд в Gitaly возможно, но не раскрывает, при каких настройках переполнение гарантированно превращается в исполнение кода. Речь о потенциальной возможности, а не о готовом сценарии для любой инсталляции. Многое решают сборка Git, версия Gitaly и режим серверных проверок слияния.

Затронутые версии

Уязвимы self-managed установки Community Edition и Enterprise Edition. Диапазон начинается с 16.2: под исправление попадают ветки 19.3 до 19.3.8, 19.4 до 19.4.6 и 19.5 до 19.5.4.

GitLab.com и GitLab Dedicated уже пропатчены, их пользователям ничего делать не нужно. Для остальных важен другой вывод: чем старее ветка, тем дольше установка работает без исправления, а обновление через несколько мажорных версий сложнее по срокам.

Оценка CVE - 7.5 по CVSS 3.1. GitLab при этом классифицирует выпуск как критический: оценка не отражает последствия выполнения кода в Gitaly. В бюллетене нет сведений об эксплуатации в реальных атаках.

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

Обновление до 19.3.8, 19.4.6 или 19.5.4 закрывает CVE-2026-105437 в поставляемой сборке Git. Патч устраняет саму причину: переполнение при подсчёте размера результата слияния больше не возникает.

Для self-compiled установок обновления пакета GitLab недостаточно. Нужно пересобрать Git внутри Gitaly, иначе уязвимый код останется на месте. Если Gitaly использует системный Git, обновите его до 2.56.1 или до версии, где ошибка закрыта.

Проверьте не только сам сервер, но и обвязку: образы контейнеров, сборочные пайплайны, конфигурацию Omnibus и сторонние сборки. Рассинхронизация версий здесь типична, особенно когда Git ставили отдельно от пакета платформы.

Если обновиться нельзя

GitLab предлагает переопределить атрибут в каждом репозитории. В файле info/attributes, который лежит вне рабочего дерева и не может быть изменён автором ветки, добавляется строка "* conflict-marker-size=7". Она перекрывает значение из закоммиченного .gitattributes.

Второй вариант - отключить серверные проверки mergeability для недоверенных репозиториев. Это убирает автоматический запуск слияния на стороне сервера, но снижает удобство работы и не устраняет ошибку в Git. Как долгосрочная мера такой обход не годится.

Полезно проверить существующие репозитории на подозрительные значения conflict-marker-size в .gitattributes. Аномально большое число в истории проекта стоит разобрать отдельно: возможно, ветку готовили заранее.

Ограничение прав тоже помогает, но частично. Если внешние контрибьюторы не могут отправлять ветки в проект, вектор атаки закрывается. Однако внутренние пользователи и сервисные учётные записи остаются.

Что сделать в первую очередь

Сначала соберите инвентаризацию: какие версии GitLab и Git работают в Gitaly на каждом узле. Приоритет - инсталляции, куда могут отправлять ветки внешние пользователи: публичные проекты, форки, открытая регистрация.

Затем обновите платформу до 19.3.8, 19.4.6 или 19.5.4. Для self-compiled добавьте пересборку Git в Gitaly отдельным пунктом регламента. После обновления убедитесь, что версия Git на узлах действительно изменилась.

До обновления примените обход в info/attributes для репозиториев с внешним доступом. После - просмотрите журналы Gitaly на аварийные завершения процессов слияния и необычные всплески памяти. Отдельно проверьте .gitattributes в проектах, где недавно появлялись новые контрибьюторы.

Ссылки

Комментарии: 0