GitHub Advisoryadvisory · Go
GHSA-82f7-87hm-852x Gitea: Repository Migration Follows Git HTTP Redirects After URL Allow/Block Validation, Enabling Internal Git Repository Exfiltration
HIGH
Official page ↗
- Aliases
- CVE-2026-57894
- Ecosystem
- Go
- Packages
- code.gitea.io/gitea
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
- Weaknesses
- CWE-918
- Reviewed
- 2026-07-21
Affected packages
• Go code.gitea.io/gitea: < 1.27.0 → fixed in 1.27.0
Description
Repository Migration Follows Git HTTP Redirects After URL Allow/Block Validation, Enabling Internal Git Repository Exfiltration
Summary
Gitea validates the user-supplied repository migration URL, but the actual clone and later mirror fetch operations are performed by the Git command-line client without disabling HTTP redirects. Git's default `http.followRedirects=initial` follows the first redirect and then uses the redirected URL as the base for later repository object requests.
This creates a URL-policy bypass, SSRF, and repository exfiltration primitive. A low-privileged authenticated user can submit an allowed public Git URL that redirects the Gitea server to an otherwise blocked or internal Git HTTP(S) endpoint. Local validation confirmed that Git followed a first-hop redirect to `127.0.0.1`, fetched Git objects, and completed the clone; `git -c http.followRedirects=false clone` blocked the same path.
The main impact is internal Git repository exfiltration into an attacker-controlled Gitea repository. Pull mirrors increase risk because scheduled `git fetch --tags` operations can keep following the redirect and collect future internal commits.
This is High severity by default for internet-accessible instances with migrations enabled, and can become Critical where internal repositories contain deploy keys, CI/CD secrets, cloud credentials, Terraform state, kubeconfigs, signing material, or production configuration. Direct unauthenticated exploitation, direct Gitea server RCE, arbitrary `file://` import, and default Actions runner execution are not confirmed.
Technical Root Cause Analysis
The root cause is a validation/enforcement mismatch across a trust boundary. This should be treated as a product security issue rather than a pure deployment misconfiguration: deployment choices influence reachability and impact, but Gitea applies policy to the originally submitted URL while the Git subprocess is allowed to reach a different effective URL after redirection.
Gitea validates the original migration URL:
• `C:\Users\One\Desktop\gitea_new\gitea\routers\web\repo\migrate.go:180` parses the submitted web migration clone address.
• `C:\Users\One\Desktop\gitea_new\gitea\routers\web\repo\migrate.go:182` calls `migrations.IsMigrateURLAllowed`.
• `C:\Users\One\Desktop\gitea_new\gitea\routers\api\v1\repo\migrate.go:101` parses the submitted API migration clone address.
• `C:\Users\One\Desktop\gitea_new\gitea\routers\api\v1\repo\migrate.go:103` calls `migrations.IsMigrateURLAllowed`.
The URL validator resolves and checks the initially supplied host:
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\migrate.go:44` defines `IsMigrateURLAllowed`.
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\migrate.go:75` rejects unsupported schemes.
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\migrate.go:79` extracts the host.
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\migrate.go:85` performs DNS resolution.
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\migrate.go:86` enforces the allow/block list on the originally resolved host.
After this validation, the actual repository data transfer is delegated to Git:
• `C:\Users\One\Desktop\gitea_new\gitea\services\repository\migrate.go:93` calls `gitrepo.CloneExternalRepo` with `opts.CloneAddr`.
• `C:\Users\One\Desktop\gitea_new\gitea\modules\gitrepo\clone.go:13` delegates to `git.Clone`.
• `C:\Users\One\Desktop\gitea_new\gitea\modules\git\repo.go:123` constructs a `git clone` command.
• `C:\Users\One\Desktop\gitea_new\gitea\modules\git\repo.go:125` conditionally sets only `http.sslVerify=false`.
• `C:\Users\One\Desktop\gitea_new\gitea\modules\git\repo.go:154` appends the source and destination arguments.
No equivalent network policy is applied to the final URL reached by Git after HTTP redirection. The protected migration HTTP client exists for service-specific migration API calls, but it is not used for the raw Git clone/fetch operation:
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\http_client.go:16` defines `NewMigrationHTTPClient`.
• `C:\Users\One\Desktop\gitea_new\gitea\services\migrations\http_client.go:27` applies a host-matching dialer.
That protection does not wrap `git clone` or `git fetch`.
The behavior depends on Git's documented redirect handling. The current Git documentation states that `http.followRedirects=initial` follows the initial request redirect and uses the redirected URL as the base for follow-up requests. The default value is `initial`: https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpfollowRedirects
This means the effective enforcement point is not the same as the actual network sink. Gitea checks `https://attacker.example/repo.git`; Git later retrieves `http://127.0.0.1:PORT/internal.git/...` or another internal target selected by the redirector.
For mirrors, the issue extends beyond initial migration:
• `C:\Users\One\Desktop\gitea_new\gitea\services\repository\migrate.go:177` creates a mirror record when migration is requested as a mirror.
• `C:\Users\One\Desktop\gitea_new\gitea\services\repository\migrate.go:188` stores the sanitized original remote address.
• `C:\Users\One\Desktop\gitea_new\gitea\services\mirror\mirror_pull.go:120` later performs mirror synchronization with `git fetch --tags`.
• `C:\Users\One\Desktop\gitea_new\gitea\services\mirror\mirror_pull.go:126` fetches from the configured remote.
Because the mirror sync path also delegates to Git, a redirecting remote can continue to redirect scheduled fetches into an internal target.
Affected Assets & Attack Surface
Affected features are URL-based repository migration, API repository migration, pull mirror creation through migration, and scheduled pull mirror synchronization. The relevant entrypoints are `POST /repo/migrate` for signed-in web users (`C:\Users\One\Desktop\gitea_new\gitea\routers\web\web.go:1062`) and `POST /api/v1/repos/migrate` for API-token users (`C:\Users\One\Desktop\gitea_new\gitea\routers\api\v1\api.go:1170`).
Important preconditions are:
• Repository migrations are enabled, which is the default in code and example configuration (`C:\Users\One\Desktop\gitea_new\gitea\modules\setting\repository.go:181`, `C:\Users\One\Desktop\gitea_new\gitea\custom\conf\app.example.ini:1078`).
• The attacker has a low-privileged account or the instance permits self-registration. Default/example service settings do not force registration confirmation by default.
• For persistent exfiltration, pull mirrors must be enabled (`C:\Users\One\Desktop\gitea_new\gitea\modules\setting\mirror.go:20`).
• The Gitea server can reach internal Git HTTP(S) services that the attacker cannot reach directly.
High-value targets include internal Gitea, GitLab, GitHub Enterprise, Bitbucket, cgit, git-http-backend, and static bare Git repositories, especially repositories containing CI/CD definitions, deployment manifests, IaC, credentials, or production configuration.
The key trust boundary is that low-privileged user input influences server-side Git network access. Gitea validates the initially supplied URL, then hands control to a Git subprocess whose redirected destination is not constrained by the same allow/block policy. An attacker can discover exposure by using a controlled redirector, observing outbound Git requests, and testing whether scheduled mirror requests continue to arrive.
Exploitation Walkthrough
Scenario 1: One-time internal repository exfiltration
1. The attacker obtains a low-privileged Gitea account. On instances with open registration, this may require only creating a user.
2. The attacker hosts a public HTTP endpoint that appears to be a Git remote, for example `https://attacker.example/public.git`.
3. The attacker configures the endpoint to respond to the initial Git discovery request with an HTTP redirect to an internal target, for example `http://internal-git.company.local/team/private.git/info/refs?service=g…
Related
Alias · CVE (1)
- CVE-2026-57894 Repository Migration Follows Git HTTP Redirects After URL Allow/Block Validation, Enabling Internal Git Repository Exfiltration vulnerability
Weakness · CWE (1)
- CWE-918 Server-Side Request Forgery weakness