mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00: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" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"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" | ||||
| 	repo_module "code.gitea.io/gitea/modules/repository" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| @@ -302,8 +304,33 @@ func handleRepoEmptyOrBroken(ctx *context.Context) { | ||||
| 	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) { | ||||
| 	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() { | ||||
| 			prepareToRenderDirectory(ctx) | ||||
| 		} 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