# Yet another RCE in Gogs, but it's fixed this time!

Unsanitized org username allows path traversal in Gogs, writing a bare repo into a worktree to hijack git hooks and achieve RCE.

- Payout: Research
- Severity: critical
- Program: Gogs
- Write-up by: Aikido Security
- Disclosed: 2026-08-19
- CVE: CVE-2026-52813, CVE-2026-52810
- Write-up quality: 9/10
- Original: https://www.aikido.dev/blog/fixed-rce-gogs-cve-2026-52813
- Library page: https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-fixed-rce-gogs-cve-2026-52813
- Tags: area:web domain:web impact:rce kind:research platform:threat-intel sev:critical tech:go technique:chained technique:source-review vuln:access-control vuln:auth-bypass vuln:path-traversal vuln:rce vuln:xss

**Target:** Gogs self-hosted Git service (API org creation, repo editor, git HTTP protocol)
**Root cause:** UserPath() joins the org username into the repository root without sanitization (org creation lacks AlphaDashDot binding), enabling ../ traversal; separately, HTTPContexter authorizes based on a service query param while routing by path, causing pull/write confusion.
**Steps:**
1. Create API token via `POST /api/v1/users/{user}/tokens`
2. Create org with `POST /api/v1/user/orgs` body `{"username":"../../gogs/data/tmp/local-r/1"}`
3. Create repo under org via `POST /api/v1/org/{urlencoded_org}/repos` to land a bare `traversal.git` inside the worktree
4. Add a dummy file via UI to materialize worktree at `/data/gogs/data/tmp/local-r/1`
5. Clone the editor repo, write `traversal.git/hooks/update` with `id>/tmp/pwned`, commit and `git push` (UI editor blocks `.git/` but native push allows `traversal.git`)
6. Upload another dummy file via `PUT /api/v1/repos/{org}/traversal/contents/dummy4` to trigger push to bare repo, firing the update hook
7. For CVE-2026-52810: mitmproxy rewrites `/git-receive-pack` to `/git-receive-pack?service=git-upload-pack` on a private repo where attacker is read-only collaborator, then `git push` succeeds
**How found:** AI pentest agent flagged path traversal in org username via API; human noticed UserPath() joins unsanitized org name, confirmed /tmp write, then reasoned that bare repo write alone is weak but placing it inside a worktree lets them edit hooks via native git push.
**Exploitation:** Attacker creates a traversal org to place a bare repo inside a Gogs-managed worktree, edits its hooks/update via native git push (bypassing the .git path check since segment is traversal.git), then triggers a commit that pushes to the bare repo, executing the hook as the git user. Push bypass uses a proxy to append service=git-upload-pack so authorization treats receive-pack as read.
**Escalation:** Chained weak path traversal (bare repo write only) with worktree placement and git hook execution to escalate to full RCE; push bypass requires private repo or RequireSigninView to avoid nil AuthUser panic.
**Insight:** When a path-traversal only yields a fixed directory structure (bare git repo), look for a second writable location (worktree temp dir) to nest it in, and check whether UI-level path filters (.git/) differ from what native git push allows (traversal.git passes).
