feat: add Fetch Metadata CSRF protection#10221
Open
memleakd wants to merge 5 commits into
Open
Conversation
- Add Fetch Metadata-first CSRF verification with token fallback. - Keep upgraded apps token-only when the new config is missing. - Add Vary handling for unsafe Fetch Metadata-protected requests. - Document configuration, fallback behavior, and same-site caveats. - Cover same-origin, same-site, cross-site, fallback, and filter behavior. Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
neznaika0
suggested changes
May 20, 2026
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
michalsn
reviewed
May 25, 2026
Member
michalsn
left a comment
There was a problem hiding this comment.
The new name csrfFetchMetadataRejectSameSite also implies a behavior change. Can we add/modify tests to make sure that:
- same-site with valid token passes by default via token fallback
- same-site with missing/invalid token fails via token fallback
- same-site with csrfFetchMetadataRejectSameSite = true fails even with a valid token
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Contributor
Author
|
Thanks for the review @michalsn. Just pushed an update addressing your feedback. |
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR proposes adding Fetch Metadata-based CSRF protection to CodeIgniter.
CSRF tokens work, and this PR keeps them as the compatibility fallback. But the web platform and modern frameworks are clearly moving toward browser-provided request context as the better default for browser CSRF protection. Other frameworks have already moved in this direction, or have active work around the same idea, and OWASP documents Fetch Metadata as a defense-in-depth layer for CSRF protection.
The reason is pretty simple: token-based CSRF protection has always been awkward and a source of headaches for many developers. Forms need hidden fields, JavaScript requests need special headers, JSON requests need special handling, cached pages and long-lived tabs can produce stale-token failures, token regeneration can surprise users, and teams regularly end up debugging "why did this normal request fail?" instead of working on the application.
Fetch Metadata gives the framework a cleaner browser-native signal. Modern browsers send the
Sec-Fetch-Siteheader, which tells the server whether an unsafe request came from the same origin, the same site, or another site. That lets CodeIgniter ask a simpler question before touching token verification:If yes, same-origin browser requests can pass without token plumbing. If it is clearly cross-site, it can be rejected before token verification. If the browser does not provide enough information, CodeIgniter falls back to the existing token check.
This keeps the change conservative while still moving new applications in the right direction:
none, unknown, orsame-siteSec-Fetch-Sitevalues fall back to token verification.cross-siterequests are rejected before token verification.$csrfFetchMetadata = false.same-siterequests before token verification with$csrfFetchMetadataRejectSameSite = true.With Fetch Metadata enabled:
Sec-Fetch-Site: same-originpasses without a token.Sec-Fetch-Site: cross-siteis rejected.Sec-Fetch-Site: same-sitefalls back to token verification by default.none, or unknown values fall back to token verification.So this PR does not remove CSRF tokens. They remain supported and useful as the migration fallback, especially for upgraded applications. But the direction is intentional: new CodeIgniter applications should get a more modern, browser-native CSRF protection path by default, and token-heavy CSRF handling can gradually become the legacy compatibility path rather than the everyday developer experience.
The CSRF filter also adds
Vary: Sec-Fetch-Siteto normal shared responses, CSRF redirect responses, and CSRF exception responses for unsafe requests when Fetch Metadata protection is enabled, so caches do not mix responses across request contexts.Tests cover same-origin, same-site, cross-site, token fallback, token-only compatibility, upgraded config compatibility, redirect responses,
Varybehavior, and request body preservation.References
Sec-Fetch-Site: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-SiteChecklist: