CORS
Also Known As
Cross-Origin Resource Sharing
CORS policy
TL;DR
Cross-Origin Resource Sharing — the browser mechanism that controls which cross-origin requests are permitted, using HTTP headers negotiated between client and server.
Explanation
Browsers enforce the same-origin policy by default, blocking cross-origin AJAX requests. CORS relaxes this via server-sent headers. Simple requests (GET, POST with safe content types) are sent directly; the browser checks the response headers. Preflighted requests (PUT, DELETE, custom headers) first send an OPTIONS request to check permissions. Misconfigured CORS is one of the most common web security vulnerabilities.
Diagram
sequenceDiagram
participant B as Browser
participant S as Server
Note over B,S: Simple Request - GET/POST safe content-type
B->>S: GET /api/data with Origin header
S-->>B: 200 OK with Access-Control-Allow-Origin
Note over B,S: Preflighted Request - PUT or custom headers
B->>S: OPTIONS /api/data preflight
S-->>B: 204 with Access-Control-Allow-Methods: PUT
B->>S: PUT /api/data actual request
S-->>B: 200 OK
Watch Out
⚠ Reflecting the incoming Origin header without validation is equivalent to a wildcard — any origin is allowed, defeating CORS entirely and enabling cross-origin reads of authenticated responses.
Common Misconception
✗ CORS is a security feature that protects the server — it actually protects the user's browser; a server-side attacker is unaffected by CORS.
Why It Matters
Permissive CORS configuration turns the browser's same-origin policy off, allowing malicious sites to make authenticated API calls on behalf of the victim.
Common Mistakes
- Reflecting the incoming Origin header as Access-Control-Allow-Origin without validating against an allowlist.
- Setting Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true — browsers block this combination.
- Allowlisting by substring match — evil-yoursite.com passes a check for yoursite.com.
- Not setting Vary: Origin when responses differ by origin — CDNs serve the wrong cached response.
Avoid When
- Do not set Access-Control-Allow-Origin: * on APIs that use cookies or session-based authentication — credentials are never sent with wildcard origins but the misconfiguration signals a broken policy.
- Avoid configuring CORS at the application layer if a gateway or CDN already handles it — duplicate headers break the browser negotiation.
When To Use
- Set Access-Control-Allow-Origin to a specific allowlist of trusted origins — never reflect the incoming Origin header directly.
- Use credentials: true (cookies/auth headers) only when the origin is explicitly trusted and listed — never combine it with a wildcard origin.
- Validate preflight OPTIONS requests and return correct Access-Control-Allow-Methods and Headers to avoid blocking legitimate cross-origin requests.
Code Examples
💡 Note
The bad example copies any Origin straight into the response header — an attacker's domain receives authenticated API responses. The fix checks the origin against an explicit allowlist before echoing it.
✗ Vulnerable
// Reflecting any Origin — security bypass:
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
header('Access-Control-Allow-Origin: ' . $origin); // Any origin allowed!
header('Access-Control-Allow-Credentials: true');
// Attacker's evil.com can now make authenticated requests
✓ Fixed
// Validate against allowlist:
$allowed = ['https://app.example.com', 'https://admin.example.com'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed, true)) {
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Credentials: true');
header('Vary: Origin');
}
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
31 Mar 2026
Views
24
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 6
Perplexity 5
Google 4
ChatGPT 3
Ahrefs 2
Also referenced
How they use it
crawler 19
crawler_json 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
Never set Access-Control-Allow-Origin to * for authenticated endpoints; always validate the Origin header against an allowlist and return the specific origin, not the wildcard
📦 Applies To
PHP 5.0+
web
api
🔍 Detection Hints
Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true; dynamic Origin reflection without validation
Auto-detectable:
✓ Yes
semgrep
owasp-zap
burpsuite
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: File
Tests: Update
CWE-942