mirror of
https://github.com/go-gitea/gitea.git
synced 2025-04-20 00:19:08 +03:00
Correctly handle submodule view and avoid throwing 500 error (#34121)
Auto-redirect for in-site links, and show 404 for external links (to avoid open redirect or phishing)
This commit is contained in:
@ -20,6 +20,8 @@ import (
|
|||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
giturl "code.gitea.io/gitea/modules/git/url"
|
||||||
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@ -302,8 +304,33 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
|
|||||||
ctx.Redirect(link)
|
ctx.Redirect(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleRepoViewSubmodule(ctx *context.Context, submodule *git.SubModule) {
|
||||||
|
submoduleRepoURL, err := giturl.ParseRepositoryURL(ctx, submodule.URL)
|
||||||
|
if err != nil {
|
||||||
|
HandleGitError(ctx, "prepareToRenderDirOrFile: ParseRepositoryURL", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
submoduleURL := giturl.MakeRepositoryWebLink(submoduleRepoURL)
|
||||||
|
if httplib.IsCurrentGiteaSiteURL(ctx, submoduleURL) {
|
||||||
|
ctx.RedirectToCurrentSite(submoduleURL)
|
||||||
|
} else {
|
||||||
|
// don't auto-redirect to external URL, to avoid open redirect or phishing
|
||||||
|
ctx.Data["NotFoundPrompt"] = submoduleURL
|
||||||
|
ctx.NotFound(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
|
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
|
if entry.IsSubModule() {
|
||||||
|
submodule, err := ctx.Repo.Commit.GetSubModule(entry.Name())
|
||||||
|
if err != nil {
|
||||||
|
HandleGitError(ctx, "prepareToRenderDirOrFile: GetSubModule", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
|
return
|
||||||
|
}
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
prepareToRenderDirectory(ctx)
|
prepareToRenderDirectory(ctx)
|
||||||
} else {
|
} else {
|
||||||
|
32
routers/web/repo/view_home_test.go
Normal file
32
routers/web/repo/view_home_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
git_module "code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/services/contexttest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestViewHomeSubmoduleRedirect(t *testing.T) {
|
||||||
|
unittest.PrepareTestEnv(t)
|
||||||
|
|
||||||
|
ctx, _ := contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
||||||
|
submodule := &git_module.SubModule{Path: "test-submodule", URL: setting.AppURL + "user2/repo-other.git"}
|
||||||
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
|
assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus())
|
||||||
|
assert.Equal(t, "/user2/repo-other", ctx.Resp.Header().Get("Location"))
|
||||||
|
|
||||||
|
ctx, _ = contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
||||||
|
submodule = &git_module.SubModule{Path: "test-submodule", URL: "https://other/user2/repo-other.git"}
|
||||||
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
|
// do not auto-redirect for external URLs, to avoid open redirect or phishing
|
||||||
|
assert.Equal(t, http.StatusNotFound, ctx.Resp.WrittenStatus())
|
||||||
|
}
|
Reference in New Issue
Block a user