fix: limit OAuth redirects to local paths (#14585)

- This prevents a malicious user from crafting a redirect
  URL to a nefarious site under their control.
This commit is contained in:
Jon Ayers
2024-09-10 15:58:50 +01:00
committed by GitHub
parent 2a9234e9ba
commit 328e69629c
8 changed files with 183 additions and 20 deletions
+31 -2
View File
@@ -207,12 +207,12 @@ func TestExternalAuthManagement(t *testing.T) {
const gitlabID = "fake-gitlab"
githubCalled := false
githubApp := oidctest.NewFakeIDP(t, oidctest.WithServing(), oidctest.WithRefresh(func(email string) error {
githubApp := oidctest.NewFakeIDP(t, oidctest.WithServing(), oidctest.WithRefresh(func(_ string) error {
githubCalled = true
return nil
}))
gitlabCalled := false
gitlab := oidctest.NewFakeIDP(t, oidctest.WithServing(), oidctest.WithRefresh(func(email string) error {
gitlab := oidctest.NewFakeIDP(t, oidctest.WithServing(), oidctest.WithRefresh(func(_ string) error {
gitlabCalled = true
return nil
}))
@@ -508,6 +508,35 @@ func TestExternalAuthCallback(t *testing.T) {
resp = coderdtest.RequestExternalAuthCallback(t, "github", client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
})
t.Run("CustomRedirect", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
ExternalAuthConfigs: []*externalauth.Config{{
InstrumentedOAuth2Config: &testutil.OAuth2Config{},
ID: "github",
Regex: regexp.MustCompile(`github\.com`),
Type: codersdk.EnhancedExternalAuthProviderGitHub.String(),
}},
})
maliciousHost := "https://malicious.com"
expectedURI := "/some/path?param=1"
_ = coderdtest.CreateFirstUser(t, client)
resp := coderdtest.RequestExternalAuthCallback(t, "github", client, func(req *http.Request) {
req.AddCookie(&http.Cookie{
Name: codersdk.OAuth2RedirectCookie,
Value: maliciousHost + expectedURI,
})
})
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
location, err := resp.Location()
require.NoError(t, err)
require.Equal(t, expectedURI, location.RequestURI())
require.Equal(t, client.URL.Host, location.Host)
require.NotContains(t, location.String(), maliciousHost)
})
t.Run("ValidateURL", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)