Replace CSRF cookie with CrossOriginProtection (#36183)

Removes the CSRF cookie in favor of
[`CrossOriginProtection`](https://pkg.go.dev/net/http#CrossOriginProtection)
which relies purely on HTTP headers.

Fixes: https://github.com/go-gitea/gitea/issues/11188
Fixes: https://github.com/go-gitea/gitea/issues/30333
Helps: https://github.com/go-gitea/gitea/issues/35107

TODOs:

- [x] Fix tests
- [ ] Ideally add tests to validates the protection

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2025-12-25 11:33:34 +01:00
committed by GitHub
parent eddf875992
commit 42d294941c
207 changed files with 178 additions and 1196 deletions
+5 -26
View File
@@ -39,9 +39,7 @@ func TestOrgTeamEmailInvite(t *testing.T) {
session := loginUser(t, "user1")
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
csrf := GetUserCSRFToken(t, session)
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
"_csrf": csrf,
"uid": "1",
"uname": user.Email,
})
@@ -58,10 +56,7 @@ func TestOrgTeamEmailInvite(t *testing.T) {
// join the team
inviteURL := "/org/invite/" + invites[0].Token
csrf = GetUserCSRFToken(t, session)
req = NewRequestWithValues(t, "POST", inviteURL, map[string]string{
"_csrf": csrf,
})
req = NewRequest(t, "POST", inviteURL)
resp = session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", test.RedirectURL(resp))
session.MakeRequest(t, req, http.StatusOK)
@@ -93,7 +88,6 @@ func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"uid": "1",
"uname": user.Email,
})
@@ -111,9 +105,7 @@ func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
req = NewRequest(t, "GET", "/user/login?redirect_to="+url.QueryEscape(inviteURL))
resp = MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
req = NewRequestWithValues(t, "POST", "/user/login", map[string]string{
"_csrf": doc.GetCSRF(),
"user_name": "user5",
"password": "password",
})
@@ -135,9 +127,7 @@ func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
session.jar.SetCookies(baseURL, cr.Cookies())
// make the request
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
req = NewRequest(t, "POST", test.RedirectURL(resp))
resp = session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", test.RedirectURL(resp))
session.MakeRequest(t, req, http.StatusOK)
@@ -164,7 +154,6 @@ func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"uid": "1",
"uname": "doesnotexist@example.com",
})
@@ -182,9 +171,7 @@ func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
resp = MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
"_csrf": doc.GetCSRF(),
"user_name": "doesnotexist",
"email": "doesnotexist@example.com",
"password": "examplePassword!1",
@@ -208,9 +195,7 @@ func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
session.jar.SetCookies(baseURL, cr.Cookies())
// make the redirected request
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
req = NewRequest(t, "POST", test.RedirectURL(resp))
resp = session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", test.RedirectURL(resp))
session.MakeRequest(t, req, http.StatusOK)
@@ -243,7 +228,6 @@ func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"uid": "1",
"uname": "doesnotexist@example.com",
})
@@ -283,9 +267,7 @@ func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
// should be redirected to accept the invite
assert.Equal(t, inviteURL, test.RedirectURL(resp))
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
req = NewRequest(t, "POST", test.RedirectURL(resp))
resp = session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", test.RedirectURL(resp))
session.MakeRequest(t, req, http.StatusOK)
@@ -319,7 +301,6 @@ func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"uid": "1",
"uname": user.Email,
})
@@ -342,9 +323,7 @@ func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
assert.Equal(t, inviteURL, test.RedirectURL(resp))
// make the request
req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
req = NewRequest(t, "POST", test.RedirectURL(resp))
resp = session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", test.RedirectURL(resp))
session.MakeRequest(t, req, http.StatusOK)