mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-22 09:01:25 +00:00
fix: revert git clone http redirection forbidden (#38530)
Revert to 1.26 behavior. Incomplete, HandleGitCmdHTTPRedirection can be improved
This commit is contained in:
15
modules/git/redirection.go
Normal file
15
modules/git/redirection.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
|
||||
import "gitea.dev/modules/git/gitcmd"
|
||||
|
||||
func HandleGitCmdHTTPRedirection(cmd *gitcmd.Command, targets ...string) {
|
||||
// Protect from SSRF vector (e.g. migrating from an attacker URL).
|
||||
// cmd.AddConfig("http.followRedirects", "false")
|
||||
// However, we can't do so at the moment:
|
||||
// this fails due to 301: git -c http.followRedirects=false clone -v https://gitlab.com/{owner}/{repo}
|
||||
// this succeeds: git -c http.followRedirects=false clone -v https://gitlab.com/{owner}/{repo}.git
|
||||
// FIXME: GIT-CLONE-HTTP-REDIRECT-SSRF: need a complete solution in the future
|
||||
}
|
||||
@@ -151,9 +151,7 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error {
|
||||
}
|
||||
|
||||
cmd := gitcmd.NewCommand().AddArguments("clone")
|
||||
// Never follow HTTP redirects: no clone caller needs them, and a remote redirecting to an
|
||||
// otherwise-blocked address would be an SSRF vector (e.g. migrating from an attacker URL).
|
||||
cmd.AddArguments("-c", "http.followRedirects=false")
|
||||
HandleGitCmdHTTPRedirection(cmd, from, to)
|
||||
if opts.SkipTLSVerify {
|
||||
cmd.AddArguments("-c", "http.sslVerify=false")
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ func TestRepoIsEmpty(t *testing.T) {
|
||||
// TestCloneRefusesRedirects ensures Clone never follows HTTP redirects, so a remote
|
||||
// cannot redirect to an otherwise-blocked address (SSRF, e.g. during migration).
|
||||
func TestCloneRefusesRedirects(t *testing.T) {
|
||||
t.Skip("FIXME: GIT-CLONE-HTTP-REDIRECT-SSRF: need a complete solution in the future")
|
||||
var targetHit atomic.Bool
|
||||
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
targetHit.Store(true)
|
||||
|
||||
@@ -71,8 +71,8 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
|
||||
}
|
||||
|
||||
func pruneBrokenReferences(ctx context.Context, m *repo_model.Mirror, repoLogName string, gitRepo git.RepositoryFacade, timeout time.Duration) error {
|
||||
// Never follow HTTP redirects, see cmdFetch in runSync.
|
||||
cmd := gitcmd.NewCommand("remote", "prune").AddConfig("http.followRedirects", "false").AddDynamicArguments(m.GetRemoteName()).WithTimeout(timeout)
|
||||
cmd := gitcmd.NewCommand("remote", "prune").AddDynamicArguments(m.GetRemoteName()).WithTimeout(timeout)
|
||||
git.HandleGitCmdHTTPRedirection(cmd, m.GetRemoteName())
|
||||
stdout, _, pruneErr := cmd.WithRepo(gitRepo).RunStdString(ctx)
|
||||
if pruneErr != nil {
|
||||
// sanitize the output, since it may contain the remote address, which may contain a password
|
||||
@@ -129,9 +129,8 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*repo_module.SyncResu
|
||||
|
||||
// use fetch but not remote update because git fetch support --tags but remote update doesn't
|
||||
cmdFetch := func() *gitcmd.Command {
|
||||
// Never follow HTTP redirects: a mirror remote that later starts redirecting to an
|
||||
// otherwise-blocked address would be an SSRF/exfiltration vector on scheduled syncs.
|
||||
cmd := gitcmd.NewCommand("fetch", "--tags").AddConfig("http.followRedirects", "false")
|
||||
cmd := gitcmd.NewCommand("fetch", "--tags")
|
||||
git.HandleGitCmdHTTPRedirection(cmd, m.GetRemoteName())
|
||||
if m.EnablePrune {
|
||||
cmd.AddArguments("--prune")
|
||||
}
|
||||
@@ -212,9 +211,9 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*repo_module.SyncResu
|
||||
}
|
||||
|
||||
cmdRemoteUpdatePrune := func() *gitcmd.Command {
|
||||
// Never follow HTTP redirects, see cmdFetch above.
|
||||
return gitcmd.NewCommand("remote", "update", "--prune").AddConfig("http.followRedirects", "false").
|
||||
AddDynamicArguments(m.GetRemoteName()).WithTimeout(timeout).WithEnv(envs)
|
||||
cmd := gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(m.GetRemoteName()).WithTimeout(timeout).WithEnv(envs)
|
||||
git.HandleGitCmdHTTPRedirection(cmd, m.GetRemoteName())
|
||||
return cmd
|
||||
}
|
||||
|
||||
if repo_service.HasWiki(ctx, m.Repo) {
|
||||
|
||||
Reference in New Issue
Block a user