Skip to content

Conversation

@silverwind
Copy link
Member

@silverwind silverwind commented Dec 17, 2025

Removes the CSRF cookie in favor of CrossOriginProtection which relies purely on HTTP headers.

Fixes: #11188
Fixes: #30333
Helps: #35107

TODOs:

  • Fix tests
  • Ideally add tests to validates the protection

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Dec 17, 2025
@github-actions github-actions bot added modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files modifies/frontend labels Dec 17, 2025
@github-actions github-actions bot added the docs-update-needed The document needs to be updated synchronously label Dec 17, 2025
@silverwind silverwind changed the title Replace csrf cookie with Go 1.25 CrossOriginProtection Replace csrf cookie with CrossOriginProtection Dec 17, 2025
@silverwind silverwind changed the title Replace csrf cookie with CrossOriginProtection Replace CSRF cookie with CrossOriginProtection Dec 17, 2025
@silverwind silverwind marked this pull request as draft December 17, 2025 23:14
@silverwind
Copy link
Member Author

silverwind commented Dec 17, 2025

Test failures need investigation. I think I was quite thorough with this removal, rg csrf returns clean.

@silverwind silverwind added the pr/breaking Merging this PR means builds will break. Needs a description what exactly breaks, and how to fix it! label Dec 18, 2025
@silverwind
Copy link
Member Author

silverwind commented Dec 18, 2025

Unexpectedly, the fix in 1eb058d worked to fix the last issue. I think there may be a underlying bug why this test is sensitive to a GET request, but as far as this PR is concerned, its ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use a new test for CrossOriginProtection

Copy link
Member Author

@silverwind silverwind Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I would still like to add a integration test that leverages Sec-Fetch-Site to validate this protection.

@wxiaoguang
Copy link
Contributor

wxiaoguang commented Dec 18, 2025

⚠️ BREAKING ⚠️

The _crsf cookie will no longer be set and is no longer necessary to be sent. GET requests that were used to retrieve it are no longer neccessary.

"breaking" usually means end users or site admins must do something, or experience something totally different.

But for this one, I think it isn't really "breaking". WDYT?


And, the TODOs are not necessary (or, we shouldn't "add additional trusted origins", there is no such use case)

@wxiaoguang
Copy link
Contributor

wxiaoguang commented Dec 18, 2025

I wonder if it's even necessary to disable COP on any endpoints. It's only active for browsers and if browser headers are not present, the protection will just allow the request which means any API client will be unaffected.

I also consider that's unnecessary to disable CrossOriginProtection. So I think we can remove optSignInAnyOrigin and only use optSignIn

Not right, see below

@silverwind
Copy link
Member Author

silverwind commented Dec 18, 2025

Yeah I think we can go strict and have it enabled on all endpoints. If issues arise, we can think about solutions.

@silverwind
Copy link
Member Author

Done in da28335, now it's always enabled unconditionally.

@wxiaoguang
Copy link
Contributor

Done in da28335, now it's always enabled unconditionally.

Wait, it will cause problems with CORS, according to AI:

If your server implements a policy that rejects Sec-Fetch-Site: cross-site for certain endpoints, the server can block it (e.g., respond 403) even if CORS would otherwise allow it.

So we still need to disable CrossOriginProtection for the CORS endpoints.

image

@silverwind
Copy link
Member Author

For the record, if there are issues, COP offers 2 ways to disable it conditionally:

Both could be made configurable, if needed.

@wxiaoguang wxiaoguang marked this pull request as draft December 18, 2025 11:12
@silverwind
Copy link
Member Author

So we still need to disable CrossOriginProtection for the CORS endpoints.

I'm not sure but yes sounds plausible that CORS is an exception.

@silverwind
Copy link
Member Author

I've re-added optSignInAnyOrigin and added it anywhere where optionsCorsHandler is active. Maybe the option could also be combined into optionsCorsHandler but I have no idea how to do that.

@silverwind
Copy link
Member Author

I think combining these two options is still not good because those route groups also match on non-CORS requests but we probably only want to disable the protection when the request was identified as CORS, e.g. when corsHandler is non-nil inside the optionsCorsHandler callback.

@wxiaoguang wxiaoguang dismissed their stale review December 18, 2025 11:23

Leave for a while. The current logic isn't right.

@GiteaBot GiteaBot added lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Dec 18, 2025
@silverwind
Copy link
Member Author

I think the cors handler could indicate in the request context that it had a match with a boolean flag, and then the COP handler could act on that flag and be disabled.

@silverwind
Copy link
Member Author

silverwind commented Dec 18, 2025

I'm not sure your AI answer is right. Go's protection relies on Sec-Fetch-Site or Origin headers and I think one, if not both headers will be present on CORS request, at least for the unsafe methods. There is even a Sec-Fetch-Mode: cors, which further reinforces my assumption.

So I'd lean towards having all endpoints protected, without exception. Restrictions can be relaxed later if issues are demonstrated. I will push again the full strict settings.

@wxiaoguang
Copy link
Contributor

I'm not sure your AI answer is right.

AI's answer is right, I asked a general question.

Go's protection relies on Sec-Fetch-Site or Origin headers and I think one, if not both headers will be present on CORS request, at least for the unsafe methods.

That's Golang's implementation. And you MUST make CrossOriginProtection work with CORS config, but not just make a new default CrossOriginProtection.

image

@silverwind
Copy link
Member Author

I don't mind having unprotected CORS routes but that AI answer seems nonsensical to me:

If your server implements a policy that rejects Sec-Fetch-Site: cross-site for certain endpoints, the server can block it (e.g., respond 403) even if CORS would otherwise allow it.

My understanding is that all requests, including CORS preflights will send one of Sec-Fetch-Site or Origin and when I ask google ai, it confirms this:

image

@wxiaoguang
Copy link
Contributor

That's Golang's implementation. And you MUST make CrossOriginProtection work with CORS config, but not just make a new default CrossOriginProtection.

See my comment above. "CrossOriginProtection" must accept (trust) that origin, if I understand correctly.

@silverwind
Copy link
Member Author

I've read a bit more on these topics, these seem like good resources:

https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
https://www.alexedwards.net/blog/preventing-csrf-in-go

From what I gather, these header checks alone are not recommended, but header checks combined with a SameSite cookie (lax or strict) is recommended as adequate protection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-update-needed The document needs to be updated synchronously lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. modifies/frontend modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files type/refactoring Existing code has been cleaned up. There should be no new functionality.

Projects

None yet

4 participants