I'm diving into how to prevent Cross-Site Request Forgery (CSRF) and came across some advice from Mozilla on implementing several protective measures:
1. Block cross-origin requests using the `Sec-Fetch-Site` header when present, and alternatively check the `Origin` or `Referer` headers to confirm they match the target site.
2. Disallow simple requests.
3. Use a CSRF token.
Given I have the first two measures in place for a web application, I'm curious why I would still need a CSRF token. OWASP suggests that the first two options aren't sufficient on their own as replacements for a CSRF token. What kind of vulnerabilities does a CSRF token help prevent that the other checks don't cover?
5 Answers
Some argue that just one of the three measures is enough, especially since the `Origin` and `Sec-Fetch-Site` headers are enforced by browsers. However, with the possibility of older browsers not implementing them correctly, a CSRF token acts as an additional fail-safe and aligns with a zero-trust approach.
It's worth mentioning that CSRF tokens are particularly important if your app uses cookies. If you can avoid cookies entirely, you might manage without them, but otherwise, tokens are advisable for secure interactions.
You have to consider the possibility that not all browsers will correctly send those headers. Relying solely on them puts you at risk. With a CSRF token, you're not putting your trust in something you don’t control; you know for sure that the request came from your site. Plus, the OWASP warns about scenarios where headers might not be reliable—adding tokens gives you better control over your app’s security.
That makes sense, thanks for explaining it!
Just remember that blocking simple requests should include strict checks on the `Content-Type` header since certain content can still pass through as simple requests due to how they're defined.
The problem with just relying on headers is that they can be manipulated or left out entirely. A CSRF token provides definite evidence that a request originated from your site, making it a trusted source.
But aren't those headers protected? Which browsers fail to send them?

I see your point. It's better to be safe than sorry!