
Gitea anterior à 1.27.1 permite execução remota de código através da API diffpatch por meio da instalação de Git hooks.
[!WARNING] Este repositório destina-se exclusivamente a pesquisa de segurança autorizada e testes controlados em laboratório. Não execute a prova de conceito contra sistemas que você não possui ou para os quais não tem permissão explícita de avaliação.
CVE-2026-60004 é uma vulnerabilidade crítica de execução remota de código na API diffpatch do Gitea. Um usuário autenticado com permissão para criar ou escrever em um repositório pode enviar um patch elaborado que faz com que um hook Git executável seja materializado dentro de um repositório bare temporário. Quando o hook é acionado, comandos controlados pelo atacante são executados com os privilégios da conta de serviço do Gitea.
Se o registro público estiver habilitado, um atacante não autenticado pode conseguir criar uma conta e alcançar o endpoint autenticado vulnerável.
| Atributo | Detalhes |
|---|
| Identificador | CVE-2026-60004 |
| Aviso | GHSA-rcr6-4jqh-j84m |
| Severidade | Crítica — CVSS 3.1: 9.8 |
| Fraqueza | CWE-94: Controle Impróprio da Geração de Código |
| Versões afetadas | Gitea 1.17.0 até 1.27.0 |
| Versão corrigida | Gitea 1.27.1 |
| Acesso necessário | Permissão de escrita no repositório |
| Contexto de execução | Conta de sistema operacional do Gitea |
| Data do CISA KEV | 2026-08-25 |
| Arquivo | Descrição |
|---|---|
gitea_diffpatch_rce.py | Prova de conceito que usa apenas a biblioteca padrão, autentica, cria um repositório privado, envia o patch elaborado e recupera a saída do comando. |
payload.patch | Patch de exemplo que cria um hook executável hooks/post-index-change. |
poc.png | Captura de tela obtida durante a validação em laboratório. |
README.md | Notas de pesquisa originais. |
A prova de conceito foi validada no seguinte ambiente isolado:
| Componente | Configuração |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Implantação | Contêiner Docker chamado gitea-lab |
| Endereço do serviço | 192.168.184.128:3000 |
| Identidade observada | uid=1000(git) gid=1000(git) |
A exploração bem-sucedida produziu uma saída de comando semelhante a:
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]

O script usa apenas a biblioteca padrão do Python e não requer pacotes adicionais.
python3 gitea_diffpatch_rce.py <base_url> <username> <password> "<command>"
Exemplo para uma instância de laboratório local:
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
O script primeiro tenta o registro via web e, em seguida, autentica com as credenciais fornecidas. Isso permite que o mesmo comando funcione tanto com uma nova conta em uma instância com registro aberto quanto com uma conta existente.
A cadeia de exploração consiste em quatro estágios:
Envio de patch controlado pelo atacante
POST /api/v1/repos/{owner}/{repo}/diffpatch aplica o conteúdo de patch fornecido
usando git apply --index --recount --cached --binary --ignore-whitespace --whitespace=fix -3 dentro de um clone temporário.
Posicionamento do caminho do hook
O repositório temporário é criado como um clone bare e compartilhado. Em um
repositório bare, a raiz do repositório também é $GIT_DIR; consequentemente, o
caminho do patch hooks/post-index-change é resolvido dentro do diretório de hooks
ativo do Git.
Materialização do hook executável
O mesmo patch é enviado duas vezes. A segunda aplicação produz um conflito add/add,
fazendo com que o fallback de três vias materialize o caminho em disco com modo
100755, apesar do uso de --cached. Uma atualização subsequente do índice invoca
post-index-change, executando o código shell injetado como a conta de serviço do
Gitea.
Recuperação de saída nativa do Git
O hook identifica o repositório de origem através de
objects/info/alternates, armazena a saída do comando como um blob Git, cria uma
árvore e um commit, e atualiza refs/heads/output-leak. A prova de conceito então
recupera o resultado através da API de arquivos brutos do Gitea. Essa técnica não
requer uma conexão de saída direta a partir do alvo.
A exploração bem-sucedida concede execução de comandos com os privilégios da conta de serviço do Gitea. Dependendo da configuração de implantação, um atacante pode conseguir acessar:
app.ini e credenciais de banco de dadosSECRET_KEY, INTERNAL_TOKEN e segredos relacionados ao LFSFoi confirmado que a conta do laboratório tinha acesso de leitura a app.ini.
Defensores devem investigar os seguintes artefatos e padrões de requisição:
/api/v1/repos/*/*/diffpatch em rápida sucessãooutput-leakpoc <[email protected]>hooks/post-index-change em repositórios
bare ou diretórios de clone temporários/data/gitea/tmp/local-repo/upload.git*Esses indicadores descrevem a prova de conceito incluída e não são exaustivos; um exploit modificado pode usar caminhos, refs, identidades ou canais de saída diferentes.
/api/v1/.../diffpatch.
Valide a regra em relação a integrações legítimas antes da implantação.DISABLE_REGISTRATION=true se isso
não for operacionalmente necessário. Isso reduz a alcançabilidade não autenticada, mas
não protege contra usuários existentes com permissão de escrita em repositórios.Para o contêiner de laboratório usado nesta pesquisa, a remoção pode ser realizada com:
docker rm -f gitea-lab
Este material é fornecido para ajudar defensores a reproduzir, compreender, detectar e corrigir a vulnerabilidade. Operadores devem testar apenas em ambientes isolados e seguir os requisitos de autorização e divulgação de sua organização.