Skip to content
RESEARCH INDEX BREACHROAD / INTELLIGENCE NOTE

CVE-2026-60004: critical Gitea RCE through a Git hook

Gitea before 1.27.1 let repository writers create a live Git hook and execute server commands. Review preconditions, impact and remediation.

PUBLIC RESEARCH
AUTHOR
/ CEO of Breachroad · OSCP · PNPT
PUBLISHED
29 July 2026
READING TIME
13 min read
TOPIC
Vulnerabilities and CVEs
CVE-2026-60004: critical Gitea RCE through a Git hook

Detailed analysis published on 29 July 2026 describes CVE-2026-60004, a critical RCE vulnerability in self-hosted Gitea. The flaw is in the diffpatch endpoint: a user with ordinary repository write access can cause an executable Git hook to be placed inside a temporary repository’s control directory and run commands as the Gitea operating-system account.

The CVSS score is 9.8. Gitea versions from 1.17 up to, but not including, 1.27.1 are affected. The official advisory does not report exploitation in the wild, but it includes a public proof of concept. That combination warrants an urgent 1.27.1 rollout and review of the exposure window.

Essential facts

Gitea’s official GHSA-rcr6-4jqh-j84m advisory confirms:

  • affected versions are Gitea 1.17 and later before 1.27.1;
  • the patched version is 1.27.1;
  • repository write permission is required;
  • code executes as the Gitea operating-system account;
  • default open registration can let an external visitor create an account and repository;
  • technical triggering requires Git 2.32+, an enabled diffpatch route and a writable, executable temporary filesystem;
  • the project does not report active exploitation.

Reporting on 29 July also notes why the fix may be overlooked. Gitea 1.27.1 shipped on 27 July, while its release note described the relevant change neutrally as “refactor: git patch apply.”

The vulnerable chain without republishing a payload

The POST /api/v1/repos/{owner}/{repo}/diffpatch route applies a supplied patch inside a temporary clone. In the vulnerable implementation, the clone is bare: it has no conventional working tree, and its root is also $GIT_DIR.

Gitea invoked git apply with index-related options and, on Git 2.32 or later, the three-way fallback. Applying a carefully prepared change twice could create an add/add conflict. The fallback materialized an indexed path despite --cached mode.

In an ordinary repository, a hooks/... path would simply be working-tree content. In a bare clone, the same path can land directly in Git’s hook directory. If executable and named for a supported hook, Git invokes it during index processing.

The lesson is that the application treated a patch as repository data, while Git interpreted the result inside its own executable control directory. The two layers disagreed about what the path meant.

Why “requires an account” does not automatically reduce risk

The endpoint rejects unauthenticated requests. Many Gitea installations, however, retain the default configuration that permits open registration, requires no email confirmation or manual approval, and lets a new user create a repository. In that environment, an internet visitor can obtain write permission through the legitimate registration form.

Open registration is therefore part of the attack path. Disabling it removes the “new external user” variant, but it:

  • does not fix vulnerable code;
  • does not protect against an existing ordinary user;
  • does not protect against a compromised developer account;
  • does not remove insider or tenant risk on a shared platform.

This explains why the advisory uses PR:N in its CVSS assessment even though the technical operation occurs in an authenticated session with repository write access.

Impact depends on service isolation

Commands execute as the Gitea service user, not automatically as root. That remains a serious access level. The official advisory lists:

  • app.ini and Gitea application secrets;
  • process environment secrets;
  • mounted repositories;
  • database credentials and contents;
  • OAuth and integration credentials;
  • other internal or external services reachable from the host.

If Gitea runs in a container as an unprivileged user, with a read-only filesystem, separate volumes and restricted egress, blast radius is smaller. If it runs on a host with broad mounts, a Docker socket, deployment tokens and a route to the management network, a Git hook can become the beginning of a CI/CD compromise.

The fix restores a directory boundary

The remediation commit changes the temporary clone from bare to non-bare. The working tree is then separate from $GIT_DIR, and content supplied by a patch does not automatically become an active hook.

This addresses the cause rather than denying one post-index-change name. A one-hook blocklist would be brittle because Git supports multiple hooks and other operations might materialize paths under its control directory. Separating repository data from Git metadata restores the correct boundary.

Immediate actions

  1. Upgrade to Gitea 1.27.1 or later. Read the version from the running application, image and container.
  2. Temporarily disable open registration where it is not required. Do not treat this as a substitute for patching.
  3. Restrict the diffpatch route during emergency deployment if the architecture permits and the change is tested.
  4. Preserve temporary directories and logs before restarting when use is suspected.
  5. Review the Gitea user’s privileges, mounts, environment variables and reachable services.
  6. Withdraw vulnerable images from registries and prevent their return through IaC.

