CVE-2026-58437

highpriority · track · 0EPSS 0.003 · 27 %ileDEEURUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.34% (27th) EPSS
CVSS 7.1 · high
Is it mine?
10 products
Check your exposure
Who says so?
4 sources
enisa_euvd · fstec_bdu · osv · cert_bund

EPSS · scored 2026-10-27

Repository Visibility Manipulation via Git Push Options

01

cvss

Technical severity, 0–10. One row per scoring source.

7.1
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.5–7.1

v3.17.1highAV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:Nsecondary · FSTEC (BDU) RU
v3.17.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:Nsecondary · ENISA EU
v3.17.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:Nsecondaryexploitability 2.8 · impact 4.2
v3.17.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:Nsecondary · OSV
v3.16.5mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N/E:Usecondary · CVSS-BT (t0sche)
02

weaknesses

The CWE weakness classes this flaw belongs to.

03

affected products (10)

Products and version ranges known to be affected.

04

advisories (3)

Vendor and ecosystem advisories describing this.

  • WID-SEC-W-2026-2304Gitea: Mehrere SchwachstellenDeutsch2026-07-13csaf · cert_bundDE

    Ein Angreifer kann mehrere Schwachstellen in Gitea ausnutzen, um beliebigen Programmcode auszuführen, erweiterte Berechtigungen zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, sensible Informationen offenzulegen, Sitzungen zu übernehmen oder wiederzuverwenden oder einen Denial-of-Service-Zustand auszulösen.

  • GHSA-8p9h-49rc-qgxjGitea: Repository Visibility Manipulation via Git Push Options2026-07-21ghsa · osvUS

    ### 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 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 | Impact | Description | |--------|-------------| | **Data exfiltration** | Private source code, CI/CD secrets in plain-text files, environment configs become publicly cloneable for the window the repo is public | | **No audit trail** | `UpdateRepositoryColsNoAutoTime` suppresses the `updated_at` change; no activity log entry; no webhook; no notification | | **Supply chain** | Combined with `repo.template=true/false`, an attacker can silently rotate repository template status, affecting all downstream repositories that generate from this template | | **Scope** | Affects 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.

  • GO-2026-6047Gitea: Repository Visibility Manipulation via Git Push Options in gitea.dev2026-07-22vendor · osvUS

    Gitea: Repository Visibility Manipulation via Git Push Options in gitea.dev

05

also known as (6)

Other names and identifiers for this entity.

06

sources

Which sources assert this record, and when.

published 2026-08-13modified 2026-10-02
07

references (6)

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan