CORS vs CSRF, What's the Actual Difference
CORS and CSRF get confused constantly because they both involve cross-origin requests and both show up in the same part of the stack — but they solve completely different problems. CORS is a browser mechanism that controls what a script is allowed to read; CSRF is an attack that doesn't need to read anything at all.
The Confusion
Developers often assume that enabling CORS correctly also protects against CSRF, or that a strict CORS policy alone is "enough" security for an API. Neither is true, and treating them as interchangeable leads to APIs that are technically CORS-compliant but still vulnerable to CSRF, or unnecessary CORS restrictions applied in an attempt to solve a problem CORS was never designed to solve.
What CORS Actually Does
CORS (Cross-Origin Resource Sharing) is a browser security feature that controls whether JavaScript running on one origin is allowed to read the response of a request made to a different origin. By default, browsers block this under the Same-Origin Policy; CORS headers from the server explicitly relax that restriction for specific origins:
Access-Control-Allow-Origin: https://trusted-app.com
Critically, CORS does not prevent the request itself from being sent — the request still reaches your server and can still have side effects (like creating a database record) even without a matching CORS header. What CORS blocks is the browser letting the malicious page's JavaScript read the response. If the attacker's script doesn't need to read the response — just needs the request to happen — CORS provides no protection at all.
What CSRF Actually Is
CSRF (Cross-Site Request Forgery) is an attack where a malicious site tricks a victim's browser into sending a request to a different site where the victim is already authenticated, relying on the browser automatically attaching stored cookies to that request. The attacker doesn't need to see the response — they just need the request to execute with the victim's credentials, for example:
<img src="https://bank.com/transfer?to=attacker&amount=1000">
If the victim is logged into bank.com in the same browser, their session cookie gets sent automatically with this request, regardless of what page the request originated from. This is precisely the scenario where CORS offers zero protection: the attacker never needed to read the response, only to trigger the action.
How They Actually Relate
Both mechanisms deal with cross-origin requests, which is where the confusion comes from, but they protect against different things:
- CORS protects the confidentiality of a response — stopping untrusted scripts from reading data they shouldn't see
- CSRF protection defends against unauthorized actions being performed using a victim's existing authentication, regardless of whether the attacker ever sees a response
- A permissive CORS policy doesn't create a CSRF vulnerability by itself, but it can make an existing CSRF vulnerability more dangerous by allowing the attacker's script to also read the result
- Correctly configuring CORS says nothing about whether your endpoints are protected against CSRF — these require separate, deliberate defenses
The Actual Fix: Defend Against Each Separately
For CORS, only allow origins you actually trust, and avoid using a wildcard (*) alongside credentialed requests, since browsers block that combination for good reason:
Access-Control-Allow-Origin: https://trusted-app.com
Access-Control-Allow-Credentials: true
For CSRF, the standard modern defense is the SameSite cookie attribute, which prevents cookies from being sent along with cross-site requests in the first place:
Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly
SameSite=Strict or SameSite=Lax stops the browser from attaching the cookie to requests originating from other sites, which directly addresses the CSRF attack pattern regardless of what your CORS configuration allows. For additional defense in depth, especially for state-changing requests, a CSRF token embedded in forms or headers and validated server-side remains a reliable, well-understood pattern that doesn't depend on cookie behavior alone.
Still Confused?
A useful mental shortcut: CORS is about what a script is allowed to read; CSRF is about what a browser will automatically send. If your threat model involves an attacker who only needs an action to happen — not to see the result — assume CORS provides no protection at all, and rely on SameSite cookies and CSRF tokens instead.