Three times in the past year this site has pointed community operators at Gitea Actions as the CI layer that keeps source control under your own roof — the piece that completes a sovereign stack alongside Keycloak and Matrix. In June, Gitea 1.26.3 shipped a large batch of security fixes, among them a breaking change hardening the fork pull-request approval gate. We didn't cover it that week, and the reason we didn't is the reason this post exists: at the time, it looked like hardening that held.
It didn't hold. Two months and two patch releases later, the gate has been bypassed three separate ways, an attacker has already used it to drop a miner-like payload on an open-registration server, and CISA added the underlying RCE to its Known Exploited Vulnerabilities catalog on August 25 with a federal remediation deadline of August 28. Gitea 1.27.3, shipped August 29, closes 26 CVEs in one release.
If you self-host Gitea — and if you follow this site, the odds are good that you do — here is the state of the patch surface, and the operational habit that contains it.
The RCE you should have patched in July is being exploited now¶
CVE-2026-60004 (CVSS 9.8) is the headline. The bug is in Gitea's diffpatch API, which applies user-supplied patches inside a temporary Git repository. Vulnerable releases cloned that temp repo bare — and in a bare clone, the repo directory is the internal data directory. With Git's three-way patch processing, attacker-controlled repository content could materialize as an executable post-index-change hook, which Git then runs. That is code execution as the Gitea service account, from ordinary repository write access.
The July 27 patch (1.27.1) fixed it by switching the temp clone from bare to non-bare — a one-line architectural fix that removes the hooks directory from the attacker's reach entirely. Note the date: July 27. KEV listing: August 25. Public PoC since disclosure. That is four weeks from "fixed" to "actively exploited," on the fastest end of the lag between disclosure and weaponization, and inside the window where the typical "we'll patch at the next maintenance window" operator is still exposed.
Two details in the exploitation path matter for community operators:
Open registration turns a low-bar bug into a no-bar bug. Exploitation requires write access to some repository. Gitea's default install enables open registration without approval or email verification, and new users can create repositories. An internet-facing instance with default settings hands an external attacker the prerequisite — an account — on demand. The one publicly documented attack went exactly this way: attacker reached the server over HTTPS, created the conditions for the bug, and executed a dropper that cleared env, killed CPU competitors, downloaded an arch-specific payload, ran it, deleted it.
The blast radius is everything the Gitea account can see. Private repositories. Database credentials. OAuth secrets. CI/CD credentials. Package registries. And if your runners sit on the same trust boundary as the forge — the pattern this site recommends for small deployments — the compromise propagates to whatever those runners can deploy. A forge compromise is a supply-chain event for everything built from it.
The fork gate broke again¶
The June 20 hardening (1.26.3) added a breaking change: a pull request from a fork must be merged before its workflows can bypass the approval gate. The August releases show the gate's enforcement was incomplete in ways only adversarial review finds:
- CVE-2026-66877 — the "approve workflow runs from first-time fork contributors" gate was enforced only by inserting a run's jobs as blocked; the job emitter never re-checked
run.NeedApproval. An unrelated run sharing a job-levelconcurrencygroup could force an emitter pass that unblocked and dispatched approval-pending fork PR jobs to your runners with no approval. Unauthenticated code execution on self-hosted runners, for anyone who can open a PR. - CVE-2026-71184 — the maintainer-approval gate was skipped for the
pull_request_review_commentevent (and review approved/rejected) because the notifier never called.WithPullRequest(pr), and a nil PR is not treated as a fork PR. Fork workflow YAML ran on the base repo without approval. - CVE-2026-66874 — a fork author could name a filtered-out workflow to match a required status check context and give it a never-matching filter, marking the required check as satisfied without any workflow running. Required checks you use as merge gates could be marked green without anything running.
And two more in the same batch are missed siblings of earlier fixes — the pattern the site flagged on the Keycloak 26.7.3 release:
- CVE-2026-70406 —
parseCompareInfolacked theTokenCanAccessRepo(headRepo)guard thatUpdatePullRequestreceived in an earlier advisory; apublic-onlytoken read private head-repo history through a public base repo's compare endpoint. - CVE-2026-63792 —
CanReadWorkflowCrossRepogranted cross-repo read of reusable workflow files via the "collaborative owner" trust relationship without checking fork-PR status — a missed sibling of a fix that only touchedGetActionsUserRepoPermission.
Plus a batch of visibility/scope leaks: issue search, SSH/GPG keys, activity feeds, packages, org labels, attachments, repository search, token scopes on org creation, migrate, and workflow badges. And CVE-2026-70402: git hook directories created with mode 0777 before umask — local code execution as the Gitea service account for anyone with local access. This is a patch batch, not a patch release.
What to do¶
-
Be on 1.27.3. If you're on 1.26.x, you are exposed to CVE-2026-60004 — CISA KEV, public PoC, active exploitation, miner-like payload documented on an open-registration server. Internet-facing instances with open registration: treat this as the same urgency class as the Keycloak 26.7.2 password-reset takeover in September's identity patch. If you have any doubt about your version, check it. If you can't upgrade immediately, close the exploit prerequisites: disable open registration, restrict repository creation, put the forge behind authentication, and watch for unexplained CPU or outbound traffic from the Gitea service account.
-
Review workflow approval settings after the upgrade. The June hardening was a breaking change: a fork PR must now be merged before it can bypass the approval gate. If your community's CI relies on fork PRs triggering CI without maintainer intervention, that behavior changed under you in June and was re-tightened August 14 and 29. Re-read the 1.26.3 breaking-change note and the 1.27.2/1.27.3 advisories, then walk your approval-gate settings. The default is safer than what you configured in 2025.
-
Sweep for malicious hooks. If you run any version from 1.17 through 1.27.0, and the server was internet-facing with open registration, you have exposure since July 27 at minimum. Check for unexpected executable files under the repos'
hooks/directories (look forpost-index-change), unusual processes under the Gitea service account, and account creation you didn't approve. Rotate secrets reachable by the Gitea account: DB creds, OAuth secrets, runner registration tokens, deploy keys. -
Assume the batch. Gitea 1.27.0 (July 12) → 1.27.1 (July 27, 2 CVEs) → 1.27.2 (Aug 14, 8 CVEs) → 1.27.3 (Aug 29, 26 CVEs). A point release accumulating 36 CVEs in six weeks is not an anomaly to react to; it's a cadence to schedule around. Put Gitea on the same patch discipline as Keycloak: security releases get applied on a schedule, not when a headline makes you.
The habit, again¶
This is the third time this site has covered a batch-release pattern — Keycloak in August, now Gitea in August. Same lesson, different layer. The June 1.26.3 release hardened the fork-PR approval gate; two months later that same gate needed two more rounds of fixes. "Fixing fixes" and "missed siblings" are not signs of a broken project. They're signs that the security boundary is complex enough that it takes adversarial review to find the remaining holes — and that the maintainers keep fixing them.
The pattern — self-host the forge, keep CI under your own roof, keep CI runners scoped — remains the right architecture for community infrastructure. But it has the same operational amendment the Keycloak posts carry: every layer you self-host is a standalone patch surface. The forge is not the IdP, the IdP is not the chat server, and none of them patch themselves.
Federation distributes authority. It does not distribute patch work. Plan for both.