diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index 2fe6280349d..8fb054762b0 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -98,17 +98,17 @@ func Migrate(ctx *context.APIContext) { } } + gitServiceType := convert.ToGitServiceType(form.Service) + remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword) if err == nil { - err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer) + err = migrations.IsMigrateURLAllowedForService(remoteAddr, gitServiceType, ctx.Doer) } if err != nil { handleRemoteAddrError(ctx, err) return } - gitServiceType := convert.ToGitServiceType(form.Service) - if form.Mirror && setting.Mirror.DisableNewPull { ctx.APIError(http.StatusForbidden, "the site administrator has disabled the creation of new pull mirrors") return diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index f927ec05697..bdddb3c6f8c 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -153,7 +153,7 @@ func MigratePost(ctx *context.Context) { remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword) if err == nil { - err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer) + err = migrations.IsMigrateURLAllowedForService(remoteAddr, form.Service, ctx.Doer) } if err != nil { handleMigrateRemoteAddrError(ctx, err, "clone_addr") diff --git a/services/migrations/migrate.go b/services/migrations/migrate.go index 313e930d285..ed7c13209ef 100644 --- a/services/migrations/migrate.go +++ b/services/migrations/migrate.go @@ -22,6 +22,7 @@ import ( "gitea.dev/modules/log" base "gitea.dev/modules/migration" "gitea.dev/modules/setting" + "gitea.dev/modules/structs" "gitea.dev/modules/util" ) @@ -35,6 +36,17 @@ func RegisterDownloaderFactory(factory base.DownloaderFactory) { factories = append(factories, factory) } +// IsMigrateURLAllowedForService checks the URL like IsMigrateURLAllowed, and additionally rejects local paths +// unless it is a plain git migration, because other services are accessed by their remote API. +func IsMigrateURLAllowedForService(remoteURL string, serviceType structs.GitServiceType, doer *user_model.User) error { + if serviceType != structs.PlainGitService { + if u, err := url.Parse(remoteURL); err == nil && (u.Scheme == "file" || u.Scheme == "") { + return &git.ErrInvalidCloneAddr{Host: remoteURL, IsProtocolInvalid: true} + } + } + return IsMigrateURLAllowed(remoteURL, doer) +} + // IsMigrateURLAllowed checks if an URL is allowed to be migrated from func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error { // Remote address can be HTTP/HTTPS/Git URL or local path. @@ -79,7 +91,7 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error { // MigrateRepository migrate repository according MigrateOptions func MigrateRepository(ctx context.Context, doer *user_model.User, ownerName string, opts base.MigrateOptions, messenger base.Messenger) (*repo_model.Repository, error) { - err := IsMigrateURLAllowed(opts.CloneAddr, doer) + err := IsMigrateURLAllowedForService(opts.CloneAddr, opts.GitServiceType, doer) if err != nil { return nil, err } diff --git a/services/migrations/migrate_test.go b/services/migrations/migrate_test.go index 5683572285b..aad6930adf1 100644 --- a/services/migrations/migrate_test.go +++ b/services/migrations/migrate_test.go @@ -11,8 +11,10 @@ import ( "testing" user_model "gitea.dev/models/user" + "gitea.dev/modules/git" "gitea.dev/modules/git/gitcmd" "gitea.dev/modules/setting" + "gitea.dev/modules/structs" "gitea.dev/modules/test" "gitea.dev/modules/util" @@ -71,3 +73,15 @@ func TestMigrateWhiteBlocklist(t *testing.T) { setting.ImportLocalPaths = old } + +func TestIsMigrateURLAllowedForServiceLocalPath(t *testing.T) { + defer test.MockVariableValue(&setting.ImportLocalPaths, true)() + admin := &user_model.User{IsAdmin: true} + for _, addr := range []string{"/tmp", "file:///tmp"} { + assert.NoError(t, IsMigrateURLAllowedForService(addr, structs.PlainGitService, admin)) + for _, svc := range []structs.GitServiceType{structs.GithubService, structs.GiteaService, structs.GitlabService, structs.BitbucketServerService} { + err := IsMigrateURLAllowedForService(addr, svc, admin) + assert.ErrorAs(t, err, new(*git.ErrInvalidCloneAddr), "%s %d", addr, svc) + } + } +} diff --git a/templates/repo/migrate/bitbucketserver.tmpl b/templates/repo/migrate/bitbucketserver.tmpl index 0032cf18531..bc0ad74619f 100644 --- a/templates/repo/migrate/bitbucketserver.tmpl +++ b/templates/repo/migrate/bitbucketserver.tmpl @@ -10,13 +10,7 @@ {{template "repo/migrate/common-init" (dict "ServiceType" .service)}} {{template "repo/migrate/variants" .}} -