Web Protocols & Security Architecture Research
What is CORS?
By default, web browsers apply the Same-Origin Policy (SOP) to isolate documents and prevent malicious websites from reading sensitive data. Under SOP, client-side scripts running on https://app.curious-techie.com cannot read responses fetched from https://api.curious-techie.com unless the destination server explicitly enables CORS.
Two URLs share the same origin if and only if their Protocol (Scheme), Host (Domain), and Port are strictly identical:
https://api.example.com:443 vs https://example.com:443CROSS-ORIGIN (Subdomain mismatch)http://example.com:80 vs https://example.com:443CROSS-ORIGIN (Protocol mismatch)https://example.com/app vs https://example.com/apiSAME-ORIGIN (Path differences allowed)Key Facts: Cross-Origin Resource Sharing (CORS)
- CORS is enforced exclusively by client web browsers, not by server firewalls, command-line utilities, or backend scripts.
- A web origin consists strictly of three components: URI Scheme (protocol), Host (domain name or IP), and Port number.
- Two URLs are cross-origin if scheme, host, or port differ, even if they share the exact same top-level domain.
- Non-simple HTTP requests trigger an automatic preflight HTTP OPTIONS probe before the browser transmits the actual payload.
- The Fetch Standard explicitly forbids the wildcard Access-Control-Allow-Origin: * when Access-Control-Allow-Credentials: true is set.
- CORS does not prevent an HTTP request from hitting an API server; CORS prevents the web browser from releasing the response body to untrusted JavaScript.
How CORS Relates to Other Entities
CORS acts as a standardized, server-controlled exception mechanism to the browser default Same-Origin Policy.
The Access-Control-Allow-Origin HTTP response header dictates which requesting origins are permitted to read the response payload.
Browsers send an automated HTTP OPTIONS preflight request to verify server authorization before executing mutating methods (PUT, DELETE) or sending custom headers.
Client-side network requests initiated through window.fetch() or XMLHttpRequest are subject to browser CORS validation.
Why does CORS exist?
In the early web, client-side JavaScript was restricted entirely to contacting the exact server that delivered the HTML page. As software architecture evolved toward decoupled architectures (microservices, cloud API gateways, and external SaaS providers), modern applications required a standardized protocol to authorize legitimate cross-domain data sharing.
Without CORS, browsers would either have to block all cross-domain API integrations (crippling modern web apps) or disable origin checks completely (leaving users vulnerable to malicious websites executing authenticated calls against internal company intranets or banking dashboards).
How does CORS work?
Origin request header; the destination server evaluates this origin and returns corresponding Access-Control-* headers indicating whether the browser is permitted to share the response with the script.The conversation relies on specific standardized HTTP response headers:
Access-Control-Allow-Origin:Specifies allowed requesting origins (e.g.https://curious-techie.comor*).Access-Control-Allow-Methods:Lists permitted HTTP methods (e.g.GET, POST, PUT, DELETE, OPTIONS).Access-Control-Allow-Headers:Declares acceptable custom request headers (e.g.Content-Type, Authorization).Access-Control-Allow-Credentials:Tells the browser whether cookies and HTTP authorization headers may be exposed to JavaScript (requires explicittrue).Access-Control-Max-Age:Defines the duration in seconds that the browser may cache preflight verification results.
What is a preflight request?
OPTIONS probe dispatched by the browser before sending a "non-simple" cross-origin request (such as PUT, DELETE, or any request carrying custom headers like Authorization or JSON bodies) to verify whether the server authorizes the operation before actual payload transmission.A request is categorized as a "Simple Request" and bypasses preflight only if it meets strict criteria:
- It uses only
GET,POST, orHEADmethods. - Its headers contain only browser-standard safe headers (
Accept,Accept-Language,Content-Language). - Its
Content-Typeis strictly limited toapplication/x-www-form-urlencoded,multipart/form-data, ortext/plain.
Any modern REST or GraphQL API request carrying Content-Type: application/json or a bearer token header triggers an OPTIONS preflight. If the server does not handle HTTP OPTIONS with 200/204 status and valid CORS headers, the browser immediately blocks the main request.
How do you fix a CORS error?
Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers headers for both preflight OPTIONS and substantive API requests, or by routing frontend traffic through a same-origin reverse proxy during development.import express from 'express';
import cors from 'cors';
const app = express();
// Whitelist of approved origins
const allowedOrigins = [
'https://curious-techie.com',
'https://app.curious-techie.com',
'http://localhost:3000' // Local development
];
app.use(cors({
origin: (origin, callback) => {
// Allow non-browser requests (e.g. mobile apps, cURL, server-to-server)
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Cross-Origin Request Blocked by CORS Policy'));
}
},
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
credentials: true, // Allow cookies and authorization headers
maxAge: 86400 // Cache preflight OPTIONS responses for 24 hours
}));
// Handle preflight explicitly across all routes
app.options('*', cors());Client-Side Fetch Invocation:
const response = await fetch('https://api.curious-techie.com/v1/user/profile', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + authToken
},
credentials: 'include' // Required when exchanging cookies across origins
});Can CORS protect an API?
A server's API endpoints must always be defended by real security controls: authentication tokens (JWTs, session IDs), cryptographic signature verification, rate limiting, and input sanitization.
Relying on CORS as a security firewall is dangerous because any adversary can forge the Origin header using tools like cURL or Node.js scripts:
curl -H "Origin: https://evil.com" -H "Authorization: Bearer token" https://api.curious-techie.com/v1/dataWhat are common misconceptions about CORS?
"CORS prevents attackers from querying our backend database."
Technical Reality: CORS only prevents web browsers from giving the response payload back to JavaScript. Attackers using bots or command line tools can still query unprotected endpoints freely.
"Setting Access-Control-Allow-Origin: * allows credentialed login calls from anywhere."
Technical Reality: The WHATWG Fetch Standard explicitly forbids * when Access-Control-Allow-Credentials: true is present. The browser will deliberately reject the response.
"I can resolve this CORS error by adding headers to my frontend fetch() call."
Technical Reality: Adding custom headers in frontend JavaScript often makes the problem worse by triggering preflight requests. CORS headers must be returned by the server, not the client.
"If the browser throws a CORS error, the server never received or processed the request."
Technical Reality: For simple GET/POST requests that bypass preflight, the server processes the request and executes mutations; the browser merely blocks JavaScript from reading the response.
Frequently Asked Questions About CORS
Q:Why do I see a CORS error in my browser console but the request works in Postman?
The server usually returns HTTP 200 OK to both tools, but Chrome or Firefox checks for Access-Control-Allow-Origin and hides the response from JavaScript when that header is missing.
Q:How can I test an API locally during development without configuring CORS on staging?
/api/* requests to the target server, turning cross-origin browser calls into same-origin requests.Because the browser connects to localhost:3000/api, no cross-origin boundary is crossed and no CORS headers are required.
Q:What is the difference between CORS and CSRF?
CORS does not stop simple POST requests from reaching the server, which is why CSRF tokens or SameSite=Lax cookies remain essential for state-changing endpoints.
References & Primary Sources
Every source below directly substantiates technical statements and protocol behaviors explained in CORS (Cross-Origin Resource Sharing). Curious-Techie prioritizes official Internet standards (IETF RFCs, W3C Recommendations, WHATWG specifications) and established security bodies (OWASP, NIST). Zero sponsored or secondary links.
- [1]WHATWGPrimary SpecificationWHATWG Fetch • § 3.2 HTTP-network-fetchVerified Primary SourceTechnical Claim Supported:
Defines the normative browser CORS protocol, preflight cache validation (Access-Control-Max-Age), and the prohibition of wildcard Access-Control-Allow-Origin: * when Access-Control-Allow-Credentials is true.
“For a CORS request with credentials, the server cannot specify a wildcard for Access-Control-Allow-Origin. It must specify an explicit origin.” - [2]IETFPrimary SpecificationRFC 9110 • § 9.2.1Verified Primary SourceTechnical Claim Supported:
Specifies that the Origin request header indicates the scheme, host, and port of the originating context and must not be altered by user-agent JavaScript.
- [3]OWASPAuthoritative Security StandardOWASP Cheat Sheet Series • Origin Validation & CredentialsVerified Primary SourceTechnical Claim Supported:
Documents the security risks of dynamic origin reflection without strict server-side allowlist verification (CORS misconfiguration vulnerabilities).
- [4]MDNDeveloper Authority (MDN)MDN Web Docs • CORS Preflight & Simple RequestsVerified Primary SourceTechnical Claim Supported:
Provides developer reference for simple requests vs. preflighted requests and safelisted headers (Accept, Accept-Language, Content-Language, Content-Type).