Security Glossary

Cross-Origin Resource Sharing (CORS)

CORS is an HTTP header-based mechanism that allows servers to indicate which origins are permitted to read their responses, providing a controlled way to relax the same-origin policy for legitimate cross-origin requests.

Understanding Cross-Origin Resource Sharing (CORS)

CORS is not a security barrier — it is a controlled gate in the same-origin policy. When a browser makes a cross-origin request, the server's CORS headers tell the browser whether to allow the requesting page to read the response. Without appropriate CORS headers, the browser blocks the response from being accessible to JavaScript, even though the request itself was sent and processed by the server.

The CORS handshake has two paths. Simple requests (GET, POST with standard content types, limited headers) are sent directly with an Origin header. The browser checks the response's Access-Control-Allow-Origin header before making the response available to JavaScript. Preflighted requests (custom headers, PUT/DELETE methods, non-standard content types) trigger an OPTIONS request first, where the browser negotiates allowed methods and headers before sending the actual request.

Credentialed requests add complexity. When the frontend sends cookies or Authorization headers with a cross-origin request (credentials: 'include'), the server must respond with Access-Control-Allow-Credentials: true and a specific origin (not the * wildcard). This combination ensures that cross-origin credential sharing is explicit and limited to trusted origins.

The most dangerous misconfiguration is reflecting the Origin header without validation. Some servers read the request's Origin header and echo it back in Access-Control-Allow-Origin, effectively allowing any domain to access the API. Combined with Access-Control-Allow-Credentials: true, this enables any website to make authenticated requests and read responses — a complete bypass of the same-origin policy.

Why This Matters for Vibe-Coded Apps

CORS issues are the most common development blocker for vibe coders, and the AI-generated fix is almost always too permissive. When the frontend cannot reach the backend, developers ask the AI to fix it, and the AI adds Access-Control-Allow-Origin: * or reflects any origin. This works in development but creates security risks in production.

For vibe-coded apps with separate frontend and backend origins: configure CORS to allow only your frontend's production domain. In development, allow localhost origins. Use your CORS middleware's origin array feature to support both. If your frontend and backend are on the same origin (e.g., Next.js API routes), you do not need CORS at all.

Real-World Examples

Misconfigured Cryptocurrency Exchange API

A major cryptocurrency exchange reflected the Origin header in its CORS response while allowing credentials. Any website could make authenticated requests to the exchange's API on behalf of logged-in users, potentially reading account balances, transaction history, and placing trades.

CORS Misconfiguration in Bug Bounty Programs

CORS misconfigurations are one of the most commonly reported vulnerability classes in bug bounty programs. Researchers routinely find APIs that reflect origins, use null origin bypass, or allow credentials with wildcard origins, demonstrating how widespread these misconfigurations are even in mature organizations.

NPM Registry CORS for Public Packages

The npm registry intentionally uses permissive CORS (Access-Control-Allow-Origin: *) for its public package data API. This is a correct use of wildcard CORS — the data is intentionally public, no credentials are involved, and restricting origins would break npm tooling. This demonstrates when wildcard CORS is appropriate.

Frequently Asked Questions

Why does my CORS configuration work in Postman but not the browser?

CORS is exclusively a browser security mechanism. Postman, curl, and server-to-server requests do not enforce the same-origin policy, so they never check CORS headers. When your API call works in Postman but fails in the browser, it confirms CORS headers are missing or incorrect on the API response. The browser is blocking your JavaScript from reading the response, not blocking the request itself.

How do I handle CORS with cookie-based authentication?

Your API must set Access-Control-Allow-Credentials: true and specify the exact origin (not *) in Access-Control-Allow-Origin. Your frontend must include credentials: 'include' in fetch options or withCredentials: true in Axios. The SameSite cookie attribute must be set to None (with the Secure flag) for cross-origin cookie sending, or Lax if the request is a top-level navigation. This is complex — hosting frontend and API on the same origin avoids all these issues.

What is the null origin and why is it dangerous?

The null origin is sent by browsers for requests from local files (file:// protocol), sandboxed iframes, and certain redirects. Some servers whitelist "null" in their CORS configuration, not realizing that attackers can trigger requests with a null origin using sandboxed iframes. Never whitelist the null origin in production unless you specifically need to support file:// protocol access.

Should I use Access-Control-Allow-Origin: * or a specific domain?

Use the wildcard (*) only for genuinely public APIs that serve public data and do not use credentials. For any API that handles user-specific data, requires authentication, or uses cookies, you must specify the exact allowed origin(s). If you need multiple origins, dynamically set the header based on the request's Origin after validating it against your allowlist. Most CORS middleware libraries handle this pattern automatically.

Is Your App Protected?

VAS automatically scans for vulnerabilities related to cross-origin resource sharing (cors) and provides detailed remediation guidance. Our scanner targets issues common in AI-generated applications.

Scans from $5, results in minutes. Get actionable fixes tailored to your stack.

Get Starter Scan