From 9115b9f34f3db77682238d928996318c98f8bf94 Mon Sep 17 00:00:00 2001 From: "stonezdj(Daojun Zhang)" Date: Mon, 26 Feb 2024 11:27:42 +0800 Subject: [PATCH] [cherry-pick] Limit URL to local site (#20023) Limit url to local path Signed-off-by: stonezdj Co-authored-by: stonezdj --- src/common/utils/utils.go | 5 +++++ src/common/utils/utils_test.go | 22 ++++++++++++++++++++++ src/core/controllers/oidc.go | 8 +++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/common/utils/utils.go b/src/common/utils/utils.go index 22875014c..9c9b6a9e6 100644 --- a/src/common/utils/utils.go +++ b/src/common/utils/utils.go @@ -342,3 +342,8 @@ func MostMatchSorter(a, b string, matchWord string) bool { } return len(a) < len(b) } + +// IsLocalPath checks if path is local +func IsLocalPath(path string) bool { + return strings.HasPrefix(path, "/") && !strings.HasPrefix(path, "//") +} diff --git a/src/common/utils/utils_test.go b/src/common/utils/utils_test.go index 73d9fb28b..8849e1f0c 100644 --- a/src/common/utils/utils_test.go +++ b/src/common/utils/utils_test.go @@ -486,3 +486,25 @@ func TestValidateCronString(t *testing.T) { } } } + +func TestIsLocalPath(t *testing.T) { + type args struct { + path string + } + tests := []struct { + name string + args args + want bool + }{ + {"normal test", args{"/harbor/project"}, true}, + {"failed", args{"www.myexample.com"}, false}, + {"other_site1", args{"//www.myexample.com"}, false}, + {"other_site2", args{"https://www.myexample.com"}, false}, + {"other_site", args{"http://www.myexample.com"}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, IsLocalPath(tt.args.path), "IsLocalPath(%v)", tt.args.path) + }) + } +} diff --git a/src/core/controllers/oidc.go b/src/core/controllers/oidc.go index 3d95ca560..1ca8a60b8 100644 --- a/src/core/controllers/oidc.go +++ b/src/core/controllers/oidc.go @@ -63,7 +63,13 @@ func (oc *OIDCController) RedirectLogin() { oc.SendInternalServerError(err) return } - if err := oc.SetSession(redirectURLKey, oc.Ctx.Request.URL.Query().Get("redirect_url")); err != nil { + redirectURL := oc.Ctx.Request.URL.Query().Get("redirect_url") + if !utils.IsLocalPath(redirectURL) { + log.Errorf("invalid redirect url: %v", redirectURL) + oc.SendBadRequestError(fmt.Errorf("cannot redirect to other site")) + return + } + if err := oc.SetSession(redirectURLKey, redirectURL); err != nil { log.Errorf("failed to set session for key: %s, error: %v", redirectURLKey, err) oc.SendInternalServerError(err) return