RCE in Gitea (CVE-2026-60004)

The diffpatch endpoint in Gitea is affected by a vulnerability that allows remote code execution (RCE). The endpoint accepts a patch from the user and applies it to the repository. To do this, Gitea runs the command git apply --index --recount --cached --binary -3 inside a bare temporary clone of the target repository. The vulnerability affects Gitea 1.17–1.27.0 and was fixed in 1.27.1; its CVSS score is 9.8. To understand where the RCE comes from, let’s break down three independent facts.
Fact 1: the -3 flag enables a fallback three-way merge. In normal operation, git apply fails with an error on a conflict. With the -3 flag (on Git ≥ 2.32), Git attempts to resolve the conflict through a three-way merge. If the merge succeeds, Git can write the file to disk. Without -3, this code path does not exist.
Fact 2: an add/add collision forces this path. If the same crafted patch is submitted twice, the second time Git sees that the file already exists in the index and is being added again—this is an add/add collision. In normal mode, the apply operation would fail, but with -3, a three-way merge takes place, and the file is written to disk. The operation was intended to update the index, but in practice the file ends up on disk.
Fact 3: in a bare clone, the repository root is $GIT_DIR. In an empty repository, there is no working directory—the repository root is also the $GIT_DIR, where hooks/ is located. Therefore, a file written to hooks/post-index-change lands directly in the active Git hooks directory. In a non-bare clone, hooks/ is located inside .git/, and a file written to the same relative path would instead be placed in the working tree, not in .git/hooks/.
Putting the three facts together:
  1. Create an account with a repository and obtain write access.
  2. The first created patch writes the payload to hooks/post-index-change—but only to the index, not to disk.
  3. The second patch triggers an add/add collision → Git switches to a three-way merge → checks the payload file out to disk at hooks/post-index-change in the active hooks directory.
  4. Git writes the index and triggers the post-index-change hook
  5. The hook runs as the Gitea service account—this is RCE.
The diffpatch route requires write access to the repository. However, Gitea ships with open registration enabled by default, and on instances where it has not been disabled, an external attacker can complete the entire chain without an existing account—by registering and creating a repository.
The problem class is broader than Gitea. The underlying issue is not specific to Gitea itself: a self-hosted SCM frontend can be vulnerable if it applies attacker-controlled patches in a bare temporary repository using git apply -3, allowing a three-way fallback to write files into $GIT_DIR. Forgejo, a Gitea fork, is affected by the same underlying pattern.
The vulnerability was actively exploited as part of the Red Heron campaign. Acronis reported that the group weaponized CVE-2026-60004 against internet-facing Gitea instances and used the resulting access for source-code theft, credential collection, persistence, and lateral movement. The campaign also involved the JITTERLY implant, which contained the SIXZUT LD_PRELOAD rootkit.
Vulnerabilities
10
CVE-2026-60004
Researchers
Nightrang3R
Vendors
Gitea
Forgejo
Products
Forgejo
Git
Gitea
Jitterly Implant
Sixzut Ld_Preload Rootkit