CVE-2026-25232: Gogs has a Protected Branch Deletion Bypass in Web Interface

Published Feb 17, 2026
·
Updated

Summary

An access control bypass vulnerability in Gogs web interface allows any repository collaborator with Write permissions to delete protected branches (including the default branch) by sending a direct POST request, completely bypassing the branch protection mechanism. This vulnerability enables privilege escalation from Write to Admin level, allowing low-privilege users to perform dangerous operations that should be restricted to administrators only.

Although Git Hook layer correctly prevents protected branch deletion via SSH push, the web interface deletion operation does not trigger Git Hooks, resulting in complete bypass of protection mechanisms.

Details

Affected Component

- File: internal/route/repo/branch.go - Function: DeleteBranchPost (lines 110-155) - Route Configuration: internal/cmd/web.go:589 go m.Post("/delete/", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)

Root Cause

The DeleteBranchPost function performs the following checks when deleting a branch: 1. ✅ User authentication (reqSignIn) 2. ✅ Write permission check (reqRepoWriter) 3. ✅ Branch existence verification 4. ✅ CommitID matching (optional parameter) 5. ❌ Missing protected branch check 6. ❌ Missing default branch check

While the UI layer (internal/route/repo/issue.go:646-658) correctly checks protected branch status and hides the delete button, attackers can directly construct POST requests to bypass UI restrictions.

Vulnerable Code

Vulnerable implementation (internal/route/repo/branch.go:110-155):

110:155:internal/route/repo/branch.go func DeleteBranchPost(c context.Context) { branchName := c.Params("") commitID := c.Query("commit")

defer func() { redirectTo := c.Query("redirectto") if !tool.IsSameSiteURLPath(redirectTo) { redirectTo = c.Repo.RepoLink } c.Redirect(redirectTo) }()

if !c.Repo.GitRepo.HasBranch(branchName) { return } if len(commitID) > 0 { branchCommitID, err := c.Repo.GitRepo.BranchCommitID(branchName) if err != nil { log.Error("Failed to get commit ID of branch %q: %v", branchName, err) return }

if branchCommitID != commitID { c.Flash.Error(c.Tr("repo.pulls.deletebranchhasnewcommits")) return } }

// 🔴 Vulnerability: Missing protected branch check here // Should add check like: // protectBranch, err := database.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branchName) // if protectBranch != nil && protectBranch.Protected { ... }

if err := c.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{ Force: true, }); err != nil { log.Error("Failed to delete branch %q: %v", branchName, err) return }

if err := database.PrepareWebhooks(c.Repo.Repository, database.HookEventTypeDelete, &api.DeletePayload{ Ref: branchName, RefType: "branch", PusherType: api.PUSHERTYPEUSER, Repo: c.Repo.Repository.APIFormatLegacy(nil), Sender: c.User.APIFormat(), }); err != nil { log.Error("Failed to prepare webhooks for %q: %v", database.HookEventTypeDelete, err) return } }

Correct implementation in Git Hook (internal/cmd/hook.go:122-125):

go // check and deletion if newCommitID == git.EmptyID { fail(fmt.Sprintf("Branch '%s' is protected from deletion", branchName), "") }

Correct UI layer check (internal/route/repo/issue.go:646-658):

go protectBranch, err := database.GetProtectBranchOfRepoByName(pull.BaseRepoID, pull.HeadBranch) if err != nil { if !database.IsErrBranchNotExist(err) { c.Error(err, "get protect branch of repository by name") return } } else { branchProtected = protectBranch.Protected }

c.Data["IsPullBranchDeletable"] = pull.BaseRepoID == pull.HeadRepoID && c.Repo.IsWriter() && c.Repo.GitRepo.HasBranch(pull.HeadBranch) && !branchProtected // UI layer has check, but backend doesn't PoC

Prerequisites

1. Have Write permissions to the target repository (collaborator or team member) 2. Target repository has protected branches configured (e.g., main, master, develop) 3. Access to Gogs web interface

Send Malicious POST Request bash Directly send DELETE request bypassing UI protection curl -X POST \ -b cookies.txt \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "csrf=YOURCSRFTOKEN" \ "https://gogs.example.com/username/repo/branches/delete/main" <img width="1218" height="518" alt="image" src="https://github.com/user-attachments/assets/745da7c3-6139-408c-9747-ccbe9ea8548f" />

Impact - Bypass branch protection mechanism: The core function of protected branches is to prevent deletion, and this vulnerability completely undermines this mechanism - Delete default branch: Can cause repository to become inaccessible (git clone/pull failures) - Bypass code review: After deleting protected branch, can push new branch bypassing Pull Request requirements - Privilege escalation: Writer permission users can perform operations that should only be allowed for Admins

Other sources

Gogs is an open source self-hosted Git service. Versions 0.13.4 and below have an access control bypass vulnerability which allows any repository collaborator with Write permissions to delete protected branches (including the default branch) by sending a direct POST request, completely bypassing the branch protection mechanism. This vulnerability in the DeleteBranchPost function eenables privilege escalation from Write to Admin level, allowing low-privilege users to perform dangerous operations that should be restricted to administrators only. Although Git Hook layer correctly prevents protected branch deletion via SSH push, the web interface deletion operation does not trigger Git Hooks, resulting in complete bypass of protection mechanisms. In oder to exploit this vulnerability, attackers must have write permissions to the target repository, protected branches configured to the target repository and access to the Gogs web interface. This issue has been fixed in version 0.14.1.

MITRE

Affected Software

2 affected componentsFixes available
go/gogs.io/gogs<0.14.1
0.14.1
Gogs Gogs<0.14.1

Event History

Feb 17, 2026
Advisory Published
via GitHub·06:43 PM
Data Sourced
via GitHub·06:43 PM
DescriptionWeaknessAffected Software
Feb 19, 2026
CVE Published
via MITRE·02:25 AM
Data Sourced
via MITRE·02:25 AM
DescriptionWeakness
Data Sourced
via NVD·07:17 AM
RemedyDescriptionSeverityWeaknessAffected Software
Aug 19, 58109
Event
via FIRST·04:47 PM
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-25232?

CVE-2026-25232 is considered a high severity vulnerability due to its potential to allow unauthorized deletion of protected branches.

2

How do I fix CVE-2026-25232?

To fix CVE-2026-25232, update to Gogs version 0.14.1 or later where the vulnerability has been patched.

3

What type of vulnerability is CVE-2026-25232?

CVE-2026-25232 is classified as an access control bypass vulnerability.

4

Who is affected by CVE-2026-25232?

Any repository collaborator with Write permissions in Gogs can be affected by CVE-2026-25232.

5

What impact does CVE-2026-25232 have on Gogs users?

The impact of CVE-2026-25232 allows malicious users to delete protected branches, including default branches, compromising project integrity.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203