Script Valley
Web Security Fundamentals for Developers
The Attacker's Mindset and HTTP Security BasicsLesson 1.4

CORS explained: what it prevents and what it does not

same-origin policy, CORS preflight, Access-Control headers, wildcard origin, credentials mode, CORS misconfiguration

Cross-Origin Resource Sharing (CORS)

CORS same-origin policy diagram

CORS is a browser-enforced mechanism that controls which origins can read responses from your API. It is not a server-side access control—it only restricts what browser JavaScript can do. A server-side tool like curl ignores CORS entirely.

The Same-Origin Policy

By default, a browser blocks JavaScript on https://evil.com from reading responses from https://yourapi.com. This is the Same-Origin Policy (SOP). CORS is how you selectively relax SOP for trusted origins.

Preflight Requests

For non-simple requests (DELETE, PUT, or requests with custom headers), the browser sends an HTTP OPTIONS preflight first. Your server must respond with the correct Access-Control-Allow-* headers before the browser sends the actual request.

Safe CORS Configuration in Express

const cors = require('cors');

// Only allow your production frontend
app.use(cors({
  origin: 'https://yourdomain.com',
  credentials: true,  // Required for cookies/auth headers
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

Critical Mistakes to Avoid

Never use origin: '*' with credentials: true. Browsers reject this combination, but developers sometimes try to work around it by dynamically reflecting the request's Origin header—which allows any origin to read credentialed responses, defeating authentication entirely.

Validate the incoming Origin header against an explicit allowlist. Do not use regex patterns that can be bypassed with crafted domain names like evil-yourapi.com.

Up next

How to read and understand a security vulnerability report (CVE)

Sign in to track progress