## https://sploitus.com/exploit?id=8F6A462F-FE9E-5CC7-9551-8CAFC43FD570
# CVE-2026-60004: Gitea Diffpatch API Remote Code Execution
> [!WARNING]
> This repository is intended exclusively for authorized security research and
> controlled laboratory testing. Do not run the proof of concept against
> systems you do not own or have explicit permission to assess.
## Overview
CVE-2026-60004 is a critical remote code execution vulnerability in Gitea's
diffpatch API. An authenticated user with permission to create or write to a
repository can submit a crafted patch that causes an executable Git hook to be
materialized inside a temporary bare repository. When the hook is triggered,
attacker-controlled commands execute with the privileges of the Gitea service
account.
If public registration is enabled, an unauthenticated attacker may be able to
create an account and reach the vulnerable authenticated endpoint.
| Attribute | Details |
|---|---|
| Identifier | CVE-2026-60004 |
| Advisory | GHSA-rcr6-4jqh-j84m |
| Severity | Critical β CVSS 3.1: 9.8 |
| Weakness | CWE-94: Improper Control of Generation of Code |
| Affected versions | Gitea 1.17.0 through 1.27.0 |
| Fixed version | Gitea 1.27.1 |
| Required access | Repository write access |
| Execution context | Gitea operating-system account |
| CISA KEV date | 2026-08-25 |
## Repository Contents
| File | Description |
|---|---|
| [`gitea_diffpatch_rce.py`](gitea_diffpatch_rce.py) | Standard-library-only proof of concept that authenticates, creates a private repository, submits the crafted patch, and retrieves command output. |
| [`payload.patch`](payload.patch) | Example patch that creates an executable `hooks/post-index-change` hook. |
| [`poc.png`](poc.png) | Screenshot captured during laboratory validation. |
| [`README.md`](README.md) | Original research notes. |
## Tested Environment
The proof of concept was validated in the following isolated environment:
| Component | Configuration |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Deployment | Docker container named `gitea-lab` |
| Service address | `192.168.184.128:3000` |
| Observed identity | `uid=1000(git) gid=1000(git)` |
Successful exploitation produced command output similar to:
```text
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]
```

## Prerequisites
- Python 3.8 or later
- Network access to the target Gitea instance
- A valid Gitea account with repository creation and write permissions, or a
target laboratory instance with public registration enabled
- An explicitly authorized test environment
The script uses only Python's standard library and does not require additional
packages.
## Usage
```bash
python3 gitea_diffpatch_rce.py ""
```
Example for a local laboratory instance:
```bash
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
```
The script first attempts web registration, then authenticates with the supplied
credentials. This allows the same command to work with either a new account on
an instance with open registration or an existing account.
## Technical Analysis
The exploitation chain consists of four stages:
1. **Attacker-controlled patch submission**
`POST /api/v1/repos/{owner}/{repo}/diffpatch` applies supplied patch content
using `git apply --index --recount --cached --binary --ignore-whitespace
--whitespace=fix -3` within a temporary clone.
2. **Hook path placement**
The temporary repository is created as a bare, shared clone. In a bare
repository, the repository root is also `$GIT_DIR`; consequently, the patch
path `hooks/post-index-change` resolves inside Git's active hooks directory.
3. **Executable hook materialization**
The same patch is submitted twice. The second application produces an
add/add conflict, causing the three-way fallback to materialize the path on
disk with mode `100755`, despite the use of `--cached`. A subsequent index
update invokes `post-index-change`, executing the injected shell code as the
Gitea service account.
4. **Git-native output retrieval**
The hook identifies the origin repository through
`objects/info/alternates`, stores command output as a Git blob, creates a
tree and commit, and updates `refs/heads/output-leak`. The proof of concept
then retrieves the result through Gitea's raw-file API. This technique does
not require a direct outbound connection from the target.
## Impact
Successful exploitation grants command execution with the privileges of the
Gitea service account. Depending on deployment configuration, an attacker may
be able to access:
- `app.ini` and database credentials
- `SECRET_KEY`, `INTERNAL_TOKEN`, and LFS-related secrets
- Repositories mounted or readable by the Gitea process
- Process environment variables
- Internal services reachable from the Gitea host or container
The laboratory account was confirmed to have read access to `app.ini`.
## Indicators of Compromise
Defenders should investigate the following artifacts and request patterns:
- Two identical or near-identical requests to
`/api/v1/repos/*/*/diffpatch` in quick succession
- A branch named `output-leak`
- Commits authored by `poc `
- Unexpected executable files named `hooks/post-index-change` in bare
repositories or temporary clone directories
- Suspicious activity below paths such as
`/data/gitea/tmp/local-repo/upload.git*`
These indicators describe the included proof of concept and are not exhaustive;
a modified exploit may use different paths, refs, identities, or output channels.
## Remediation and Mitigation
1. **Upgrade to Gitea 1.27.1 or later.** This is the recommended remediation.
The fix changes the affected workflow to use a non-bare temporary clone.
2. **Restrict the diffpatch API at the reverse proxy** until the upgrade is
complete, for example by denying access to matching `/api/v1/.../diffpatch`
routes. Validate the rule against legitimate integrations before deployment.
3. **Disable public registration** by setting `DISABLE_REGISTRATION=true` if it
is not operationally required. This reduces unauthenticated reachability but
does not protect against existing users with repository write access.
4. **Review logs and repository refs** for the indicators above, and rotate
credentials or secrets accessible to the Gitea account if compromise is
suspected.
For the laboratory container used in this research, teardown can be performed
with:
```bash
docker rm -f gitea-lab
```
## Responsible Use
This material is provided to help defenders reproduce, understand, detect, and
remediate the vulnerability. Operators should test only in isolated environments
and follow their organization's authorization and disclosure requirements.