Skip to main content
All updates

How a Git Patch Turned Into Remote Code Execution: Inside the Gitea CVE-2026-60004 Attack

By Mohammad Karami, PhD

A Git patch is supposed to modify source code. In CVE-2026-60004, however, a carefully crafted patch could end up executing commands on the server running Gitea.

The vulnerability affects Gitea 1.17 through 1.27.0 and has a CVSS score of 9.8 (Critical). It was fixed in Gitea 1.27.1.

First: What Is Gitea?

[Gitea](https://about.gitea.com/) is a self-hosted Git platform similar to GitHub or GitLab. Organizations can use it to host repositories, manage pull requests, track issues, and collaborate on code while keeping the infrastructure under their own control.

One of Gitea's features allows users to submit a Git patch through the API:

POST /api/v1/repos/{owner}/{repo}/diffpatch

Gitea then applies that patch to a temporary Git repository.

That sounds harmless.

The problem was where and how the patch was applied.

The Dangerous Combination

Gitea created a temporary bare Git repository when processing the patch.

Normally, a Git repository looks roughly like this:

project/
├── index.html
├── app.js
└── .git/
    ├── objects/
    ├── refs/
    └── hooks/

But a bare repository has no normal working directory. The repository itself effectively acts as Git's internal $GIT_DIR.

This distinction became important because Git has a special directory:

hooks/

Git hooks are executable programs that Git automatically runs when certain events occur.

For example:

hooks/post-index-change

can execute after Git updates its index.

So if an attacker can somehow place an executable file there, a normal Git operation may become command execution.

From Patch to RCE

Gitea attempted to safely process patches using git apply with --cached. Normally, --cached means:

Update Git's index, but don't write the files into the working directory.

However, Gitea also allowed Git's three-way merge fallback on Git 2.32 and newer.

Researchers found an interesting edge case.

A simplified attack flow looked like this:

Crafted Git patch
      ↓
Gitea applies it to a bare repository
      ↓
Same patch is submitted again
      ↓
Git encounters an add/add conflict
      ↓
Three-way merge fallback is triggered
      ↓
A file is written despite --cached
      ↓
hooks/post-index-change is created
      ↓
Git executes the hook
      ↓
Remote Code Execution

The first patch places the malicious file into Git's index. Applying the same patch again creates a conflict and forces Git into its three-way merge path.

That fallback can materialize the file on disk.

And because the temporary repository is bare, the attacker's path:

hooks/post-index-change

doesn't become an innocent project file.

It becomes an actual Git hook.

Git then executes it automatically during an index operation.

Why This Is Serious

The injected hook executes as the Gitea operating-system account.

Depending on how the server is configured, an attacker could potentially access:

  • private repositories
  • Gitea configuration and application secrets
  • database credentials
  • OAuth or integration credentials
  • environment variables
  • internal services accessible from the Gitea server

The API requires repository write access. However, if a Gitea instance allows open registration, an external attacker may simply create an account and repository to obtain the required permissions.

The Security Lesson

The interesting part of CVE-2026-60004 isn't simply "Git hooks are dangerous."

It's the interaction between several individually reasonable behaviors:

User-controlled patch
        +
Bare Git repository
        +
git apply --cached
        +
Three-way merge fallback
        +
Executable Git hooks
        =
Remote Code Execution

Security vulnerabilities often appear exactly at these boundaries.

Gitea expected a patch to modify repository content.

Git ultimately interpreted part of that content as repository control infrastructure capable of executing code.

That difference in interpretation turned an ordinary patch-processing feature into an RCE vulnerability.

Mitigation

Administrators running affected Gitea versions should upgrade to Gitea 1.27.1 or later.

If upgrading immediately isn't possible, reducing exposure—particularly disabling unnecessary open registration and restricting access to untrusted users—can reduce the attack surface.

CVE: CVE-2026-60004 Severity: Critical — CVSS 9.8 Affected: Gitea ≥ 1.17 and < 1.27.1 Fixed: Gitea 1.27.1

Animated attack flow showing how CVE-2026-60004 turns a Git patch into remote code execution in Gitea