Gitea Cloud said managed instances would be upgraded automatically. Customers should still obtain version and deployment-time evidence, especially where integrations or runners remain outside the managed service.

Reviewing the exposure window

No confirmed exploitation does not remove the need for a log review. The public PoC can retrieve output without an outbound callback: a hook may store results in Git objects and expose them through the normal repository protocol. Detection based only on a connection to an external C2 could miss it.

Review:

  • calls to diffpatch, particularly repetitions of the same change;
  • new accounts and repositories created shortly before unusual activity;
  • hooks/ paths in patch data or temporary clones;
  • Gitea or Git child processes launching a shell;
  • new branches or Git objects with unusual names;
  • reads of app.ini, environment files, runner configuration and credentials;
  • changes to tokens, webhooks, deploy keys and repository settings.

Adapt these hypotheses to the installation’s logging. If /tmp is cleared during restart, evidence may disappear, which makes pre-update imaging important where abuse is suspected.

Hardening after the update

Run Gitea as a separate non-login user with minimum volume permissions. Deployment secrets should not remain in the web process when a runner can receive a short-lived identity. Restrict egress to required registries and webhooks, and route production deployment through a separate CI/CD layer with approval.

Also consider:

  • approving new accounts or using SSO;
  • restricting organization and repository creation;
  • enforcing MFA for administrators and owners;
  • isolating runners from the Gitea server;
  • rotating deploy keys and webhook secrets;
  • scanning images and SBOMs after updates;
  • monitoring child processes of the service account.

Use this case in cybersecurity training for technical teams: an apparently safe “apply patch” function delegates data to a tool with its own executable mechanisms.

Verifying remediation without RCE

There is no need to execute the public PoC in production. Demonstrate:

  • 1.27.1+ on every active instance;
  • no old image in running workloads;
  • the correct backport commit if a fork is used;
  • working-tree separation from $GIT_DIR in a safe integration test;
  • no execution of a harmless marker as a hook;
  • normal diffpatch operation for legitimate changes.

An independent IT security audit or web and API penetration test can also cover registration, roles, repositories, webhooks, runners and secrets—areas that a CVE version scan cannot assess.

Sources and inference limits

Version, precondition, impact and PoC facts come from GHSA-rcr6-4jqh-j84m, the 1.27.1 release and the fix commit. New reporting appeared on 29 July in The Hacker News.

None of the cited sources confirms active exploitation. Detection and isolation guidance are BreachRoad analysis. A public PoC exists, but safe production validation does not require it; a patched version and evidence of the restored directory boundary are the correct retest goals.

Hunt the exposure window without running the PoC

There is no need to reproduce a public payload in production. Establish when each instance first ran an affected version, when 1.27.1 was installed, its Git version, temporary-directory settings, registration policy and users with repository write access.

Then correlate safe evidence:

  • requests to the diffpatch route, especially repeated operations against one repository;
  • files created under hooks paths in temporary repositories;
  • Gitea child processes not explained by normal administration;
  • outbound network activity from the service account;
  • new SSH keys, tokens, webhooks or accounts after the suspicious time;
  • repository changes attributed to the service identity rather than a user.

Missing route or process logs do not establish non-exploitation; record them as visibility limitations. Our Sigma and SIEM detection-engineering guide explains how to maintain these correlations, while an incident-response plan turns findings into containment and rotation decisions.

Service-account reach defines impact

RCE runs with the Gitea process privileges, so impact depends on its environment. The account may reach the database, object storage, signing keys, webhook secrets, OAuth configuration and repositories. A container limits parts of the filesystem but does not automatically protect secrets in environment variables and mounted volumes.

When exploitation is confirmed or credible, map every credential available to the service and rotate it in impact order. Restarting a pod does not revoke a stolen token. Review activity after the software update as well, because a credential obtained earlier can preserve access outside Gitea.

A safe regression test

Retest 1.27.1 or later by validating a legitimate patch and confirming that an executable file cannot reach the hook directory. Use a harmless marker in an isolated environment without production secrets. Keep the case as an automated regression test around diff application.

The issue connects application security with Git trust boundaries. Our software supply-chain attack guide explores similar boundary failures, while the Breachroad Academy reinforces authorisation and observability fundamentals. The final objective is not merely absence of one CVE: it is a least-privileged Gitea account, closed registration where unnecessary and evidence that attempted abuse will trigger an alert.

SHARE / COPY