CISA adds critical Gitea RCE CVE-2026-60004 to its KEV catalog. Discover how default registration settings enable Git hook exploitation and host takeover.
Self-hosted developer infrastructure faced an urgent security reckoning after the Cybersecurity and Infrastructure Security Agency added a critical remote code execution flaw in Gitea to its Known Exploited Vulnerabilities catalog on August 25, 2026. Discovered and reported by security researcher Shai Rod (NightRang3r), the flaw is tracked as CVE-2026-60004 (GHSA-rcr6-4jqh-j84m) with a maximum CVSS 9.8 (Critical) rating. The vulnerability allows unauthenticated remote actors to plant executable Git hooks on internet-facing instances, executing arbitrary commands within the server environment.
The flaw affects Gitea versions 1.17.0 through 1.27.0. Upstream maintainers released fixes in versions 1.27.1, 1.27.2, and 1.27.3 on July 27, 2026, where the initial remediation in pull request #38514 was discreetly cataloged under release notes as a miscellaneous refactoring of Git patch application before public vulnerability advisories were published. Automated threat actors began weaponizing the vulnerability across global virtual private server providers within weeks of disclosure.
Initial code execution does not grant instant administrative root privileges over the host. Instead, payloads run under the unprivileged service account operating the Gitea daemon—typically uid=1000 (git). Host takeover occurs only when underlying infrastructure contains secondary privilege escalation vectors, such as permissive sudo rules, exposed Docker sockets, unconfined containers, or outdated Linux kernels. However, even an unprivileged footprint grants attackers immediate access to internal application databases, private source repositories, and local network perimeters.
| Vulnerability Attribute | Technical Specification |
|---|---|
| CVE Identifier | CVE-2026-60004 (GHSA-rcr6-4jqh-j84m) |
| CVSS v3.1 Score | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8 Critical) |
| CWE Classification | CWE-94: Improper Control of Generation of Code |
| Affected Versions | Gitea 1.17.0 through 1.27.0 |
| Fixed Releases | Gitea 1.27.1, 1.27.2, 1.27.3 |
| Execution Context | Unprivileged service daemon (uid=1000 git) |
[[image:poster]]
Anatomy of CVE-2026-60004: Diffpatch Add/Add Collisions
The vulnerability resides within services/repository/files/patch.go, which implements Gitea’s diffpatch REST API endpoint:
POST /api/v1/repos/{owner}/{repo}/diffpatch
Content-Type: application/json
{
"content": "<base64_encoded_unified_diff>",
"branch": "main"
}
The endpoint allows users with repository write permissions to apply unified diff patches directly over HTTP. In vulnerable versions, Gitea processed incoming patches by creating a temporary Git index pointing directly to the target repository's bare storage directory and invoking the system Git binary:
git apply --index --recount --cached --binary -3
In standard software working trees, Git maintains configuration and hooks inside a separate .git directory, and the git apply utility explicitly blocks patch writes targeting .git/hooks/. Gitea, however, manages on-disk repositories as bare Git repositories where core.bare = true. In a bare repository, there is no isolated working tree; the repository root directory itself serves as $GIT_DIR.
Beginning with Git version 2.32, the three-way merge fallback (-3) handles conflicting additions by reconstructing the conflicted file directly in the active index. When an attacker crafts a unified diff targeting the relative file path hooks/post-index-change and transmits identical patch requests twice in rapid succession, the duplicate submission triggers an add/add collision:
The initial patch stages the hook definition within the temporary index cache. The replayed patch forces an add/add conflict, causing Git's three-way merge engine to write the executable script directly into $GIT_DIR/hooks/post-index-change with file mode 0755.
Because Git's client-side post-index-change hook triggers automatically whenever index files synchronize during operations like git checkout-index or git read-tree, Gitea’s commit finalization routine executes the malicious hook script under the daemon's runtime credentials.
To remediate the vulnerability, Gitea maintainers switched the diffpatch temporary workspace from a bare repository clone to a standard non-bare clone equipped with a dedicated working tree. In a non-bare tree, Git CLI safeguards actively prevent file writes into internal hook directories.
In-the-Wild Exploitation and Case Study
Exploitation campaigns capitalized on instances exposed directly to the public internet. Documented abuse involving virtual private servers hosted on providers like HOSTKEY revealed automated scanning botnets targeting open Gitea HTTP endpoints and version headers.
Forensic timelines demonstrate a repeatable exploitation chain:
- Automated Registration: The botnet accesses unauthenticated registration endpoints, provisioning random user accounts without requiring email confirmation.
- Repository Provisioning: The threat actor creates a transient private repository, fulfilling the write-permission authorization check on the diffpatch endpoint.
- Hook Deployment: Replaying duplicate diffpatch requests triggers the add/add collision, writing a staging script into
hooks/post-index-change. - Environment Scrubbing: The executed hook sanitizes dynamic linking variables to bypass local security monitoring tools:
unset LD_PRELOAD LD_LIBRARY_PATH
- Payload Staging: The hook fetches an unconfirmed miner-like payload dropper that drove sustained CPU utilization above 70%, triggering provider throttling and abuse alerts.
Threat Hunting and Process Artifacts
Security teams operating self-hosted instances should audit on-disk repository storage pools and runtime process trees for signs of compromise.
In legitimate Gitea deployments, hooks within /var/lib/gitea/data/repositories/ consist of symbolic links referencing the main Gitea binary. Any standalone script or binary located inside a repository's hooks/ directory indicates tampering:
# Locate unauthorized post-index-change hooks across repository storage
find /var/lib/gitea/data/repositories/ -type f -name "post-index-change" -ls
# Scan for standalone executable files within hooks directories
find /var/lib/gitea/data/repositories/ -path "*/hooks/*" -type f -executable ! -name "*.sample" -exec file {} +
# Audit system memory for processes executing from deleted binaries
ls -l /proc/*/exe 2>/dev/null | grep '(deleted)'
Suspicious process lineages include instances where the Gitea daemon or child Git processes spawn /bin/sh, curl, wget, or interactive shells.
Auditing app.ini Defaults and Purging Accounts
The diffpatch endpoint requires write privileges on the target repository. However, Gitea's default configuration file (app.ini) prioritizes rapid onboarding over perimeter defense:
| Configuration Parameter | Default Value | Security Risk |
|---|---|---|
DISABLE_REGISTRATION | false | Permits open account creation for any unauthenticated remote visitor. |
REGISTER_EMAIL_CONFIRM | false | Activates new user accounts immediately without email validation. |
ENABLE_OPENID_SIGNUP | true | Allows external identity provisioning without administrative review. |
REQUIRE_SIGNIN_VIEW | false | Exposes platform metadata and public endpoints without credentials. |
Because newly created accounts automatically receive full ownership and write privileges over their own repositories, open registration collapses the authentication boundary, granting remote visitors the permissions needed to execute the exploit.
Security teams can audit underlying database instances to detect signup bursts:
-- Identify automated registration spikes grouped by day
SELECT
DATE(created_unix, 'unixepoch') AS registration_date,
COUNT(*) AS total_signups
FROM "user"
WHERE type = 0
GROUP BY registration_date
ORDER BY registration_date DESC
LIMIT 30;
To prevent leaving orphaned records across relational database tables, administrators should purge illicit accounts using the native Gitea administrative command-line interface:
# Cleanly delete malicious accounts and all associated repository objects
gitea admin user delete --username "attacker_bot" --purge --config /etc/gitea/app.ini
Defense-in-Depth Remediation
Remediating CVE-2026-60004 requires software updates paired with perimeter and operating-system isolation:
- Upgrade Software: Update installations immediately to Gitea version 1.27.1 or higher.
- Close Public Registration: Edit
app.inito enforceDISABLE_REGISTRATION = true,REQUIRE_SIGNIN_VIEW = true, and setENABLE_OPENID_SIGNUP = falseunder[openid]. - Filesystem Hardening: Mount temporary directories (
/tmp,/dev/shm) and repository storage withnoexec,nosuid,nodevoptions in/etc/fstabto block direct script execution. - Container Sandboxing: Run Gitea inside rootless container environments like Podman with a read-only root filesystem (
--read-only), dropped capabilities (--cap-drop=ALL), andno-new-privilegesenabled. - Mandatory Access Control: Apply AppArmor or SELinux policies that explicitly prevent the Gitea daemon and child Git processes from invoking network utilities such as
curl,wget, or compilers.
Applying application patches neutralizes the diffpatch vulnerability, while disabling open registration and sandboxing system runtimes ensures future parser edge cases cannot compromise enterprise perimeter systems.