{"id":"CVE-2026-26231","aliases":["GHSA-mm7c-rhg6-qr4r","GO-2026-5510"],"url":"https://o3.security/vulnerability/CVE-2026-26231","summary":"Gitea maintainer-edit permissions allow unauthorized commits to readable repositories","details":"## Summary\n\nAny authenticated low-privilege user with read access to a repository can push arbitrary commits directly to that repository, bypassing all write-access checks.\n\n## Vulnerability\n\nGitea's \"Allow edits from maintainers\" PR option can be abused via reverse-fork PRs:\n\n1. The web UI PR-create endpoint binds `allow_maintainer_edit=true` **without** verifying that the submitter has write access to the HEAD repository.\n2. Gitea allows creating a PR where **BASE = attacker's fork** and **HEAD = upstream target**. The attacker is \"maintainer\" of the BASE (their own fork), so the flag is set against the upstream HEAD.\n3. On `git push` over HTTP/SSH, Gitea relaxes the required access mode to `Read` when `SupportProcReceive` is enabled ([`routers/web/repo/githttp.go`](https://github.com/go-gitea/gitea/blob/v1.25.5/routers/web/repo/githttp.go#L189), [`routers/private/serv.go`](https://github.com/go-gitea/gitea/blob/v1.25.5/routers/private/serv.go#L337)) and defers enforcement to the pre-receive hook.\n4. The pre-receive hook calls [`CanMaintainerWriteToBranch`](https://github.com/go-gitea/gitea/blob/v1.25.5/models/issues/pull_list.go#L72) (`models/issues/pull_list.go`), which finds the malicious PR, sees `AllowMaintainerEdit=true`, and checks whether the pusher has write access to the **BASE** repo. Since BASE is the attacker's own fork, the check passes and the push is authorized against the upstream.\n\n## Exploitation\n\n1. Attacker forks the target repository.\n2. Attacker visits the web compare endpoint and creates a PR with `BASE = their_fork`, `HEAD = upstream`, and \"Allow edits from maintainers\" checked.\n3. Attacker clones their fork, makes a commit, and runs `git push <upstream_url> <branch>` — the push is accepted.\n\n## Reproduction\n\n```bash\npython3 poc.py --repo http://gitea:3000/victim/repo --user attacker --password attacker_pass\n```\n[poc.py](https://github.com/user-attachments/files/26641541/poc.py)\n\nExpected output:\n```\n[+] target: victim/my_repo  default branch: main\n[*] forking -> attacker/my_repo_pocfork (202)\n[+] fork ready\n[+] malicious PR created (BASE=attacker fork, HEAD=upstream)\n\nremote: . Processing 1 references\nremote: Processed 1 references in total\nTo http://192.168.101.20:3000/victim/my_repo.git\n   e5c07b3..9a0b884  main -> main\n\n[+] latest commit on victim/my_repo@main: 'PoC: unauthorized commit via maintainer-edit bypass'\n[+] CONFIRMED: unauthorized push to upstream succeeded.\n```\n\nA `PWNED.txt` file will appear on the target repo's default branch, committed by the attacker who has no write access.\n\n\n## Impact\n\nFull repository compromise. Any logged-in user can backdoor any repository they can read, including all public repositories on the instance.\n\n## Suggested Fix\n\nTwo independent checks are missing; both should be added for defense in depth:\n\n1. **At PR creation:** before setting `AllowMaintainerEdit = true`, verify the submitter has write access to the **HEAD** repository.\n2. **In `CanMaintainerWriteToBranch`:** verify that the PR's HEAD repo matches the repository being pushed to, and that the PR was opened by a legitimate owner/writer of the HEAD repository. Do not trust `AllowMaintainerEdit` solely based on BASE write access.","published":"2026-07-03T20:19:34.133Z","modified":"2026-08-12T03:51:16.868271624Z","cvss":{"score":8.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N"},"epss":{"score":0.00351,"percentile":0.28686,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Go","name":"code.gitea.io/gitea","fixedVersion":"1.26.2"}],"fix":{"url":"https://github.com/go-gitea/gitea/pull/37479","label":"go-gitea/gitea#37479"},"references":[{"type":"ADVISORY","url":"https://blog.gitea.com/release-of-1.26.2/"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/26xxx/CVE-2026-26231.json"},{"type":"ADVISORY","url":"https://github.com/go-gitea/gitea/releases/tag/v1.26.2"},{"type":"ADVISORY","url":"https://github.com/go-gitea/gitea/security/advisories/GHSA-mm7c-rhg6-qr4r"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-26231"},{"type":"FIX","url":"https://github.com/go-gitea/gitea/pull/37479"},{"type":"FIX","url":"https://github.com/go-gitea/gitea/pull/37484"},{"type":"PACKAGE","url":"https://github.com/go-gitea/gitea"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:16.868271624Z"}}