From a9bd068d00be473fdeb424cc948022e08e12b98c Mon Sep 17 00:00:00 2001 From: doasu Date: Tue, 31 Mar 2026 21:51:57 +0200 Subject: [PATCH] fix: URL-encode login provider name in the `href` attribute (#10301) The authentication provider's name (`$provider.DisplayName`) is not URL-encoded, so any illegal characters (e.g., '/') will be put in the link's href attribute verbatim. For example, if the provider's name is `foo/bar` (valid name), the href attribute will point to `/user/oauth2/foo/bar` instead of `/user/oauth2/foo%2Fbar`, resulting in a "404 Not found" error. This patch fixes this behaviour by URL-encoding the provider's DisplayName before appending it to the href attribute. Signed-off-by: doasu Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10301 Reviewed-by: Gusted Co-authored-by: doasu Co-committed-by: doasu --- templates/user/auth/oauth_container.tmpl | 2 +- tests/integration/signin_test.go | 30 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/templates/user/auth/oauth_container.tmpl b/templates/user/auth/oauth_container.tmpl index 7531320394..a50ca5f612 100644 --- a/templates/user/auth/oauth_container.tmpl +++ b/templates/user/auth/oauth_container.tmpl @@ -8,7 +8,7 @@
{{range $provider := .OAuth2Providers}} - diff --git a/tests/integration/signin_test.go b/tests/integration/signin_test.go index c9b2d6ed1c..0367bedd6e 100644 --- a/tests/integration/signin_test.go +++ b/tests/integration/signin_test.go @@ -97,6 +97,36 @@ func TestSigninWithRememberMe(t *testing.T) { session.MakeRequest(t, req, http.StatusOK) } +func TestProviderDisplayNameIsPathEscaped(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + testCases := []string{ + "sla/shed", + "per%cent", + "que?ry=string", + "ha#sh", + "spa ce", // doesn't break the path + "pl+us", // unchanged by url.PathEscape + "amper&sand", // unchanged by url.PathEscape + } + + for _, testCase := range testCases { + // GitLab is only used here for convenience. + addAuthSource(t, authSourcePayloadGitLabCustom(testCase)) + } + + request := NewRequest(t, "GET", "/user/login") + response := MakeRequest(t, request, http.StatusOK) + htmlDoc := NewHTMLParser(t, response.Body) + + for _, testCase := range testCases { + t.Run(testCase, func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + htmlDoc.AssertElement(t, fmt.Sprintf("a.oauth-login-link[href='/user/oauth2/%s']", url.PathEscape(testCase)), true) + }) + } +} + func TestDisableSignin(t *testing.T) { defer tests.PrepareTestEnv(t)() // Mock alternative auth ways as enabled