Login
ChallengesLearn
Scoreboard
Teams
Profile

Preferences

Truesapiens

LearnWEB ProtocolsCORS & Same-Origin Policy
WEB Protocols·Lesson 6 of 8

CORS & Same-Origin Policy

The same-origin policy, cross-origin requests, simple vs preflight requests, CORS headers (Access-Control-Allow-Origin, -Methods, -Credentials), and common CORS misconfigurations.

Intermediate14 min
CORSSOPSecurity
Loading lesson…
PreviousCDN & CachingNextWebSockets & Real-Time

© 2026 Truesapiens.

Terms of ServicePrivacy PolicyCookie Policy

The Same-Origin Policy (SOP) is the browser's most fundamental security boundary. It prevents a page loaded from one origin from reading the response of a request sent to a different origin. Cross-Origin Resource Sharing (CORS) provides a controlled way to relax this restriction, but getting it wrong is one of the most common API security vulnerabilities on the web.

What you'll be able to do
  • Explain what the Same-Origin Policy protects against and how it differs from Cross-Origin Resource Sharing.
  • Distinguish simple requests from preflight requests and describe when each is used.
  • Interpret the key CORS response headers and explain how they control cross-origin access.
  • Identify dangerous CORS misconfigurations and explain how they can be exploited.
Key terms
Same-Origin Policy
A browser security mechanism that restricts how a document or script loaded from one origin can interact with resources from another origin.
Preflight request
An OPTIONS request sent by the browser before a non-simple cross-origin request to determine whether the actual request is permitted.
Access-Control-Allow-Origin
The CORS response header that specifies which origins are permitted to read the response. Can be a single origin, a wildcard (*), or null.
Simple request
A cross-origin request that uses GET, POST, or HEAD with only standard headers, triggering no preflight.
What is it?

Same-Origin Policy and CORS

The Same-Origin Policy (SOP) dictates that a web browser may only allow a script from origin A to read the response of a request sent to origin A. Two URLs share the same origin only if they have the same scheme (http/https), host, and port. For example, https://api.example.com and https://www.example.com are different origins because their hosts differ.

SOP does not block the sending of cross-origin requests - it blocks the reading of the response. A page on https://evil.com can issue a POST request to https://bank.com/api/transfer, but it cannot read the response to extract an anti-CSRF token or confirmation message. This is what prevents most cross-site request forgery (CSRF) data exfiltration.

Cross-Origin Resource Sharing (CORS) is a mechanism that allows servers to selectively relax the SOP. The server includes specific HTTP headers in its response that tell the browser which origins are allowed to read the response. The core header is Access-Control-Allow-Origin (ACAO), which can be set to a specific origin, a wildcard (*), or null.

httpCORS response headers
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: X-Request-Id

For simple requests - GET, POST, or HEAD with only standard headers (Accept, Accept-Language, Content-Language, Content-Type with values application/x-www-form-urlencoded, multipart/form-data, or text/plain) - the browser sends the cross-origin request directly and checks the response headers. For non-simple requests (PUT, DELETE, custom headers like Authorization, or Content-Type application/json), the browser first sends a preflight OPTIONS request to check if the server permits the actual request.

httppreflight flow
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: https://myapp.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Authorization

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400

The Access-Control-Allow-Credentials header controls whether cookies and authorisation headers may be included in cross-origin requests. When set to true, the ACAO header must specify a concrete origin - the wildcard * is not allowed. The Vary: Origin header should be included on CORS responses to ensure CDNs cache the correct variant per requesting origin.

CORS request flow
Mini Map
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Try it

CORS playground

Use the simulator below to explore how different CORS configurations affect cross-origin requests. Configure the request method, headers, and server settings to see preflight requests and browser CORS errors in action.

devhttps://myapp.com
CORS Playground
Web Page
API ServerACL config
ACAO: https://myapp.com ACM: GET, POST ACH: Content-Type ACC: false Vary: Origin
Ready
Configure the request and click Send Request to test CORS behaviour
Key insight
  • Simple requests (GET/POST with standard content types) skip preflight. Custom headers like x-custom-token trigger an OPTIONS preflight.
  • The Access-Control-Allow-Origin header must match the requesting origin exactly when credentials: include is used.
  • Reflecting the Origin header allows any site to read the response - never do this in production.
  • Using null as ACAO is dangerous: sandboxed iframes and data: URLs use null as their origin.
Real-world relevance

Why CORS matters in practice

Every modern web application loads resources from multiple origins: the main application from app.example.com, the API from api.example.com, images from a CDN, analytics from a third-party service, and fonts from Google Fonts. Getting CORS right is essential for all of these cross-origin interactions to work securely.

CORS misconfigurations are consistently ranked among the top API security vulnerabilities. The most common dangerous patterns include: reflecting the Origin header directly in ACAO (trusting any origin), using ACAO: * with credentials, setting ACAO to null (which can be exploited from sandboxed documents), and omitting the Vary: Origin header which can cause CDNs to serve CORS responses meant for one origin to another.

Mitigation

Safe CORS configuration

To configure CORS safely, start from a deny-by-default position. Never reflect the Origin request header in the ACAO response header - this effectively disables the Same-Origin Policy for any site. Instead, maintain a whitelist of allowed origins on the server and compare the incoming Origin against it.

If credentials are required (cookies or client certificates), never use Access-Control-Allow-Origin: *. Always specify the concrete origin and set Access-Control-Allow-Credentials: true. Include the Vary: Origin header so that CDNs and browsers cache the correct CORS response for each requesting origin. Limit Access-Control-Allow-Methods and Access-Control-Allow-Headers to only what the API actually needs. Use a short Access-Control-Max-Age (or omit it) to prevent stale preflight responses from being cached too long.

httpsafe vs dangerous CORS
# Safe: specific origin with credentials
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Credentials: true
Vary: Origin

# Dangerous: reflecting the request origin
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true
# Now evil.com can read authenticated responses
Key takeaways

What to remember

  • The Same-Origin Policy prevents a page from reading responses from a different origin. CORS is the opt-in mechanism to relax this restriction.
  • Simple requests (GET/POST/HEAD with standard content types) skip preflight; all others trigger an OPTIONS preflight request.
  • Never reflect the Origin header in Access-Control-Allow-Origin - this allows any site to read the response.
  • The wildcard ACAO: * is incompatible with credentialed requests. When Allow-Credentials is true, the ACAO must specify a concrete origin and the Vary: Origin header must be set.
Further reading
  • CORS - MDN Web Docs(MDN)
  • Same-Origin Policy - MDN Web Docs(MDN)
  • OWASP CORS Misconfiguration(OWASP)

Knowledge check

0/3 answered · 0 correct
  1. 1.What does the Same-Origin Policy prevent?

  2. 2.When does a browser send a preflight OPTIONS request?

  3. 3.What is the danger of reflecting the Origin header in Access-Control-Allow-Origin?