From 435a7d56cb551dbcd45c6c518c5e5231c90b30b0 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 2 Nov 2025 10:53:27 +0200 Subject: [PATCH 01/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Extended core guidance to mention Fetch Metadata request headers (Sec-Fetch-*) as an alternative to CSRF tokens for state-changing requests. Added clarification that developers can use CSRF tokens or Fetch Metadata depending on project needs and client compatibility. Updated Fetch Metadata positionaing --- ..._Request_Forgery_Prevention_Cheat_Sheet.md | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 17bae843ea..1d733f61dc 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -14,7 +14,8 @@ In short, the following principles should be followed to defend against CSRF: - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** - **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** -- **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state changing requests (requests that cause actions on the site) and validate them on the backend** +- **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state changing requests (requests that cause actions on the site) and validate them on the backend, or validate [Fetch Metadata headers](#fetch-metadata-headers) on the backend for all state-changing requests.** +- **If your software is intended to be used only on modern browsers, you may rely primarily on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)** - **Stateless software should use [double submit cookies](#alternative-using-a-double-submit-cookie-pattern)** - **If an API-driven site can't use `
` tags, consider [using custom request headers](#employing-custom-request-headers-for-ajaxapi)** @@ -151,6 +152,97 @@ Since an attacker is unable to access the cookie value during a cross-site reque Though the Naive Double-Submit Cookie method is simple and scalable, it remains vulnerable to cookie injection attacks, especially when attackers control subdomains or network environments allowing them to plant or overwrite cookies. For instance, an attacker-controlled subdomain (e.g., via DNS takeover) could inject a matching cookie and thus forge a valid request token. [This resource](https://owasp.org/www-chapter-london/assets/slides/David_Johansson-Double_Defeat_of_Double-Submit_Cookie.pdf) details these vulnerabilities. Therefore, always prefer the _Signed Double-Submit Cookie_ pattern with session-bound HMAC tokens to mitigate these threats. +## Fetch Metadata headers + +Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. + +Although Fetch Metadata headers are relatively new compared to [token-based defenses](#token-based-mitigation), they provide a simple way to block cross-origin state-changing requests and on modern browsers—can serve as a primary CSRF mitigation. The main caveat is compatibility: some legacy browsers, non-browser clients and certain webviews may not send `Sec-Fetch-*` headers, so deployments should include tested fallback behavior and a careful rollout plan. + +The Fetch Metadata request headers are: + +- Sec-Fetch-Site — indicates relationship between request initiator’s origin and it's target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. +- Sec-Fetch-Mode — indicates the request's [mode](https://fetch.spec.whatwg.org/#concept-request-mode)(e.g., `navigate`, `no-cors`, `cors`, `same-origin`, and `websocket`), which allows to distinguish between requests originating from a user navigating between HTML pages, and requests to load images and other resources. +- Sec-Fetch-Dest — indicates the [destination](https://fetch.spec.whatwg.org/#concept-request-destination) for the requested resource (e.g., `document`, `image`, `script`, etc.). +- Sec-Fetch-User — present only for navigation requests initiated by user. When sent value is `?1`, meaning `true`. + +If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. + +**Ease of use** + +Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patterns](#alternative-using-a-double-submit-cookie-pattern) — which require additional client/server coordination and are easy to misimplement — Fetch Metadata checks are straightforward to implement correctly. They typically require only a small amount of server-side logic (inspect Sec-Fetch-Site, optionally refine with Sec-Fetch-Mode/Sec-Fetch-Dest) and no client changes. That simplicity reduces complexity, making the approach attractive for many applications. + +**Browser compatability** + +Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). + +If your project requires absolute, 100% client coverage, [CSRF tokens](#token-based-mitigation) remain the safest universal option. + +### How to treat Fetch Metadata headers on the server-side + +`Sec-Fetch-Site` is the most useful Fetch Metadata header for blocking CSRF-like cross-origin requests and should be the primary signal in a Fetch-Metadata-based policy. Use other Fetch Metadata headers (`Sec-Fetch-Mode`, `Sec-Fetch-Dest`, `Sec-Fetch-User`) to further refine or tailor policies to your application (for example, allowing navigate mode top-level requests or permitting specific Dest values for resource endpoints). +**Policy (high level)** + +1. If `Sec-Fetch-Site` is present: + 1.1. Treat cross-site as untrusted for state-changing actions. By default, reject non-safe methods (POST / PUT / PATCH / DELETE) when `Sec-Fetch-Site: cross-site`. + + ```JavaScript + const SAFE = new Set(['GET','HEAD','OPTIONS']); + const site = req.get('Sec-Fetch-Site'); // e.g. 'cross-site','same-site','same-origin','none' + + if (site === 'cross-site' && !SAFE.has(req.method)) { + return false; // forbid this request + } + ``` + + 1.2. Allow `same-origin`. Treat `same-site` as allowed only if your threat model trusts sibling subdomains; otherwise handle `same-site` conservatively (for example, require additional validation). + + ```JavaScript + const trustSameSite = false; // set true only if you trust sibling subdomains + + if (site === 'same-origin') { + return true; + } else if (site === 'same-site') { + // handle same-site separately so the subcondition is clearly scoped to same-site + if (!trustSameSite && !SAFE.has(req.method)) { + return false; // treat same-site as untrusted for state-changing methods + } + return true; + } + ``` + + 1.3. Allow none for user-driven top-level navigations (bookmarks, typed URLs, explicit form submits) where appropriate. + +2. If `Sec-Fetch-*` headers are absent: choose a fallback based on risk and compatibility requirements: + 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. + 2.2. Fail-open (compatibility-first): fallback to other security measure (CSRF tokens, validate Origin/Referer, and/or require additional validation). + +3. Additionall options + 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. + + ```JavaScript + if (req.get('Sec-Fetch-Mode') === 'navigate' && + req.method === 'GET' && + req.get('Sec-Fetch-Dest') !== 'object' && + req.get('Sec-Fetch-Dest') !== 'embed') { + return true; // Allow this request + } + ``` + + 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. + +### Limitations and gotchas + +- Not universal. Some older browsers, webviews, bots, and non-browser HTTP clients do not send Sec-Fetch-*. Do not assume presence on every request — implement fallbacks. +- May break legitimate cross-origin integrations. A global Sec-Fetch policy can unintentionally block legitimate CORS or third-party flows; plan explicit whitelisting. +- One limitation is that Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). This means the headers will generally be present for requests to origins whose scheme is `https`, `wss`, or `file`, and for `localhost` (hosts in the `127.0.0.0/8` or `::1/128` ranges). For the full rules and additional edge cases (the algorithm the user agent uses to decide trustworthiness), see the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy). + +### Rollout & testing recommendations + +- Include an appropriate `Vary` header, in order to ensure that caches handle the response appropriately. For example, `Vary: Accept-Encoding, Sec-Fetch-Site`. See more [Fetch Metadata specification](https://w3c.github.io/webappsec-fetch-metadata/#vary). +- Start in “log only” mode. Record requests that would be blocked and review for false positives before enforcing. This is the safest way to discover legitimate flows that need whitelisting. +- Monitor UA coverage. Track which user agents include `Sec-Fetch-*` and which don’t; ensure your fallback logic covers missing-header cases. Use metrics to decide when to enforce stricter policies. +- Document exceptions. Keep an explicit list of endpoints whitelisted for cross-origin access. + ## Disallowing simple requests When a `` tag is used to submit data, it sends a ["simple" request](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) that browsers do not designate as "to be preflighted". These "simple" requests introduce risk of CSRF because browsers permit them to be sent to any origin. If your application uses `` tags to submit data anywhere in your client, you will still need to protect them with alternate approaches described in this document such as tokens. From 3ae17e832b53a974f64629c66e03f05599f7f66d Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 2 Nov 2025 11:04:17 +0200 Subject: [PATCH 02/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md removed old Fetch Metadata section --- ..._Request_Forgery_Prevention_Cheat_Sheet.md | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 1d733f61dc..c76a0c2895 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -460,89 +460,6 @@ Cookie prefixes [are supported by all major browsers](https://developer.mozilla. See the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives) and [IETF Draft](https://tools.ietf.org/html/draft-west-cookie-prefixes-05) for further information about cookie prefixes. -### Use Fetch Metadata headers to verify nature of the request - -Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. - -It is important to note that Fetch Metadata headers should be implemented as an additional layer defense in depth concept. This attribute should not replace a CSRF tokens (or equivalent framework protections). - -The Fetch Metadata request headers are: - -- Sec-Fetch-Site — indicates relationship between request initiator’s origin and it's target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. -- Sec-Fetch-Mode — indicates the request's [mode](https://fetch.spec.whatwg.org/#concept-request-mode)(e.g., `navigate`, `no-cors`, `cors`, `same-origin`, and `websocket`), which allows to distinguish between requests originating from a user navigating between HTML pages, and requests to load images and other resources. -- Sec-Fetch-Dest — indicates the [destination](https://fetch.spec.whatwg.org/#concept-request-destination) for the requested resource (e.g., `document`, `image`, `script`, etc.). -- Sec-Fetch-User — present only for navigation requests initiated by user. When sent value is `?1`, meaning `true`. - -If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. - -Browser compatability: Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). - -#### How to treat Fetch Metadata headers on the server-side - -Sec-Fetch-Site is the most useful Fetch Metadata header for blocking CSRF-like cross-origin requests and should be the primary signal in a Fetch-Metadata-based policy. Use other Fetch Metadata headers (Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User) to further refine or tailor policies to your application (for example, allowing navigate mode top-level requests or permitting specific Dest values for resource endpoints). -**Policy (high level)** - -1. If Sec-Fetch-Site is present: - 1.1. Treat cross-site as untrusted for state-changing actions. By default, reject non-safe methods (POST / PUT / PATCH / DELETE) when `Sec-Fetch-Site: cross-site`. - - ```JavaScript - const SAFE = new Set(['GET','HEAD','OPTIONS']); - const site = req.get('Sec-Fetch-Site'); // e.g. 'cross-site','same-site','same-origin','none' - - if (site === 'cross-site' && !SAFE.has(req.method)) { - return false; // forbid this request - } - ``` - - 1.2. Allow `same-origin`. Treat `same-site` as allowed only if your threat model trusts sibling subdomains; otherwise handle `same-site` conservatively (for example, require additional validation). - - ```JavaScript - const trustSameSite = false; // set true only if you trust sibling subdomains - - if (site === 'same-origin') { - return true; - } else if (site === 'same-site') { - // handle same-site separately so the subcondition is clearly scoped to same-site - if (!trustSameSite && !SAFE.has(req.method)) { - return false; // treat same-site as untrusted for state-changing methods - } - return true; - } - ``` - - 1.3. Allow none for user-driven top-level navigations (bookmarks, typed URLs, explicit form submits) where appropriate. - -2. If Sec-Fetch-* headers are absent: choose a fallback based on risk and compatibility requirements: - 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. - 2.2. Fail-open (compatibility-first): fallback to other security measure (CSRF tokens, validate Origin/Referer, and/or require additional validation). - -3. Additionall options - 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. - - ```JavaScript - if (req.get('Sec-Fetch-Mode') === 'navigate' && - req.method === 'GET' && - req.get('Sec-Fetch-Dest') !== 'object' && - req.get('Sec-Fetch-Dest') !== 'embed') { - return true; // Allow this request - } - ``` - - 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. - -#### Limitations and gotchas - -- Not universal. Some older browsers, webviews, bots, and non-browser HTTP clients do not send Sec-Fetch-*. Do not assume presence on every request — implement fallbacks. -- May break legitimate cross-origin integrations. A global Sec-Fetch policy can unintentionally block legitimate CORS or third-party flows; plan explicit whitelisting. -- One limitation is that Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). This means the headers will generally be present for requests to origins whose scheme is `https`, `wss`, or `file`, and for `localhost` (hosts in the `127.0.0.0/8` or `::1/128` ranges). For the full rules and additional edge cases (the algorithm the user agent uses to decide trustworthiness), see the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy). - -#### Rollout & testing recommendations - -- Include an appropriate Vary header [RFC9110], in order to ensure that caches handle the response appropriately. For example, `Vary: Accept-Encoding, Sec-Fetch-Site`. See more [Fetch Metadata specification](https://w3c.github.io/webappsec-fetch-metadata/#vary). -- Start in “log only” mode. Record requests that would be blocked and review for false positives before enforcing. This is the safest way to discover legitimate flows that need whitelisting. -- Monitor UA coverage. Track which user agents include Sec-Fetch-* and which don’t; ensure your fallback logic covers missing-header cases. Use metrics to decide when to enforce stricter policies. -- Document exceptions. Keep an explicit list of endpoints whitelisted for cross-origin access. - ### User Interaction-Based CSRF Defense While all the techniques referenced here do not require any user interaction, sometimes it's easier or more appropriate to involve the user in the transaction to prevent unauthorized operations (forged via CSRF or otherwise). The following are some examples of techniques that can act as strong CSRF defense when implemented correctly. From 092090731f4422a6e2bb3ec0084cc6458218981b Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 2 Nov 2025 11:14:53 +0200 Subject: [PATCH 03/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Fix typos and markdown issues --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index c76a0c2895..7ed1647ddd 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -167,11 +167,11 @@ The Fetch Metadata request headers are: If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. -**Ease of use** +#### Ease of use Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patterns](#alternative-using-a-double-submit-cookie-pattern) — which require additional client/server coordination and are easy to misimplement — Fetch Metadata checks are straightforward to implement correctly. They typically require only a small amount of server-side logic (inspect Sec-Fetch-Site, optionally refine with Sec-Fetch-Mode/Sec-Fetch-Dest) and no client changes. That simplicity reduces complexity, making the approach attractive for many applications. -**Browser compatability** +#### Browser compatibility Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). From 0c2aa2071b7837ad4c56e5cbe308951b35377d39 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 2 Nov 2025 11:17:07 +0200 Subject: [PATCH 04/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md fix heading increment --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 7ed1647ddd..80d7e47210 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -167,11 +167,11 @@ The Fetch Metadata request headers are: If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. -#### Ease of use +### Ease of use Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patterns](#alternative-using-a-double-submit-cookie-pattern) — which require additional client/server coordination and are easy to misimplement — Fetch Metadata checks are straightforward to implement correctly. They typically require only a small amount of server-side logic (inspect Sec-Fetch-Site, optionally refine with Sec-Fetch-Mode/Sec-Fetch-Dest) and no client changes. That simplicity reduces complexity, making the approach attractive for many applications. -#### Browser compatibility +### Browser compatibility Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). From 8d1a3944403ee08d8917c78d793a105a53924d28 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sat, 8 Nov 2025 15:10:07 +0200 Subject: [PATCH 05/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Added guidance that all Fetch Metadata implementations must include a mandatory fallback to Origin/Referer verification for compatibility. Reworked browser compatibility notes and Limitations and gotchas section. Changed language to avoid undermining Fetch Metadata headers --- ...Site_Request_Forgery_Prevention_Cheat_Sheet.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 80d7e47210..e17e3c0ae6 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -15,7 +15,7 @@ In short, the following principles should be followed to defend against CSRF: - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** - **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** - **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state changing requests (requests that cause actions on the site) and validate them on the backend, or validate [Fetch Metadata headers](#fetch-metadata-headers) on the backend for all state-changing requests.** -- **If your software is intended to be used only on modern browsers, you may rely primarily on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests** +- **If your software is intended to be used only on modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)** - **Stateless software should use [double submit cookies](#alternative-using-a-double-submit-cookie-pattern)** - **If an API-driven site can't use `` tags, consider [using custom request headers](#employing-custom-request-headers-for-ajaxapi)** @@ -156,7 +156,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. -Although Fetch Metadata headers are relatively new compared to [token-based defenses](#token-based-mitigation), they provide a simple way to block cross-origin state-changing requests and on modern browsers—can serve as a primary CSRF mitigation. The main caveat is compatibility: some legacy browsers, non-browser clients and certain webviews may not send `Sec-Fetch-*` headers, so deployments should include tested fallback behavior and a careful rollout plan. +Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. The Fetch Metadata request headers are: @@ -173,9 +173,9 @@ Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patt ### Browser compatibility -Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). +Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android), with [over 97% global coverage](https://caniuse.com/mdn-http_headers_sec-fetch-site). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). -If your project requires absolute, 100% client coverage, [CSRF tokens](#token-based-mitigation) remain the safest universal option. +For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` support, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) should provide the required coverage. If this is acceptable for your project, consider prompting users to update their browsers, as they are running on outdated and potentially insecure versions. ### How to treat Fetch Metadata headers on the server-side @@ -214,7 +214,7 @@ If your project requires absolute, 100% client coverage, [CSRF tokens](#token-ba 2. If `Sec-Fetch-*` headers are absent: choose a fallback based on risk and compatibility requirements: 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. - 2.2. Fail-open (compatibility-first): fallback to other security measure (CSRF tokens, validate Origin/Referer, and/or require additional validation). + 2.2. Fail-open (compatibility-first): fallback to other security measure ([standard origin verification](#using-standard-headers-to-verify-origin), CSRF tokens, and/or require additional validation). 3. Additionall options 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. @@ -230,11 +230,10 @@ If your project requires absolute, 100% client coverage, [CSRF tokens](#token-ba 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. -### Limitations and gotchas +### Things to consider -- Not universal. Some older browsers, webviews, bots, and non-browser HTTP clients do not send Sec-Fetch-*. Do not assume presence on every request — implement fallbacks. -- May break legitimate cross-origin integrations. A global Sec-Fetch policy can unintentionally block legitimate CORS or third-party flows; plan explicit whitelisting. - One limitation is that Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). This means the headers will generally be present for requests to origins whose scheme is `https`, `wss`, or `file`, and for `localhost` (hosts in the `127.0.0.0/8` or `::1/128` ranges). For the full rules and additional edge cases (the algorithm the user agent uses to decide trustworthiness), see the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy). +- To ensure consistent inclusion of Fetch Metadata headers, enforce HTTPS across your site. Enabling [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) helps achieve this by automatically upgrading all HTTP requests to HTTPS, ensuring requests are always sent from a secure, trustworthy context. ### Rollout & testing recommendations From ae616bd03b781178fdceefb9d9b32e835a3fd921 Mon Sep 17 00:00:00 2001 From: Jim Manico Date: Mon, 10 Nov 2025 12:47:59 +0100 Subject: [PATCH 06/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Like this, go for it Co-authored-by: Ari Kalfus --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index e17e3c0ae6..6cef36d00b 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -156,7 +156,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. -Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. +Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all desktop browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers) and all mobile browsers since October 2025. The Fetch Metadata request headers are: From 8cc3255ffbd09002a3e0f5599404ad43467eaf7b Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sat, 15 Nov 2025 00:45:00 +0200 Subject: [PATCH 07/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: Ari Kalfus --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 6cef36d00b..21187c70c4 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -216,7 +216,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. 2.2. Fail-open (compatibility-first): fallback to other security measure ([standard origin verification](#using-standard-headers-to-verify-origin), CSRF tokens, and/or require additional validation). -3. Additionall options +3. Additional options 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. ```JavaScript From 8baf8d4a632ad93d197856ae26c1a3c54d931468 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:14:57 +0200 Subject: [PATCH 08/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 21187c70c4..b19f487071 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -15,7 +15,7 @@ In short, the following principles should be followed to defend against CSRF: - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** - **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** - **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state changing requests (requests that cause actions on the site) and validate them on the backend, or validate [Fetch Metadata headers](#fetch-metadata-headers) on the backend for all state-changing requests.** -- **If your software is intended to be used only on modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests** +- **If your software is intended to be used only on modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests, so long as you use the fallback options detailed below.** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)** - **Stateless software should use [double submit cookies](#alternative-using-a-double-submit-cookie-pattern)** - **If an API-driven site can't use `` tags, consider [using custom request headers](#employing-custom-request-headers-for-ajaxapi)** From 86fc26bf146381099d2640b793b45bcc0fc69e54 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:17:44 +0200 Subject: [PATCH 09/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index b19f487071..7f8c7a3742 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -156,7 +156,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. -Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all desktop browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers) and all mobile browsers since October 2025. +Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers). The Fetch Metadata request headers are: From c3579b553bbbd820ce488f5c8e732ba47affe4c5 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:18:42 +0200 Subject: [PATCH 10/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 7f8c7a3742..efac143454 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -173,7 +173,7 @@ Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patt ### Browser compatibility -Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android), with [over 97% global coverage](https://caniuse.com/mdn-http_headers_sec-fetch-site). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). +Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android), with [over 98% global coverage](https://caniuse.com/mdn-http_headers_sec-fetch-site). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` support, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) should provide the required coverage. If this is acceptable for your project, consider prompting users to update their browsers, as they are running on outdated and potentially insecure versions. From 68310fc573f4b780cdb39c8260dbcf6f7d0a4075 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:25:37 +0200 Subject: [PATCH 11/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Updated "The Fetch Metadata request headers are" part. Updated "Use Built-In Or Existing CSRF Implementations for CSRF Protection" to include reference to Go CrossOriginProtection. Updated "### Things to consider" --- ..._Request_Forgery_Prevention_Cheat_Sheet.md | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index efac143454..4369103b0c 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -26,13 +26,15 @@ In short, the following principles should be followed to defend against CSRF: - **Do not use GET requests for state changing operations.** - **If for any reason you do it, protect those resources against CSRF** -## Token-Based Mitigation +### Use Built-In Or Existing CSRF Implementations for CSRF Protection -The [synchronizer token pattern](#synchronizer-token-pattern) is one of the most popular and recommended methods to mitigate CSRF. +Before building a custom token or Fetch-Metadata implementation, check whether your framework or platform already provides CSRF protection you can use. Built-in defenses are generally preferable because they’re maintained by the framework authors and reduce the risk of subtle implementation mistakes. For example: + - .NET can use [built-in protection](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1) to add tokens to CSRF vulnerable resources. If you choose to use this protection, .NET makes you responsible for proper configuration (such as key management and token management). + - Starting from [1.25](https://pkg.go.dev/net/http@go1.25rc2), Go developers can rely on the built-in [CrossOriginProtection](https://pkg.go.dev/net/http@go1.25rc2#CrossOriginProtection) type. It implements a Fetch-Metadata-based CSRF defense (including validation of Sec-Fetch-Site and related headers) directly in the standard library. -### Use Built-In Or Existing CSRF Implementations for CSRF Protection +## Token-Based Mitigation -Since synchronizer token defenses are built into many frameworks, find out if your framework has CSRF protection available by default before you build a custom token generating system. For example, .NET can use [built-in protection](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1) to add tokens to CSRF vulnerable resources. If you choose to use this protection, .NET makes you responsible for proper configuration (such as key management and token management). +The [synchronizer token pattern](#synchronizer-token-pattern) is one of the most popular and recommended methods to mitigate CSRF. ### Synchronizer Token Pattern @@ -160,10 +162,8 @@ Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [ The Fetch Metadata request headers are: -- Sec-Fetch-Site — indicates relationship between request initiator’s origin and it's target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. -- Sec-Fetch-Mode — indicates the request's [mode](https://fetch.spec.whatwg.org/#concept-request-mode)(e.g., `navigate`, `no-cors`, `cors`, `same-origin`, and `websocket`), which allows to distinguish between requests originating from a user navigating between HTML pages, and requests to load images and other resources. -- Sec-Fetch-Dest — indicates the [destination](https://fetch.spec.whatwg.org/#concept-request-destination) for the requested resource (e.g., `document`, `image`, `script`, etc.). -- Sec-Fetch-User — present only for navigation requests initiated by user. When sent value is `?1`, meaning `true`. +- Sec-Fetch-Site — the primary signal for CSRF protection. It indicates relationship between request initiator’s origin and it's target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. +- Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User — additional headers that provide context about the request (such as the request mode, destination type, or whether it was triggered by a user navigation). More details are available in the [MDN documentation](https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header). If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. @@ -230,10 +230,11 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. -### Things to consider +### Requirements -- One limitation is that Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). This means the headers will generally be present for requests to origins whose scheme is `https`, `wss`, or `file`, and for `localhost` (hosts in the `127.0.0.0/8` or `::1/128` ranges). For the full rules and additional edge cases (the algorithm the user agent uses to decide trustworthiness), see the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy). -- To ensure consistent inclusion of Fetch Metadata headers, enforce HTTPS across your site. Enabling [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) helps achieve this by automatically upgrading all HTTP requests to HTTPS, ensuring requests are always sent from a secure, trustworthy context. +- Your application must be served over trustworthy URLs. Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). In practice, this includes `https`, `wss`, `file`, and `localhost` (including `127.0.0.0/8` and `::1/128`). See the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy) for full details. +- HTTPS must be enforced across the entire application. This ensures consistent inclusion of Fetch Metadata headers. Enabling [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) helps achieve this by automatically upgrading all HTTP requests to HTTPS. +- [Safe HTTP methods](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) must not be used for state-changing requests. ### Rollout & testing recommendations From a6d73366ab88fd7f0b4594a55a04d668c38f6e4a Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:27:52 +0200 Subject: [PATCH 12/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md fix list indentation --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 4369103b0c..5d89cda87a 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -29,8 +29,8 @@ In short, the following principles should be followed to defend against CSRF: ### Use Built-In Or Existing CSRF Implementations for CSRF Protection Before building a custom token or Fetch-Metadata implementation, check whether your framework or platform already provides CSRF protection you can use. Built-in defenses are generally preferable because they’re maintained by the framework authors and reduce the risk of subtle implementation mistakes. For example: - - .NET can use [built-in protection](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1) to add tokens to CSRF vulnerable resources. If you choose to use this protection, .NET makes you responsible for proper configuration (such as key management and token management). - - Starting from [1.25](https://pkg.go.dev/net/http@go1.25rc2), Go developers can rely on the built-in [CrossOriginProtection](https://pkg.go.dev/net/http@go1.25rc2#CrossOriginProtection) type. It implements a Fetch-Metadata-based CSRF defense (including validation of Sec-Fetch-Site and related headers) directly in the standard library. +- .NET can use [built-in protection](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1) to add tokens to CSRF vulnerable resources. If you choose to use this protection, .NET makes you responsible for proper configuration (such as key management and token management). +- Starting from [1.25](https://pkg.go.dev/net/http@go1.25rc2), Go developers can rely on the built-in [CrossOriginProtection](https://pkg.go.dev/net/http@go1.25rc2#CrossOriginProtection) type. It implements a Fetch-Metadata-based CSRF defense (including validation of Sec-Fetch-Site and related headers) directly in the standard library. ## Token-Based Mitigation From d2160554ef85013b10b2dad9de5d682f9eee6d09 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:29:49 +0200 Subject: [PATCH 13/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md --- cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 1 + 1 file changed, 1 insertion(+) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 5d89cda87a..b8715fe25f 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -29,6 +29,7 @@ In short, the following principles should be followed to defend against CSRF: ### Use Built-In Or Existing CSRF Implementations for CSRF Protection Before building a custom token or Fetch-Metadata implementation, check whether your framework or platform already provides CSRF protection you can use. Built-in defenses are generally preferable because they’re maintained by the framework authors and reduce the risk of subtle implementation mistakes. For example: + - .NET can use [built-in protection](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1) to add tokens to CSRF vulnerable resources. If you choose to use this protection, .NET makes you responsible for proper configuration (such as key management and token management). - Starting from [1.25](https://pkg.go.dev/net/http@go1.25rc2), Go developers can rely on the built-in [CrossOriginProtection](https://pkg.go.dev/net/http@go1.25rc2#CrossOriginProtection) type. It implements a Fetch-Metadata-based CSRF defense (including validation of Sec-Fetch-Site and related headers) directly in the standard library. From a6ccd2c4ca18fe2ddd3dd07b76008b65a63356d7 Mon Sep 17 00:00:00 2001 From: Jim Manico Date: Mon, 17 Nov 2025 13:53:41 -1000 Subject: [PATCH 14/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index b8715fe25f..1062433268 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -14,7 +14,7 @@ In short, the following principles should be followed to defend against CSRF: - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** - **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** -- **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state changing requests (requests that cause actions on the site) and validate them on the backend, or validate [Fetch Metadata headers](#fetch-metadata-headers) on the backend for all state-changing requests.** +- **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state-changing requests (requests that cause actions on the site) and validate them on the backend.** - **If your software is intended to be used only on modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests, so long as you use the fallback options detailed below.** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)** - **Stateless software should use [double submit cookies](#alternative-using-a-double-submit-cookie-pattern)** From ce48f47b2751d9bae206824aade49a3b79714d5e Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 18 Nov 2025 14:58:44 +0200 Subject: [PATCH 15/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Removed `Origin` and `Referer` from the ## Fetch Metadata headers description --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index edebcb0929..79be48dc7a 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -159,7 +159,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. -Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) using the `Origin` and `Referer` headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers). +Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers). The Fetch Metadata request headers are: From ed608c5ad1e0ec4d0b602846607c4bde1e68aed7 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:09:10 +0200 Subject: [PATCH 16/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md navigate mode clarification --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 79be48dc7a..e3c5d172f9 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -180,7 +180,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp ### How to treat Fetch Metadata headers on the server-side -`Sec-Fetch-Site` is the most useful Fetch Metadata header for blocking CSRF-like cross-origin requests and should be the primary signal in a Fetch-Metadata-based policy. Use other Fetch Metadata headers (`Sec-Fetch-Mode`, `Sec-Fetch-Dest`, `Sec-Fetch-User`) to further refine or tailor policies to your application (for example, allowing navigate mode top-level requests or permitting specific Dest values for resource endpoints). +`Sec-Fetch-Site` is the most useful Fetch Metadata header for blocking CSRF-like cross-origin requests and should be the primary signal in a Fetch-Metadata-based policy. Use other Fetch Metadata headers (`Sec-Fetch-Mode`, `Sec-Fetch-Dest`, `Sec-Fetch-User`) to further refine or tailor policies to your application's needs (for example, allowing top-level navigation requests or permitting specific Dest values for resource endpoints). **Policy (high level)** 1. If `Sec-Fetch-Site` is present: From 189cb719276cce61023eb94bb47cf09b4e5643a3 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 18 Nov 2025 16:56:48 +0200 Subject: [PATCH 17/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: Scott Leggett --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index e3c5d172f9..47df2a64df 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -170,7 +170,7 @@ If any of headers above contain values not listed in the specification, in order ### Ease of use -Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patterns](#alternative-using-a-double-submit-cookie-pattern) — which require additional client/server coordination and are easy to misimplement — Fetch Metadata checks are straightforward to implement correctly. They typically require only a small amount of server-side logic (inspect Sec-Fetch-Site, optionally refine with Sec-Fetch-Mode/Sec-Fetch-Dest) and no client changes. That simplicity reduces complexity, making the approach attractive for many applications. +Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patterns](#alternative-using-a-double-submit-cookie-pattern) — which require additional client/server coordination and are difficult to implement correctly — Fetch Metadata checks are much more straightforward. They typically require only a small amount of server-side logic (inspect Sec-Fetch-Site, optionally refine with Sec-Fetch-Mode/Sec-Fetch-Dest) and no client changes. That simplicity reduces complexity, making the approach attractive for many applications. ### Browser compatibility From 9813b91b79ee85909d53f558c14a05c371dd424c Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:44:27 +0200 Subject: [PATCH 18/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md state-changing safe methods requests clarification --- ..._Request_Forgery_Prevention_Cheat_Sheet.md | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 47df2a64df..4dc24fcd80 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -183,8 +183,9 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp `Sec-Fetch-Site` is the most useful Fetch Metadata header for blocking CSRF-like cross-origin requests and should be the primary signal in a Fetch-Metadata-based policy. Use other Fetch Metadata headers (`Sec-Fetch-Mode`, `Sec-Fetch-Dest`, `Sec-Fetch-User`) to further refine or tailor policies to your application's needs (for example, allowing top-level navigation requests or permitting specific Dest values for resource endpoints). **Policy (high level)** -1. If `Sec-Fetch-Site` is present: - 1.1. Treat cross-site as untrusted for state-changing actions. By default, reject non-safe methods (POST / PUT / PATCH / DELETE) when `Sec-Fetch-Site: cross-site`. +1. If `Sec-Fetch-Site` is present + + 1.1. Treat cross-site as untrusted for state-changing actions. By default, reject non-safe methods (POST / PUT / PATCH / DELETE) when `Sec-Fetch-Site: cross-site`. ```JavaScript const SAFE = new Set(['GET','HEAD','OPTIONS']); @@ -195,7 +196,30 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp } ``` - 1.2. Allow `same-origin`. Treat `same-site` as allowed only if your threat model trusts sibling subdomains; otherwise handle `same-site` conservatively (for example, require additional validation). + 1.2 If your application relies on [safe HTTP methods](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) (GET, HEAD, or OPTIONS) for state‑changing actions, you should explicitly reflect that in your policy – e.g., by requiring a Fetch‑Metadata header review for requests to those endpoints. This can be enforced with a policy rule like: + + ```JavaScript + const SAFE_METHODS = new Set(['GET','HEAD','OPTIONS']); + const SENSITIVE_ENDPOINTS = new Set([ + '/user/profile', + '/account/details', + ]); + + const site = req.get('Sec-Fetch-Site'); + const path = req.path; + + // Block if cross-site + sensitive endpoint + if (site === 'cross-site' && SENSITIVE_ENDPOINTS.has(path)) { + return false; + } + + // Block if cross-site + unsafe method + if (site === 'cross-site' && !SAFE_METHODS.has(req.method)) { + return false; + } + ``` + + 1.3. Allow `same-origin`. Treat `same-site` as allowed only if your threat model trusts sibling subdomains; otherwise handle `same-site` conservatively (for example, require additional validation). ```JavaScript const trustSameSite = false; // set true only if you trust sibling subdomains @@ -211,14 +235,15 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp } ``` - 1.3. Allow none for user-driven top-level navigations (bookmarks, typed URLs, explicit form submits) where appropriate. + 1.4. Allow none for user-driven top-level navigations (bookmarks, typed URLs, explicit form submits) where appropriate. 2. If `Sec-Fetch-*` headers are absent: choose a fallback based on risk and compatibility requirements: 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. 2.2. Fail-open (compatibility-first): fallback to other security measure ([standard origin verification](#using-standard-headers-to-verify-origin), CSRF tokens, and/or require additional validation). 3. Additional options - 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. + + 3.1 To ensure that your site can still be linked from other sites, you have to allow simple (HTTP GET) top-level navigation. ```JavaScript if (req.get('Sec-Fetch-Mode') === 'navigate' && @@ -229,7 +254,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp } ``` - 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. + 3.2 Whitelist explicit cross-origin flows. If certain endpoints intentionally accept cross-origin requests (CORS JSON APIs, third-party integrations, webhooks), explicitly exempt those endpoints from the global Sec-Fetch deny policy and secure them with proper CORS configuration, authentication, and logging. ### Requirements From f3b2ab4601cd60045dca33fa13c43ce32c1f3f74 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Wed, 19 Nov 2025 13:39:51 +0200 Subject: [PATCH 19/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Vary header clarification --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 4dc24fcd80..ce6e3bc666 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -264,7 +264,9 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp ### Rollout & testing recommendations -- Include an appropriate `Vary` header, in order to ensure that caches handle the response appropriately. For example, `Vary: Accept-Encoding, Sec-Fetch-Site`. See more [Fetch Metadata specification](https://w3c.github.io/webappsec-fetch-metadata/#vary). +- Include an appropriate `Vary` header, in order to ensure that caches handle the response appropriately. For example, `Vary: Sec-Fetch-Site, Origin`. See more [Fetch Metadata specification](https://w3c.github.io/webappsec-fetch-metadata/#vary). + - Note that the `Vary` header does not impact CSRF defenses in any way. It is a response header, so it is applied after the server has already made its allow/deny decision based on CSRF protections. Its purpose is operational rather than defensive. + - If the server responds differently based on HTTP headers (e.g., `Sec-Fetch-Site`, `Origin`), caches must vary on those headers. Without this, CDNs or proxies may reuse a response generated for a different context, causing broken behavior or contributing to cache-poisoning scenarios. Adding the appropriate `Vary` header ensures caches keep these responses separate. - Start in “log only” mode. Record requests that would be blocked and review for false positives before enforcing. This is the safest way to discover legitimate flows that need whitelisting. - Monitor UA coverage. Track which user agents include `Sec-Fetch-*` and which don’t; ensure your fallback logic covers missing-header cases. Use metrics to decide when to enforce stricter policies. - Document exceptions. Keep an explicit list of endpoints whitelisted for cross-origin access. From 1adef8aa058eb75bb5a48c3992dfc2b73cb2fe2d Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:27:21 +0200 Subject: [PATCH 20/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Added concerns section --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index ce6e3bc666..a489fc2ba3 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -262,6 +262,11 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp - HTTPS must be enforced across the entire application. This ensures consistent inclusion of Fetch Metadata headers. Enabling [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) helps achieve this by automatically upgrading all HTTP requests to HTTPS. - [Safe HTTP methods](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) must not be used for state-changing requests. +### Concerns + +- Prerender/prefetch and other [speculative navigation](https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Speculative_loading) may send `Sec-Fetch-*` values that don’t match the final navigation, and browser-initiated flows (e.g., [PaymentRequest](https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API)) could generate requests without predictable fetch-metadata headers. These behaviors are still being refined, so header propagation isn’t fully stable across all navigation types. +- Intermediaries (proxies, gateways, load balancers) can remove or modify `Origin` and `Sec-*` headers — whether due to privacy filters, network optimizations, or simple misconfiguration — which can break fetch-metadata-based protections. This kind of header stripping is a problem on its own, but it still occurs surprisingly often in large enterprise networks, healthcare, ICS environments. + ### Rollout & testing recommendations - Include an appropriate `Vary` header, in order to ensure that caches handle the response appropriately. For example, `Vary: Sec-Fetch-Site, Origin`. See more [Fetch Metadata specification](https://w3c.github.io/webappsec-fetch-metadata/#vary). From 846529508c815ef03bc6d9c3a3839e0a5466d518 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:39:11 +0200 Subject: [PATCH 21/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index a489fc2ba3..abd4889670 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -15,7 +15,7 @@ In short, the following principles should be followed to defend against CSRF: - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** - **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** - **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state-changing requests (requests that cause actions on the site) and validate them on the backend.** -- **If your software is intended to be used only on modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) to block cross-site state-changing requests, so long as you use the fallback options detailed below.** +- **If your software targets only modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) together with the fallback options described below to block cross-site state-changing requests.** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)** - **Stateless software should use [double submit cookies](#alternative-using-a-double-submit-cookie-pattern)** - **If an API-driven site can't use `` tags, consider [using custom request headers](#employing-custom-request-headers-for-ajaxapi)** From f5f08c567c6aeee0827adb78f49b8dd846c504c0 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:40:46 +0200 Subject: [PATCH 22/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index abd4889670..4a22100f8b 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -157,7 +157,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains ## Fetch Metadata headers -Fetch Metadata request headers provide extra context about how an HTTP request was made, and how the resource will be used, enabling servers to reject suspicious cross-site requests. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. +Fetch Metadata request headers provide extra information about the context from which an HTTP request was made. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers). From 278e8f2c5c10de32c31828db597556874e953164 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:42:57 +0200 Subject: [PATCH 23/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 4a22100f8b..c7b1de1cb3 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -163,7 +163,7 @@ Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [ The Fetch Metadata request headers are: -- Sec-Fetch-Site — the primary signal for CSRF protection. It indicates relationship between request initiator’s origin and it's target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. +- Sec-Fetch-Site — the primary signal for CSRF protection. It indicates the relationship between the request initiator’s origin and its target's origin: `same-origin`, `same-site`, `cross-site`, or `none`. - Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User — additional headers that provide context about the request (such as the request mode, destination type, or whether it was triggered by a user navigation). More details are available in the [MDN documentation](https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header). If any of headers above contain values not listed in the specification, in order to support forward-compatibility, servers should ignore those headers. From 8dbbbed928acf5a4e7b7f23ea3dc51ac0cf60897 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:43:45 +0200 Subject: [PATCH 24/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index c7b1de1cb3..c1a0d16108 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -188,10 +188,10 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp 1.1. Treat cross-site as untrusted for state-changing actions. By default, reject non-safe methods (POST / PUT / PATCH / DELETE) when `Sec-Fetch-Site: cross-site`. ```JavaScript - const SAFE = new Set(['GET','HEAD','OPTIONS']); + const SAFE_METHODS = new Set(['GET','HEAD','OPTIONS']); const site = req.get('Sec-Fetch-Site'); // e.g. 'cross-site','same-site','same-origin','none' - if (site === 'cross-site' && !SAFE.has(req.method)) { + if (site === 'cross-site' && !SAFE_METHODS.has(req.method)) { return false; // forbid this request } ``` From 0193cd8c11a724c8cd071d4f076b577afe664a9e Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:43:57 +0200 Subject: [PATCH 25/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index c1a0d16108..115ba1ac25 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -228,7 +228,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp return true; } else if (site === 'same-site') { // handle same-site separately so the subcondition is clearly scoped to same-site - if (!trustSameSite && !SAFE.has(req.method)) { + if (!trustSameSite && !SAFE_METHODS.has(req.method)) { return false; // treat same-site as untrusted for state-changing methods } return true; From b7071c9fe59194a7ad344f8ba0c14924334b72a0 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:44:14 +0200 Subject: [PATCH 26/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 115ba1ac25..31d76d350b 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -239,7 +239,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp 2. If `Sec-Fetch-*` headers are absent: choose a fallback based on risk and compatibility requirements: 2.1. Fail-safe (recommended for sensitive endpoints): treat absence as unknown and block the request. - 2.2. Fail-open (compatibility-first): fallback to other security measure ([standard origin verification](#using-standard-headers-to-verify-origin), CSRF tokens, and/or require additional validation). + 2.2. Fail-open (compatibility-first): fallback to ([standard origin verification](#using-standard-headers-to-verify-origin), CSRF tokens, and/or require additional validation). 3. Additional options From 7c92749c4f80aab382bf5cfa192582bc3745c093 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 14:46:21 +0200 Subject: [PATCH 27/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- ...oss-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 31d76d350b..daebbf101e 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -208,14 +208,9 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp const site = req.get('Sec-Fetch-Site'); const path = req.path; - // Block if cross-site + sensitive endpoint - if (site === 'cross-site' && SENSITIVE_ENDPOINTS.has(path)) { - return false; - } - - // Block if cross-site + unsafe method - if (site === 'cross-site' && !SAFE_METHODS.has(req.method)) { - return false; + // Block if cross-site + unsafe method OR cross-site + sensitive endpoint + if (site === 'cross-site' && (! SAFE_METHODS.has(req.method) || SENSITIVE_ENDPOINTS.has(path))) { + return false; // forbid this request } ``` From e2841e5422a11b5a30b8c8a84ccfd81c89912daa Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:01:13 +0200 Subject: [PATCH 28/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index daebbf101e..37aee88aee 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -26,7 +26,7 @@ In short, the following principles should be followed to defend against CSRF: - **Do not use GET requests for state changing operations.** - **If for any reason you do it, protect those resources against CSRF** -### Use Built-In Or Existing CSRF Implementations for CSRF Protection +### Built-In Or Existing CSRF Implementations for CSRF Protection Before building a custom token or Fetch-Metadata implementation, check whether your framework or platform already provides CSRF protection you can use. Built-in defenses are generally preferable because they’re maintained by the framework authors and reduce the risk of subtle implementation mistakes. For example: From d88c9623b2dd3cd9f2be996db9dd5704350e20bc Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:03:02 +0200 Subject: [PATCH 29/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index 37aee88aee..b534710b52 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -174,7 +174,7 @@ Unlike [synchronizer tokens](#synchronizer-token-pattern) or [double-submit patt ### Browser compatibility -Fetch Metadata request headers are supported in most modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android), with [over 98% global coverage](https://caniuse.com/mdn-http_headers_sec-fetch-site). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). +Fetch Metadata request headers are supported in all modern browsers on both desktop and mobile (Chrome, Edge, Firefox, Safari 16.4+, and even in webviews on both iOS and Android), with [over 98% global coverage](https://caniuse.com/mdn-http_headers_sec-fetch-site). For compatibility detail, see the [browser support table](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#browser_compatibility). For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` support, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) should provide the required coverage. If this is acceptable for your project, consider prompting users to update their browsers, as they are running on outdated and potentially insecure versions. From e5a586ebb1f73fe43b439ced8ad2237cb72853e9 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:03:59 +0200 Subject: [PATCH 30/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index b534710b52..ae246dc224 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -260,7 +260,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp ### Concerns - Prerender/prefetch and other [speculative navigation](https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Speculative_loading) may send `Sec-Fetch-*` values that don’t match the final navigation, and browser-initiated flows (e.g., [PaymentRequest](https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API)) could generate requests without predictable fetch-metadata headers. These behaviors are still being refined, so header propagation isn’t fully stable across all navigation types. -- Intermediaries (proxies, gateways, load balancers) can remove or modify `Origin` and `Sec-*` headers — whether due to privacy filters, network optimizations, or simple misconfiguration — which can break fetch-metadata-based protections. This kind of header stripping is a problem on its own, but it still occurs surprisingly often in large enterprise networks, healthcare, ICS environments. +- Intermediaries (proxies, gateways, load balancers) may remove or modify `Origin` and `Sec-*` headers — whether due to privacy filters, network optimizations, or simple misconfiguration — which can break fetch-metadata-based protections. This kind of header stripping is problematic, but common. ### Rollout & testing recommendations From 2c6dbfa658e3b8012e78325e63e2d4b30addc831 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:07:34 +0200 Subject: [PATCH 31/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index ae246dc224..d4bcddd2f4 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -255,7 +255,7 @@ For the rare cases of outdated or embedded browsers that lack `Sec-Fetch-*` supp - Your application must be served over trustworthy URLs. Fetch Metadata request headers are only sent to [potentially trustworthy URLs](https://www.w3.org/TR/secure-contexts/#is-url-trustworthy). In practice, this includes `https`, `wss`, `file`, and `localhost` (including `127.0.0.0/8` and `::1/128`). See the [W3C Secure Contexts spec](https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy) for full details. - HTTPS must be enforced across the entire application. This ensures consistent inclusion of Fetch Metadata headers. Enabling [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security) helps achieve this by automatically upgrading all HTTP requests to HTTPS. -- [Safe HTTP methods](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) must not be used for state-changing requests. +- [Safe HTTP methods](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) should not be used for state-changing requests. ### Concerns From 6c81728895e360c45f8ea0dacb6cd5aeb0a10beb Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:13:51 +0200 Subject: [PATCH 32/33] Update cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md Co-authored-by: nickchomey <88559987+nickchomey@users.noreply.github.com> --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index d4bcddd2f4..a936e19f89 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -159,7 +159,7 @@ Though the Naive Double-Submit Cookie method is simple and scalable, it remains Fetch Metadata request headers provide extra information about the context from which an HTTP request was made. Servers can use these headers — most importantly `Sec-Fetch-Site` — as a lightweight and reliable method to block obvious cross-site requests. See the [Fetch Metadata specification](https://www.w3.org/TR/fetch-metadata/) for details. -Because some legacy browsers may not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/?search=sec-fetch-site) in all browsers since March 2023 (with the exception of IE as it no longer receives updates and does not support `Sec-Fetch-*` headers). +Because some legacy browsers do not send `Sec-Fetch-*` headers, a fallback to [standard origin verification](#using-standard-headers-to-verify-origin) headers **is a mandatory requirement** for any Fetch Metadata implementation. `Sec-Fetch-*` [is supported](https://caniuse.com/mdn-http_headers_sec-fetch-site) in all major browsers since March 2023. The Fetch Metadata request headers are: From 17e5789c9c40847a521855b2baa9367d3155cfd2 Mon Sep 17 00:00:00 2001 From: mkhanas <87975887+mkhanas@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:15:04 +0200 Subject: [PATCH 33/33] Update Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md --- .../Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md index a936e19f89..9cda71b849 100644 --- a/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md +++ b/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md @@ -13,7 +13,7 @@ In short, the following principles should be followed to defend against CSRF: **IMPORTANT: Remember that Cross-Site Scripting (XSS) can defeat all CSRF mitigation techniques!** While Cross-Site Scripting (XSS) vulnerabilities can bypass CSRF protections, CSRF tokens are still essential for web applications that rely on cookies for authentication. Consider the client and authentication method to determine the best approach for CSRF protection in your application. - **See the OWASP [XSS Prevention Cheat Sheet](Cross_Site_Scripting_Prevention_Cheat_Sheet.md) for detailed guidance on how to prevent XSS flaws.** -- **First, check if your framework has [built-in CSRF protection](#use-built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** +- **First, check if your framework has [built-in CSRF protection](#built-in-or-existing-csrf-implementations-for-csrf-protection) and use it** - **If the framework does not have built-in CSRF protection, add [CSRF tokens](#token-based-mitigation) to all state-changing requests (requests that cause actions on the site) and validate them on the backend.** - **If your software targets only modern browsers, you may rely on [Fetch Metadata headers](#fetch-metadata-headers) together with the fallback options described below to block cross-site state-changing requests.** - **Stateful software should use the [synchronizer token pattern](#synchronizer-token-pattern)**