A AegiFlow
HIGHCVSS 7.1

CVE-2026-58437

Gitea: Repository Visibility Manipulation via Git Push Options

Published
2026-07-21
Modified
2026-07-21
Aliases
GHSA-8p9h-49rc-qgxj
Sources
github-advisory

Summary

### Repository Visibility Manipulation via Git Push Options | Field | Value | |-------|-------| | **Affected File** | `routers/private/hook_post_receive.go` | | **Affected Function** | `HookPostReceive()` | | **Affected Lines** | 173–225 | | **Prerequisite** | Attacker 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 re

Affected packages

EcosystemPackageAffected versionsFixed versions
Gocode.gitea.io/gitea1.27.0

Remediation: Upgrade to 1.27.0 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.

CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.