I’ve heard developers say “I need to add CORS to my API for security” more times than I can count. That’s backwards. CORS doesn’t make your API more secure. In fact, it makes it less restricted. The security feature is the Same-Origin Policy. CORS is the controlled exception.
Let me clear this up once and for all.
Same-Origin Policy (SOP)#
The Same-Origin Policy is a built-in browser security mechanism. It’s been around since the early days of the web. Here’s what it does:
It prevents a web page from reading responses to cross-origin requests.
An “origin” is protocol + hostname + port. https://example.com and https://api.example.com are different origins. https://example.com and http://example.com are different origins.
What SOP Actually Restricts#
SOP restricts reading cross-origin responses. It does NOT restrict sending requests.
// This request IS sent to the server. The server processes it.
// But the browser blocks the RESPONSE from being read by JavaScript.
fetch('https://bank.com/api/transfer', {
method: 'POST',
body: JSON.stringify({ to: 'attacker', amount: 10000 })
});The request goes through. If the server doesn’t have its own authentication, the transfer might even succeed. But the browser won’t let the attacker’s JavaScript read the response. This is a subtle but important distinction.
What SOP Does NOT Restrict#
Several things bypass SOP entirely:
<script>tags loading external JavaScript<img>tags loading external images<link>tags loading stylesheets<iframe>tags embedding pages (though the parent can’t access the iframe’s DOM)- Form submissions to other origins
- CSS background-images, @font-face, etc.
These are allowed because the web was built on the assumption that these resources are “safe” to load (they can’t execute code in the loading page’s context).
CORS (Cross-Origin Resource Sharing)#
CORS is the mechanism that lets a server say, “Yes, I explicitly allow this other origin to read my responses.”
Without CORS: The browser blocks all cross-origin response reads. With CORS: The browser allows cross-origin response reads IF the server sends the right headers.
CORS is not a security feature. It’s a way to selectively relax the Same-Origin Policy. The relaxation is controlled by the server, which makes it safe — a malicious website can’t bypass SOP on its own.
The Relationship#
| Same-Origin Policy | CORS | |
|---|---|---|
| What is it? | Browser restriction | Server-controlled exception |
| Default behavior | Blocks cross-origin | Blocks cross-origin |
| Purpose | Protect users | Enable legitimate cross-origin access |
| Where configured | Nowhere (built-in) | Server headers |
| Can you disable it? | No | Server can allow all |
Think of it like a locked door (SOP) with a keycard system (CORS). The door is always locked. CORS is you giving specific people keycards.
Common Misconceptions#
“CORS protects my API”#
No. CORS protects users. Specifically, it prevents malicious websites from reading API responses using the logged-in user’s browser session.
Your API needs its own protection: authentication, authorization, rate limiting, etc. CORS doesn’t replace any of that.
“Disabling CORS makes my API insecure”#
It makes your API more accessible from browsers, which could be a problem if your API exposes sensitive data without proper authentication. But CORS doesn’t add any security — it removes it selectively.
“I need to configure CORS on the client”#
CORS headers are ALWAYS set by the server. The client (React, Angular, etc.) has no control over CORS. If you’re adding CORS headers to your fetch calls, you’re doing it wrong.
“CORS prevents DDoS attacks”#
No. CORS doesn’t prevent any type of attack on your server. It only controls browser behavior.
“Server-to-server requests are affected by CORS”#
No. CORS is a browser feature. If you make a request from Node.js, Python, or any server-side code, CORS doesn’t apply. The request goes through regardless.
When CORS Matters#
You need CORS when:
- Your frontend is at
app.example.comand your API is atapi.example.com - Your SPA makes requests to a third-party API
- You’re loading fonts or other resources from a CDN
- You’re embedding content from another origin
You DON’T need CORS when:
- Everything is on the same domain (same origin)
- Server-to-server communication
- Mobile app → API (no browser involved)
- Desktop app → API (no browser involved)