CVE-2026-60004 — Gitea diffpatch API Code Injection (Unauthenticated-in-Practice RCE)
diffpatch API endpoint. A user with ordinary repository write access can plant an executable Git hook that runs arbitrary shell commands as the Gitea service account. Because Gitea ships with open self-registration by default, an unauthenticated visitor can obtain that write access simply by registering. CISA added it to KEV on 2026-08-25 after confirmed exploitation deploying a crypto-mining-like dropper. Defensive hunt & harden pack — no offensive/exploit code.Executive Summary
CVE-2026-60004 (CVSS 9.8, CWE-94 Improper Control of Generation of Code) is a critical code-injection vulnerability in Gitea, the open-source self-hosted Git service, affecting versions 1.17 through 1.27.0. A user with ordinary repository write access can submit a malicious patch to Gitea's diffpatch API endpoint (/api/v1/repos/{owner}/{repo}/.../diffpatch); Gitea's vulnerable temporary-clone handling lets Git's patch-processing materialize attacker-controlled content as an executable Git hook, which then runs arbitrary shell commands with the privileges of the Gitea OS/service account. Because Gitea ships with open self-registration enabled by default — no admin approval, no email confirmation, no CAPTCHA required — an unauthenticated visitor can obtain the write access needed for exploitation simply by registering an account and creating a repository. That collapses this from a nominally "authenticated" bug into a practically unauthenticated one on unmodified, internet-facing installs.
Gitea patched the flaw in version 1.27.1 (released 2026-07-27, security advisory published 2026-07-28), credited to Salesforce security researcher Shai Rod (NightRang3r). CISA added CVE-2026-60004 to its Known Exploited Vulnerabilities catalog on 2026-08-25 after confirmed real-world exploitation, ordering FCEB agencies to remediate by 2026-08-28 under BOD 26-04. A publicly documented incident shows the full kill chain: an automated scanner registered an account on a vulnerable, internet-facing Gitea instance, created a repository, triggered the exploit chain, wrote a "proof of RCE" marker into a Git branch, downloaded a universal shell-loader, then downloaded and ran an architecture-specific crypto-mining-like dropper that killed competing CPU-hungry processes before running. The active attack took roughly 11 seconds; in that specific incident the Docker container was unprivileged, the miner-like process did not survive a restart, and no persistence (cron/systemd/SSH keys) was found — but that favorable outcome depends on deployment isolation and is not guaranteed for every target.
No public C2 domains, IPs, or file hashes have been disclosed for the dropper — the incident's own investigator could not attribute it to a known cryptojacking family, describing it only as "miner-like." Shadowserver-tracked exposure sits near 5,000 internet-facing Gitea instances. This pack ships behavioral-detection-first: process lineage from the gitea/git service context, two-stage tool transfer, resource-hijacking command-line signatures, Git-hooks-directory writes, and anti-forensic self-deletion — backed by a patch/config audit rather than any fabricated atomic indicator.
gitea/git service context spawning a shell or interpreter — is the decisive endpoint tell (a planted hook executing). Pair with Q3 (shell-loader → miner-like dropper download) and Q4 (miner-style command-line flags) to catch the rest of the kill chain. The low-priv/effectively-pre-auth HTTP request to the diffpatch API itself is a network-only artifact (Coverage Map GAP) — patch to Gitea ≥1.27.1 (prefer 1.27.2) and disable open self-registration immediately; if you can't patch today, put the diffpatch API path behind additional authentication or a WAF control.Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry |
|---|---|---|---|
| 1 · Authoritative | CISA KEV Catalog Alert (2026-08-25) | Confirms CVE-2026-60004 added to KEV based on evidence of active exploitation; cites BOD 26-04; FCEB remediation due 2026-08-28; alert itself carries no attack-technical detail | yes |
| 2 · Journalism | The Hacker News (Ravie Lakshmanan, 2026-08-26) | CVSS 9.8; affected versions 1.17+; fix in 1.27.1; default open registration enables unauth-in-practice exploitation; references the documented dropper/miner incident | yes |
| 2 · Journalism | BleepingComputer (Sergiu Gatlan, 2026-08-26) | Names the diffpatch API endpoint mechanism verbatim from Gitea's security team; credits researcher Shai Rod; confirms 1.27.1 release date (2026-07-27); Shadowserver ~5,000 exposed instances; notes related CVE-2026-20896 | yes |
| 2 · Journalism | Help Net Security (Zeljka Zorz, 2026-08-26) | Most detailed public incident writeup: attack ran inside Docker as the git user, wrote a proof-of-RCE marker to a branch, downloaded a shell-loader then a miner-like dropper, ~11s active attack, no persistence found, unprivileged container so the miner didn't survive restart; lists potential secret-exposure impact (app.ini, DB creds, OAuth) | yes |
| 2 · Journalism | SecurityWeek (Eduard Kovacs, 2026-08-26) | Corroborates CISA's description quote, patch date, FCEB deadline; notes no prior public exploitation reports before the KEV addition and that attacker identity/motive remain unclear | yes |
| 3 · Technical blog | SOC Prime (2026-08-26) | Deepest technical mechanism explanation: CWE-94, bare-vs-non-bare temporary-clone / Git three-way-merge hook materialization, exact API route, dropper behavior detail (clears env vars, kills competing CPU processes, arch-specific payload, self-deletes), detection-guidance checklist | yes |
| 3 · Vendor blog | runZero (Matthew Kienow, updated 2026-08-25) | Confirms affected versions 1.17–1.27.0, CVSS 9.8; provides an asset-discovery query for impacted software inventory | partial |
Decisions: No atomic IOCs (hash/IP/domain) are published for the miner-like dropper — the documented incident's own investigator could not attribute it to a known cryptojacking family. §9 therefore ships behavioral signatures + a patch/config audit rather than fabricated indicator blocks (the CSV uses explicit REPLACE_WITH placeholders). The exact diffpatch API route and internal hook-materialization mechanism are drawn primarily from SOC Prime's technical writeup (Tier 3); CISA's KEV alert itself carries no technical detail and Gitea's own security-advisory page was not independently re-fetched in this research pass. The mechanism description is consistent across the six sources that discuss it — verify the exact API path and hook-injection detail against Gitea's own security advisory in your own review before relying on it for anything beyond detection engineering. No fetched source contained embedded instructions directed at this pipeline; all content was ordinary security journalism / vendor analysis and was treated strictly as data.
Hunt Brief & Attack Chain
Working hypothesis: A user (frequently an unauthenticated visitor who just self-registered on a default-configured instance) obtains repository write access, submits a crafted patch to the diffpatch API, and Git's patch-processing plants an executable hook inside Gitea's temporary-clone directory. The next repository operation triggers that hook, executing attacker shell commands as the Gitea OS/service account. From there the attacker stages a small "proof" artifact, retrieves a generic loader, then a target-specific crypto-mining-like payload, and cleans up after itself.
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 · Recon / access | Discover internet-facing, vulnerable (1.17–1.27.0) Gitea instance with open self-registration; register account, create repository | Gitea access/audit log, reverse-proxy log | N1 (GAP for EDR) |
| 2 · Exploit (inject) | Crafted patch submitted to the diffpatch API; Git's three-way-merge fallback materializes attacker content as an executable hook in the temp-clone dir | Network request body (WAF/IDS) — not on endpoint | N1 (GAP) |
| 3 · Command exec | Git triggers the planted hook; hook runs shell commands as the Gitea OS/service account (e.g. git user inside a container) | ProcessRollup2 / SyntheticProcessRollup2 | Q1 / Q2 |
| 4 · Proof / staging | Attacker writes a "proof of RCE" marker into a Git branch | Git repository/branch content — not EDR-visible | N4 |
| 5 · Tool transfer | Hook process downloads a generic "universal shell-loader" | ProcessRollup2, outbound connection | Q3 |
| 6 · Payload retrieval & run | Shell-loader fetches an architecture-specific crypto-mining-like dropper; dropper clears env vars, enumerates and tries to kill competing CPU-heavy processes, then runs | ProcessRollup2, NetworkConnectIP4 | Q3, Q4, N3 |
| 7 · Anti-forensics | Downloaded loader/payload files deleted after execution | ProcessRollup2 (rm/unlink) | Q6 |
| 8 · Impact | Sustained high CPU utilization (resource hijacking); no persistence observed in the documented incident, but a more sophisticated actor could add one | Host/cgroup/hypervisor CPU metrics; ProcessRollup2 | N3; Q5 (persistence, anticipatory) |
| 9 · Secondary risk | If the Gitea process/user has broader reach, exposure of app.ini secrets, DB credentials, OAuth/CI-CD tokens — supply-chain risk to downstream builds | Secrets-access audit, credential-use anomaly | GAP — containment/rotation (§12) |
Affected surface & telemetry
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| Gitea server hosts/containers (Linux, occasionally Windows) | Falcon Linux/Windows sensor on host, or container-aware sensor inside the workload | Critical | Medium-High — containerized Gitea (as in the documented incident) is common and often under-sensored without Falcon container/cloud workload coverage |
diffpatch API / HTTP request layer | Gitea access log, reverse-proxy, WAF | High | High — opaque to EDR; the exploit request body itself is not visible to a Falcon sensor |
| Git hooks directory & repository storage | File-write telemetry (NewExecutableWritten) | High | Medium — path varies per install; scope with REPLACE_WITH_GITEA_DATA_PATH in your tenant |
| Host/container CPU & resource metrics | Hypervisor / cloud-provider / cgroup monitoring | High | Medium — this is literally how the documented compromise was first noticed (a hoster's CPU alert), not EDR |
| Gitea admin/security configuration | Config management / CMDB / IaC | Medium | Low-Medium — confirm registration/CAPTCHA/email-confirm settings are tracked as code |
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| CVE | CVE-2026-60004 · Gitea Security Advisory (2026-07-28) | high | detect | Patch audit — Gitea diffpatch code injection |
| Endpoint | diffpatch API (/api/v1/repos/{owner}/{repo}/.../diffpatch) | medium | hunt | Vulnerable API surface; exact route per Tier-3 source, verify against Gitea advisory |
| Versions | Gitea 1.17 – 1.27.0 vulnerable; 1.27.1 fixed (prefer 1.27.2) | high | detect | Patch audit across all self-hosted instances |
| Behavior | gitea/git service context → shell/interpreter child | high | detect | Command injection / planted hook executing |
| Behavior | shell-loader → arch-specific miner-like dropper (2-stage fetch) | high | detect | Post-exploit ingress tool transfer |
| Behavior | miner-style CLI flags (stratum+tcp, --donate-level, -o pool, --algo) under service context | high | detect | Resource-hijacking signature |
| Config | app.ini [service] DISABLE_REGISTRATION / REGISTER_EMAIL_CONFIRM / ENABLE_CAPTCHA | medium | hunt | Exposure-reduction config audit |
| Payload hash / C2 | none published — capture in triage | low | pivot | Use §9 CSV placeholders per incident |
ATT&CK Mapping
| Tactic | Technique | Observed Behavior | Query / Control |
|---|---|---|---|
| Initial Access | T1190 — Exploit Public-Facing Application | Crafted patch to the diffpatch API plants an executable Git hook | N1; patch; WAF |
| Initial Access (supporting) | T1585.001 — Establish Accounts: Social Media / generic self-registration | Self-registration on a default-config instance to obtain repository write access | N1 |
| Execution | T1059.004 — Unix Shell | Planted Git hook executes shell commands as the Gitea OS/service account | Q1, Q2 |
| Command & Control | T1105 — Ingress Tool Transfer | Download of a "universal shell-loader," then an arch-specific miner-like dropper | Q3 |
| Discovery | T1057 / T1082 — Process Discovery / System Information Discovery | Dropper enumerates and tries to kill competing CPU-intensive processes; environment recon | Q4, N3 |
| Impact | T1496 — Resource Hijacking | Crypto-mining-like payload consumes sustained CPU | Q4, N3 |
| Defense Evasion | T1070.004 — Indicator Removal: File Deletion | Downloaded loader/payload files removed after execution | Q6 |
| Persistence (anticipatory) | T1053.003 / T1098.004 — Scheduled Task/Cron / SSH Authorized Keys | Not observed in the documented incident, but a hunt for cron/systemd/SSH-key persistence from the service context is prudent | Q5 |
| Defense Evasion / Persistence-adjacent | Git-hooks tamper (no dedicated ATT&CK ID) | Writes to the Git hooks directory outside expected deploy/admin activity | Q7, N5 |
| Credential Access / Collection (conditional) | T1552.001 — Unsecured Credentials: Credentials In Files | Potential exposure of app.ini secrets, DB credentials, OAuth/CI-CD tokens if reachable from the compromised process | GAP — rotate on suspicion (§12) |
Native Audit-Log Hunts
| Hunt | Source | Logic | Response |
|---|---|---|---|
| N1 · New-account → new-repo → diffpatch burst | Gitea access/audit log, reverse-proxy/WAF log | Account registration immediately followed by repository creation and one or more diffpatch API calls within minutes, especially from a source with no prior history | Investigate account + source IP; disable account; hunt the host (Q1-Q4) |
| N2 · Version / patch audit | Asset inventory / package manager / container image tags | Enumerate all Gitea instances; compare installed build to the 1.27.1 fixed release (prefer 1.27.2) | Schedule emergency patch; mitigate unpatched hosts (disable registration, restrict diffpatch) |
| N3 · Sustained high CPU on a Gitea host/container | Hoster / hypervisor / cgroup / host-monitoring CPU metrics | Unexplained, sustained CPU utilization on a Gitea server or its container — this is exactly how the documented real-world compromise was first noticed | Correlate with Q1-Q4 process activity; isolate; triage |
| N4 · Unexpected Git branches/commits | Git repository/branch review, Gitea admin UI or API | New branches or commits (e.g. a "proof of RCE" style marker) not tied to known contributors or expected CI activity, especially soon after a new account registers | Treat as compromise evidence; correlate with N1 and Q1/Q2 |
| N5 · Gitea security-config audit | Config management / CMDB / IaC / app.ini | Registration mode, email-confirmation requirement, and CAPTCHA settings compared to a hardened baseline (registration closed or admin-approved) | Remediate config drift; alert on unauthorized config changes |
CrowdStrike LogScale CQL Hunt Queries
ParentBaseFileName/FileName to avoid unescaped path separators. The pre-auth/low-priv HTTP request body is network-only — pair these with N1.Looks for: any shell/interpreter process whose direct parent is the gitea binary itself (not the git helper it normally shells out to). Accomplishes: the highest-fidelity signal — the main Gitea process spawning a shell directly is abnormal. FP: low — baseline first to learn any benign helper the main process legitimately forks, then exclude it.
// HUNT: CVE-2026-60004 Gitea binary spawns shell/interpreter (T1190 / T1059.004) // CONF: high FP: low COST: low | REQUIRES: Falcon sensor on the Gitea host/container #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^gitea(\.exe)?$/i | FileName=/^(sh|bash|dash|ksh|zsh|python[0-9.]*|perl|powershell|pwsh|cmd)(\.exe)?$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: a shell child of git (the normal hook-execution path) whose command line contains recon or download commands. Accomplishes: Git hooks legitimately run as shell children of git, so this narrows to injection-consistent content rather than flagging every hook. FP: medium — organizations with legitimate deploy/CI hooks will see hits; baseline and allow-list known hook script hashes or paths.
// HUNT: CVE-2026-60004 injected hook shell / recon (T1059.004) // CONF: high FP: medium COST: low // TUNING: allow-list known-good hook script hashes/paths (SHA256HashData) once baselined #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^git(\.exe)?$/i | FileName=/^(sh|bash|dash|ksh|zsh|python[0-9.]*|perl)(\.exe)?$/i | CommandLine=/\b(id|whoami|uname|hostname|cat|ls|env|curl|wget)\b/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: download-and-run / decode-and-run patterns parented by gitea, git, or the shell they spawned. Accomplishes: catches the documented "universal shell-loader → arch-specific dropper" ingress-tool-transfer stage. FP: low when scoped to the Gitea service context; verify any hit.
// HUNT: CVE-2026-60004 shell-loader / payload retrieval from service context (T1105) // CONF: high FP: low COST: low #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^(gitea|git|sh|bash|dash)(\.exe)?$/i | CommandLine=/(curl|wget|fetch).{0,80}(\bsh\b|bash|\|\s?sh)|chmod\s+\+?x|base64\s+-d|\/dev\/tcp\//i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: common cryptominer command-line flags/URLs (stratum protocol, donate-level, pool/algo flags, known miner binary names) spawned under the Gitea service context. Accomplishes: a resource-hijacking behavioral signature that doesn't depend on any specific hash. FP: medium — a stripped-down or renamed miner binary with no recognizable flags will evade this; pair with N3 (CPU monitoring) for coverage.
// HUNT: CVE-2026-60004 miner-like payload command-line signature (T1496) // CONF: high FP: medium COST: low // TUNING: exclude any confirmed legitimate CPU-benchmarking or build tooling that matches these flags #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^(gitea|git|sh|bash|dash)(\.exe)?$/i | CommandLine=/stratum\+tcp:\/\/|--donate-level|--cpu-priority|--algo(=|\s)|-o\s+\S+:\d+.{0,40}-u\s+\S+|\bxmrig\b|\bcpuminer\b|\bminerd\b|monero|cryptonight/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: cron/systemd edits, SSH authorized_keys writes, or back-connect shells run from the Gitea/git service context. Accomplishes: the documented incident found no persistence, but a more careful actor could establish one — this closes that gap. FP: medium — admins legitimately edit cron/keys; allow-list known admin accounts and change windows.
// HUNT: CVE-2026-60004 persistence / reverse shell from service context (T1053.003 / T1098.004) // CONF: medium FP: medium COST: low // TUNING: exclude known admin AIDs and scheduled change-window maintenance #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^(gitea|git|sh|bash|dash)(\.exe)?$/i | CommandLine=/(crontab\s+-|systemctl\s+(enable|daemon-reload)|authorized_keys|nc\s+-e|ncat\s+.{0,20}-e|bash\s+-i|\/dev\/tcp\/|mkfifo.{0,30}\|\s?(sh|bash))/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: a deletion command run from the Gitea/git service context targeting a temp-directory file, matching the documented behavior of removing the dropper after execution. Accomplishes: catches the cleanup stage even if Q3/Q4 miss the download itself. FP: medium — legitimate temp-file cleanup scripts can match; correlate with Q1-Q4 hits.
// HUNT: CVE-2026-60004 anti-forensic self-deletion (T1070.004) // CONF: medium FP: medium COST: low // TUNING: correlate with a Q1-Q4 hit in the same process tree/aid before alerting #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^(gitea|git|sh|bash|dash)(\.exe)?$/i | CommandLine=/\brm\s+-f\b|\bunlink\b|Remove-Item.{0,40}-Force/i | CommandLine=/\/tmp\/|\/var\/tmp\/|\btemp\b/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: a file write whose basename matches a standard Git hook name — this is where the injected code lands. Accomplishes: a file-write-side view of the exploit that complements the process-side Q1/Q2. FP: medium — legitimate admin-deployed hooks (CI/CD, mirroring) exist; allow-list known admin/deploy accounts and change windows.
// HUNT: CVE-2026-60004 Git hooks directory tamper (defense evasion / persistence-adjacent) // CONF: medium FP: medium COST: low | REQUIRES: NewExecutableWritten telemetry (fires when a file becomes executable, e.g. the hook's exec bit being set) // TUNING: exclude known admin/deploy AIDs and scheduled change windows; scope to REPLACE_WITH_GITEA_DATA_PATH if available #event_simpleName=/NewExecutableWritten/ | FileName=/^(pre-receive|post-receive|update|post-update|pre-commit|post-commit|pre-push|post-checkout|post-merge|applypatch-msg|pre-applypatch|post-applypatch|pre-rebase|pre-auto-gc)(\.exe)?$/i | table([@timestamp, aid, ComputerName, UserName, FileName, TargetFileName], limit=200) | sort(@timestamp, order=desc)
CrowdStrike Custom IOA Recommendations
| IOA Name | Field Patterns | Benign Exclusions | Deployment Path |
|---|---|---|---|
| Gitea — main binary spawns shell/interpreter | ParentBaseFileName gitea + child shell/interpreter FileName | Baseline-confirmed benign helper fork (if any), excluded by image/hash | Custom IOA → Process Creation, critical, Detect+Block |
| Gitea — service-context download+run | Parent gitea/git/shell + CmdLine curl|wget … sh / base64 -d | None expected | Custom IOA → Process Creation, high, Detect+Block |
| Gitea — miner-style command-line flags | CmdLine matches stratum/donate-level/algo/known miner names under service context | Approved CPU-benchmarking or build tooling (rare) | Custom IOA → Process Creation, high, Detect+Block |
| Gitea — hook directory tamper | NewExecutableWritten with FileName matching a standard hook name | Approved admin/deploy AIDs and change windows | Custom IOA → File Write, medium, Detect |
Machine-Readable IOC Appendix
Grouped IOC Quick-Copy
No public payload atoms exist for this CVE — the documented incident's dropper could not be attributed to a known family. The CSV uses explicit REPLACE_WITH placeholders for per-incident indicators. The durable layer is the behavioral signature and the patch/config audit.
type,value,action,severity,expiration,description,tags sha256,REPLACE_WITH_DROPPER_SHA256,prevent,critical,2026-12-27,CVE-2026-60004 miner-like dropper (per incident),cve:CVE-2026-60004 sha256,REPLACE_WITH_SHELLLOADER_SHA256,prevent,critical,2026-12-27,CVE-2026-60004 shell-loader (per incident),cve:CVE-2026-60004 ipv4,REPLACE_WITH_LOADER_OR_C2_IP,detect,high,2026-09-27,CVE-2026-60004 payload host / exploit source (per incident),cve:CVE-2026-60004 domain,REPLACE_WITH_PAYLOAD_DOMAIN,detect,medium,2026-09-27,CVE-2026-60004 payload host (per incident),cve:CVE-2026-60004
Inject: gitea binary spawns a shell/interpreter directly (should not happen normally) Exec: git spawns a shell whose cmdline runs recon (id/whoami/uname) or a download tool Retrieve: service-context curl|wget piped to sh ; chmod +x ; base64 -d ; /dev/tcp/ Resource: cmdline matches stratum+tcp:// / --donate-level / --algo / xmrig-style flags Persist: crontab - ; systemctl enable ; authorized_keys write ; back-connect shell (anticipatory) Cleanup: rm -f / unlink of a just-downloaded file in /tmp or /var/tmp Tamper: write to a standard git hook filename (pre-receive, post-receive, update, ...) Access: new-account -> new-repo -> diffpatch API burst within minutes (app-log only) Resource2: sustained unexplained CPU on the Gitea host/container (infra monitoring, not EDR)
CVE-2026-60004 # Code injection (CWE-94), CVSS 9.8, effectively pre-auth on default config
Advisory: Gitea Security Advisory, published 2026-07-28
Endpoint: diffpatch API (/api/v1/repos/{owner}/{repo}/.../diffpatch)
Mechanism: crafted patch -> Git 3-way-merge fallback materializes an executable hook in the
temp-clone dir -> hook runs as the Gitea OS/service account on next Git operation
Versions: 1.17 through 1.27.0 vulnerable
Fixed: 1.27.1 (released 2026-07-27) ; 1.27.2 is the current recommended build
Reporter: Shai Rod (NightRang3r), Salesforce
KEV: added by CISA 2026-08-25 ; FCEB remediation due 2026-08-28 (BOD 26-04)
# 1) Upgrade Gitea to >=1.27.1 (prefer 1.27.2) -- adjust to your install method
# Binary/systemd:
sudo systemctl stop gitea
# ... replace the gitea binary with the REPLACE_WITH_1.27.2_RELEASE build ...
sudo systemctl start gitea
# Docker:
docker pull REPLACE_WITH_YOUR_REGISTRY/gitea:1.27.2
docker compose up -d # or your equivalent redeploy command
# 2) Disable open self-registration (app.ini, [service] section)
# DISABLE_REGISTRATION = true
# -- if registration must stay open, at minimum:
# REGISTER_EMAIL_CONFIRM = true
# ENABLE_CAPTCHA = true
sudo systemctl restart gitea
# 3) If you cannot patch immediately, put the diffpatch API path behind
# additional auth/WAF control at your reverse proxy, e.g. (nginx sketch):
# location ~ ^/api/v1/repos/.*/diffpatch { deny all; } # confirm exact route in your build
# 4) Confirm the running version post-upgrade
REPLACE_WITH_GITEA_BINARY_PATH --version
Hardening — Tiered & Deployable
This is a pre-auth-in-practice RCE on a self-hosted DevOps hub — patching and cutting off open self-registration are the decisive moves; everything else limits blast radius and catches what patching alone won't.
- Upgrade every Gitea instance to ≥1.27.1 (prefer 1.27.2) — M1051. This is the only complete fix; treat as an emergency change given confirmed KEV exploitation.
- Disable open self-registration, or at minimum require email confirmation + CAPTCHA — M1042. Removes the practical "unauthenticated" path to repository write access. See §9 mitigation commands.
- If you can't patch right now, put the diffpatch API path behind additional auth/WAF control — M1037. Reduces exposure until the patch window opens.
- Ensure a Falcon sensor is installed & reporting on every Gitea host/container — M1040. Q1/Q2 only work if the workload is sensored, and containerized deployments (as in the documented incident) are the common blind spot.
- Harden the Gitea container/host runtime: drop capabilities, non-root, restrict egress — M1030 / M1048. Limits what a successful injection can reach and blocks the shell-loader/miner fetch (Q3).
- Deploy Q1/Q3/Q4 as Custom IOAs (Detect+Block) on a Gitea host group; forward Gitea access logs + host CPU metrics to your SIEM/monitoring — M1040 / M1047. Feeds N1/N3.
- Least-privilege the Gitea service account; file-integrity-monitor the Git hooks directory — M1026 / M1022. Limits injected-command blast radius and catches Q7 tamper.
- Rotate Gitea-held secrets (app secret key, DB credentials, OAuth/CI-CD tokens) if any exposure window is suspected — M1027. A compromised Gitea host is a source-control and supply-chain event.
- Network-segment dev infrastructure (Gitea, CI/CD) away from the open internet; require VPN/SSO for access — M1030. Shrinks the ~5,000-instance internet-facing exposure this pack's sources describe.
- Formal patch-SLA + vendor-advisory monitoring for self-hosted DevOps tooling — M1051 / M1047. Gitea's own July→August timeline shows disclosure-to-exploitation windows can be under a month.
- Audit CI/CD credential scope reachable from Gitea; adopt short-lived tokens over long-lived secrets — M1027. Limits supply-chain impact if a Gitea host is compromised again in the future.
Deployable Playbooks
Playbook A — Emergency patch & registration lockdown (binary/systemd deployment)
For Gitea installed as a native binary/systemd service. Adjust paths to your install.
Step 1: Confirm current version
Command: REPLACE_WITH_GITEA_BINARY_PATH --version
Prerequisites: SSH/console access to the Gitea host
Reboot required: No
Rollback: none required (read-only check)
Step 2: Back up app.ini and the Gitea data directory
Command: tar czf gitea-backup-REPLACE_WITH_DATE.tar.gz REPLACE_WITH_GITEA_DATA_PATH REPLACE_WITH_APP_INI_PATH
Prerequisites: Sufficient disk space for the archive; maintenance window scheduled
Reboot required: No
Rollback: N/A (this step creates the rollback artifact for later steps)
Step 3: Upgrade the Gitea binary to >=1.27.1 (prefer 1.27.2)
Command: sudo systemctl stop gitea
# replace binary with the 1.27.2 release from your trusted distribution channel
sudo systemctl start gitea
Prerequisites: Backup from Step 2 completed; maintenance window
Reboot required: Service restart only, not a host reboot
Rollback: systemctl stop gitea ; restore prior binary + data dir from the Step 2 backup ; systemctl start gitea
Step 4: Lock down self-registration in app.ini [service]
Command: DISABLE_REGISTRATION = true
# or, if registration must stay open:
REGISTER_EMAIL_CONFIRM = true
ENABLE_CAPTCHA = true
sudo systemctl restart gitea
Prerequisites: Admin edit access to app.ini; Step 2 backup taken
Reboot required: Service restart only
Rollback: Restore app.ini from the Step 2 backup ; systemctl restart gitea
Playbook B — Container hardening (Docker/Kubernetes deployment)
Matches the documented incident's deployment shape (Gitea in Docker). Test in staging first — Gitea needs writable volumes for its data/repo directories, so a fully read-only filesystem will break it unless those paths are mounted as writable volumes.
Step 1: Pull the patched image
Command: docker pull REPLACE_WITH_YOUR_REGISTRY/gitea:1.27.2
Prerequisites: Registry access; staging environment available for validation
Reboot required: No
Rollback: Keep the prior image tag available locally; no action needed if not yet deployed
Step 2: Redeploy with hardened runtime flags
Command: docker run --cap-drop=ALL --security-opt=no-new-privileges:true \
-v REPLACE_WITH_GITEA_DATA_VOLUME:/data \
REPLACE_WITH_YOUR_REGISTRY/gitea:1.27.2
Prerequisites: Validated in staging; data/repo paths mounted as writable volumes (not read-only)
Reboot required: Container recreate -- brief service interruption
Rollback: Redeploy the previous container definition / compose file
Step 3: Restrict container egress to only required destinations
Command: REPLACE_WITH_YOUR_NETWORK_POLICY_TOOL (e.g. Docker network + firewall rules,
Kubernetes NetworkPolicy) -- default-deny egress, allow only package-mirror
destinations needed for updates
Prerequisites: Allow-list of required destinations defined
Reboot required: No (network policy applies live)
Rollback: Remove or revert the network policy
Step 4: Deploy Q1/Q3/Q4 as Custom IOAs Detect+Block on the Gitea host group
Command: Falcon console -> Custom IOA rule groups -> scope to Gitea host group
Prerequisites: Falcon admin console access; queries validated in your tenant (§7)
Reboot required: No
Rollback: Disable or delete the Custom IOA rule
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-contain any Gitea host with a Q1/Q3/Q4 hit; if containerized, pause/stop (don't delete) the container to preserve evidence; block egress from the host/container; freeze the affected Gitea admin/service account | SOC L2 | Containment timestamps; Q1-Q4 process tree |
| Triage | Reconstruct the gitea/git child-process tree; identify the shell-loader and dropper (Q3/Q4); check for a "proof of RCE" branch/commit marker (N4); determine whether persistence exists (Q5) despite the documented incident showing none; assess whether the container was privileged (escape risk) | IR | Process timeline; recovered payload + hash if available |
| Eradicate | Remove the miner-like payload, shell-loader, and any planted Git hooks (Q7); restore hooks directory and app.ini from known-good; rebuild the container from a clean patched image if compromise scope is uncertain; confirm upgrade to ≥1.27.1 (prefer 1.27.2) | IR | Removed-artifact log; patch confirmation |
| Recover | Rotate every secret Gitea holds (app secret key, DB credentials, OAuth/integration tokens, CI/CD credentials reachable from the host); review repositories/branches for unauthorized commits; verify integrity before reconnecting | IR + DevOps/IAM | Credential-rotation log; repository integrity review |
| Harden | Confirm patch and registration lockdown; deploy Q1/Q3/Q4 IOAs Detect+Block; forward Gitea access logs + host CPU metrics; apply container hardening flags (§11 Playbook B) | Detection Eng | Patch + IOA + logging status |
Detection Coverage Map & Validation
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1190 (request body) | Crafted diffpatch API request | — | — | GAP network-only — access log/WAF + patch (N1) |
| T1585.001 (account creation) | Self-registration abuse | — | — | GAP app-log only — N1 |
| T1059.004 | Planted hook executes shell as service account | Q1, Q2 | IOA-1 | Good decisive; needs sensor + hook baseline for Q2 |
| T1105 | Shell-loader → dropper retrieval | Q3 | IOA-2 | Good |
| T1057 / T1082 | Dropper recon / competing-process kill | Q2 (partial) | — | Partial covered indirectly via Q2 recon patterns |
| T1496 | Resource hijacking / miner-like CPU abuse | Q4 | IOA-3 | Partial cmdline signature evadable by a flag-stripped binary; pair with N3 |
| T1070.004 | Anti-forensic self-deletion | Q6 | — | Partial correlate with Q1-Q4 hit |
| T1053.003 / T1098.004 | Persistence (anticipatory) | Q5 | — | Partial tune admin allow-list; not observed in the documented incident |
| Hook-directory tamper | Writes to Git hooks directory | Q7 | IOA-4 | Partial tune admin/deploy allow-list |
| T1552.001 | Secret exposure (app.ini/DB/OAuth) | — | — | GAP not proactively detectable — rotate on suspicion (§12) |
Validation gates: (1) confirm a Falcon sensor is installed and reporting on every Gitea host/container and that ProcessRollup2 carries ParentBaseFileName plus full command line; (2) baseline any benign child gitea/git legitimately forks (deploy hooks, CI integrations) and exclude by hash/path so Q1/Q2/Q7 stay clean; (3) populate admin/change-window allow-lists (Q5/Q6/Q7) before promoting to alerting; (4) lab-test Q4 against a known-benign CPU-heavy process (e.g. a legitimate build job) to confirm the miner-flag regex doesn't over-fire; (5) confirm host/container CPU metrics are actually reaching your monitoring stack for N3 — this was the only signal that caught the documented real-world incident; (6) promote Q1/Q3/Q4 to Custom IOA Detect+Block on the Gitea host group once tuned. The CVE/version/mechanism facts are source-cited and safe to use as-is; there is no payload hash to deploy.
Hunt Summary Ticket
TITLE: Hunt — CVE-2026-60004 Gitea diffpatch API code injection (KEV)
SEVERITY: Critical (CVSS 9.8; effectively pre-auth RCE on default-config Gitea)
SCOPE: All self-hosted Gitea instances (versions 1.17-1.27.0); Linux/container hosts
HYPOTHESIS: Self-registration or repo write access -> crafted diffpatch API request plants
a Git hook -> hook runs shell as Gitea service account -> shell-loader ->
miner-like dropper -> sustained CPU abuse -> self-deletion, no persistence observed.
QUERIES RUN: Q1 gitea->shell (IOA) | Q2 git-hook shell/recon* | Q3 shell-loader/payload (IOA) |
Q4 miner cmdline signature (IOA) | Q5 persistence (anticipatory)* |
Q6 self-deletion* | Q7 hook-directory write (IOA)*
(* = requires env tuning: hook hash/path baseline or admin/change-window allow-list)
DO FIRST: Q1, Q3, Q4 -- escalate any hit; treat as source-control + supply-chain compromise
FINDINGS: <pending analyst execution>
GAPS: diffpatch request body (network-only; WAF/access-log N1); self-registration abuse
pattern (app-log only N1); secret exposure (not proactively detectable, §12)
ACTIONS: Patch to Gitea >=1.27.1 (prefer 1.27.2); disable open self-registration;
deploy Q1/Q3/Q4 IOAs Detect+Block; rotate Gitea-held secrets on suspicion
OWNER: HuntPack
VERSION: v0.1 - 2026-08-27
Changelog
References
| Tier | Source | Used For |
|---|---|---|
| 1 | CISA — Adds One Known Exploited Vulnerability to Catalog (2026-08-25) | Authoritative KEV addition, CVE ID, BOD 26-04 remediation deadline |
| 2 | The Hacker News — Critical Gitea RCE Actively Exploited | CVSS, affected/fixed versions, default-registration exploitation path |
| 2 | BleepingComputer — Hackers now exploit critical Gitea flaw | diffpatch mechanism quote, researcher credit, exposure count, related CVE |
| 2 | Help Net Security — Critical Gitea Vulnerability Now Exploited in the Wild | Full documented-incident narrative, container/persistence findings, potential secret exposure |
| 2 | SecurityWeek — CISA Warns of Exploited Gitea Vulnerability | CISA description corroboration, patch/deadline dates, attribution uncertainty |
| 3 | SOC Prime — CVE-2026-60004 Critical Gitea RCE | Technical mechanism detail, API route, dropper behavior, detection-guidance checklist |
| 3 | runZero — Gitea Vulnerability CVE-2026-60004 | Affected-version confirmation, asset-discovery context |
HuntPack v0.1 · CVE-2026-60004 (Gitea diffpatch API code injection) · Generated 2026-08-27 · Defensive use only — no offensive code or exploit. No public payload atoms exist; the behavioral detections plus the patch/config audit are the durable signal. Verify the exact diffpatch API route and hook-injection mechanism against Gitea's own security advisory, and validate field names + tune hook-hash/admin allow-lists in your tenant before promoting any query to alerting.