🛡️ CVE-2026-58510 — gitea.dev

⚪ Unknown ✅ No Known Exploit CWE-200 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Gitea: GHSA-8fwc-qjw5-rvgp ClearRepoWatches fix not applied to API EditRepo path — sister code path retains stale watches on public->private

Summary

GHSA-8fwc-qjw5-rvgp ("Gitea may send release notification emails for private repositories to users whose access has been revoked", fix in PR #36319 / commit 8a98ac22) added repo_model.ClearRepoWatches as a defense for the state transition public→private. The cleanup was wired into services/repository/repository.go::MakeRepoPrivate only. The sister helper services/repository/repository.go::updateRepository — which is the function used by the API path PATCH /api/v1/repos/{owner}/{repo} — was not patched and still calls ClearRepoStars only.

As a result, when a public repository is flipped to private via the REST API (rather than via the web Settings → Danger Zone UI), the watch records persist. Affected users can:

  • See the now-private repository in GET /api/v1/user/subscriptions?private=true along with its full Repository JSON (description, default branch, language, fork status, counts, mirror metadata, license list, etc.) — even though they have no access to the repository.
  • Have their stale watch records re-leak content through any future notification path that does not include the send-time CheckRepoUnitUser check that was added to services/mailer/mail_release.go.
  • Inflate the visible NumWatches counter on the repository.

Severity

Medium — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

Same impact class as the original GHSA-8fwc-qjw5-rvgp (which was classified Medium). The send-time mail filter added in the same PR mitigates the release-content disclosure vector. The residual leak is repo metadata via the subscriptions endpoint and stale watcher counts.

CWE-281 (Improper Preservation of Permissions), CWE-359 (Exposure of Private Personal Information), CWE-200 (Exposure of Sensitive Information).

Affected Versions

Every release starting from v1.25.4 (the release shipping the original GHSA-8fwc-qjw5-rvgp fix) through HEAD (master @ ef801bb6, 2026-05-16). The follow-up refactor in commit 943ff752 (PR #36959, 2026-03-24) which merged MakeRepoPublic+MakeRepoPrivate did not propagate the ClearRepoWatches call to updateRepository.

Affected Component

  • services/repository/repository.go:240-302func updateRepository(ctx, repo, visibilityChanged bool), the sister helper called via the API path. Clears stars on line 273 but never calls ClearRepoWatches.
  • routers/api/v1/repo/repo.go::Edit (line 573) → updateBasicProperties (line 678-697) → repo_service.UpdateRepository(ctx, repo, visibilityChanged) (line 726) — the API path that exercises the sister helper.

Steps to Reproduce

The bug is observable purely from static analysis; the live PoC is straightforward.

1. Start a Gitea instance at any release from v1.25.4 onwards (verified static at HEAD ef801bb6).

2. Create users A (org admin) and B (member). Create a public repository A/proj. As B, watch the repo:

```

curl -u B:<token> -X PUT "https://gitea.example.com/api/v1/repos/A/proj/subscription"

```

3. As A, flip the repo to private via the REST API (not via the web UI):

```

curl -u A:<token> -X PATCH "https://gitea.example.com/api/v1/repos/A/proj" \

-H 'Content-Type: application/json' \

-d '{"private": true}'

```

4. As B, list B's watched repos with private=true:

```

curl -u B:<token> "https://gitea.example.com/api/v1/user/subscriptions"

```

The now-private repo A/proj is returned in B's subscription list, with the full Repository payload — including description, default_branch, language, topics, license, fork/branch/issue/release counts, etc.

5. Compare with the web-UI path (which IS patched). As A, flip a different public repo A/proj2 to private via Settings → Danger Zone → "Make this repository private" (which calls repo_service.MakeRepoPrivate). Verify B's subscription list no longer contains A/proj2.

The asymmetry of outcomes between steps 4 and 5 — for the same state transition — is the gap.

Direct Evidence (no PoC needed)

```

$ gh api repos/go-gitea/gitea/contents/services/repository/repository.go \

--jq .content | base64 -d | grep -n "ClearRepoWatches\|ClearRepoStars"

154: if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil {

157: if err = repo_model.ClearRepoWatches(ctx, repo.ID); err != nil { # MakeRepoPrivate

273: if err = repo_model.ClearRepoStars(ctx, repo.ID); err != nil { # updateRepository — ClearRepoWatches missing here

```

The fix-author's own test file confirms the asymmetry:

```

$ gh api repos/go-gitea/gitea/contents/services/repository/repository_test.go --jq .content | base64 -d | grep -n "Test.*VisibilityChanged\|Test.*ClearsWatches"

44:func TestUpdateRepositoryVisibilityChanged(t *testing.T) { # only checks act.IsPrivate

73:func TestMakeRepoPrivateC

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality low, integrity none, availability none.

Weakness class

CVE-2026-58510 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.

Affected software

CVE-2026-58510 is recorded against 2 packages.

  • code.gitea.io/gitea
  • gitea.dev

Timeline and source

Published on 21 July 2026 and last revised on 27 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
CWE CWE-200
Public Exploit ✅ No
Source OSV
Published 2026-07-21
Updated 2026-08-12
Modified 2026-07-27
Fix URL N/A

Affected Packages

Software From version Fixed in
code.gitea.io/gitea
gitea.dev

Similar Threats

Free Vulnerability Check

Is your site affected by CVE-2026-58510?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-58510 and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.