
Gitea до 1.27.1 допускает удалённое выполнение кода через API diffpatch посредством установки Git-хуков.
[!WARNING] Этот репозиторий предназначен исключительно для авторизованных исследований в области безопасности и контролируемого лабораторного тестирования. Не запускайте proof of concept против систем, которыми вы не владеете или на проверку которых у вас нет явного разрешения.
CVE-2026-60004 — критическая уязвимость удалённого выполнения кода в API diffpatch Gitea. Аутентифицированный пользователь с правом создания репозитория или записи в него может отправить специально сформированный патч, который приводит к материализации исполняемого Git-хука внутри временного bare-репозитория. При срабатывании хука контролируемые злоумышленником команды выполняются с привилегиями служебной учётной записи Gitea.
Если включена публичная регистрация, неаутентифицированный злоумышленник может создать учётную запись и получить доступ к уязвимой конечной точке, требующей аутентификации.
| Атрибут | Детали |
|---|---|
| Идентификатор | CVE-2026-60004 |
| Рекомендация | GHSA-rcr6-4jqh-j84m |
| Критичность | Критическая — CVSS 3.1: 9.8 |
| Слабость | CWE-94: Некорректный контроль генерации кода |
| Уязвимые версии | Gitea 1.17.0 — 1.27.0 |
| Исправленная версия | Gitea 1.27.1 |
| Требуемый доступ | Право записи в репозиторий |
| Контекст выполнения | Учётная запись операционной системы Gitea |
| Дата CISA KEV | 2026-08-25 |
| Файл | Описание |
|---|---|
gitea_diffpatch_rce.py | Proof of concept, использующий только стандартную библиотеку: выполняет аутентификацию, создаёт приватный репозиторий, отправляет сформированный патч и получает вывод команды. |
payload.patch | Пример патча, создающего исполняемый хук hooks/post-index-change. |
poc.png | Скриншот, сделанный во время лабораторной проверки. |
README.md | Исходные заметки исследования. |
Proof of concept был проверен в следующей изолированной среде:
| Компонент | Конфигурация |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Развёртывание | Docker-контейнер с именем gitea-lab |
| Адрес сервиса | 192.168.184.128:3000 |
| Наблюдаемая идентичность | uid=1000(git) gid=1000(git) |
Успешная эксплуатация давала вывод команды, подобный следующему:
uid=1000(git) gid=1000(git) groups=1000(git)
Linux 6.12.20-amd64 x86_64
/data/gitea/tmp/local-repo/upload.git630501597
[exit-status=0]

Скрипт использует только стандартную библиотеку Python и не требует дополнительных пакетов.
python3 gitea_diffpatch_rce.py <base_url> <username> <password> "<command>"
Пример для локального лабораторного экземпляра:
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
Скрипт сначала пытается выполнить веб-регистрацию, затем аутентифицируется с указанными учётными данными. Это позволяет одной и той же команде работать как с новой учётной записью на экземпляре с открытой регистрацией, так и с существующей учётной записью.
Цепочка эксплуатации состоит из четырёх этапов:
Отправка контролируемого злоумышленником патча
POST /api/v1/repos/{owner}/{repo}/diffpatch применяет переданное содержимое
патча с помощью git apply --index --recount --cached --binary --ignore-whitespace --whitespace=fix -3 внутри временного клона.
Размещение пути хука
Временный репозиторий создаётся как bare-клон с общим доступом. В
bare-репозитории корень репозитория также является $GIT_DIR; следовательно,
путь патча hooks/post-index-change разрешается внутри активного каталога
хуков Git.
Материализация исполняемого хука
Один и тот же патч отправляется дважды. Второе применение вызывает
конфликт add/add, из-за чего трёхсторонний откат материализует путь на
диске с режимом 100755, несмотря на использование --cached. Последующее
обновление индекса вызывает post-index-change, выполняя внедрённый
shell-код от имени служебной учётной записи Gitea.
Получение вывода средствами Git
Хук определяет исходный репозиторий через
objects/info/alternates, сохраняет вывод команды как Git-блоб, создаёт
дерево и коммит и обновляет refs/heads/output-leak. Затем proof of concept
получает результат через API raw-файлов Gitea. Этот метод не требует
прямого исходящего соединения с целевой системы.
Успешная эксплуатация даёт выполнение команд с привилегиями служебной учётной записи Gitea. В зависимости от конфигурации развёртывания злоумышленник может получить доступ к:
app.ini и учётным данным базы данныхSECRET_KEY, INTERNAL_TOKEN и секретам, связанным с LFSБыло подтверждено, что лабораторная учётная запись имеет доступ на чтение к
app.ini.
Защитникам следует исследовать следующие артефакты и шаблоны запросов:
/api/v1/repos/*/*/diffpatch с малым интерваломoutput-leakpoc <[email protected]>hooks/post-index-change в
bare-репозиториях или каталогах временных клонов/data/gitea/tmp/local-repo/upload.git*Эти индикаторы описывают включённый proof of concept и не являются исчерпывающими; модифицированный эксплойт может использовать другие пути, ссылки, идентичности или каналы вывода.
/api/v1/.../diffpatch.
Перед развёртыванием проверьте правило на легитимных интеграциях.DISABLE_REGISTRATION=true,
если она не требуется операционно. Это снижает доступность для
неаутентифицированных пользователей, но не защищает от существующих
пользователей с правом записи в репозиторий.Для лабораторного контейнера, использованного в этом исследовании, удаление можно выполнить командой:
docker rm -f gitea-lab
Этот материал предоставлен, чтобы помочь защитникам воспроизвести, понять, обнаружить и устранить уязвимость. Операторам следует тестировать только в изолированных средах и соблюдать требования своей организации к авторизации и раскрытию информации.