---
# === IDENTITY ===
id: software/security/browser-security-model/2026
canonical_question: "How does the browser security model work (SOP, CSP, CORS)?"
aliases:
  - "same-origin policy explained"
  - "browser security headers overview"
  - "SOP CSP CORS COOP COEP explained"
  - "cross-origin security policies"
  - "web browser security architecture"
  - "Content Security Policy vs CORS vs SOP"
  - "how to configure browser security headers"
  - "cross-origin isolation Spectre mitigations"
entity_type: software_reference
domain: software > security > Browser Security Model
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-02-27
confidence: 0.95
version: 1.0
first_published: 2026-02-27

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Chrome 85 defaulted Referrer-Policy to strict-origin-when-cross-origin (2020); COOP/COEP required for SharedArrayBuffer (Chrome 92, 2021); CSP Level 3 strict-dynamic widely adopted (2023); document.domain deprecated in Chrome 115 (2023)"
  next_review: 2026-08-26
  change_sensitivity: low

# === CONSTRAINTS ===
constraints:
  - "SOP is enforced by the BROWSER, not the server -- server-side code cannot rely on SOP for protection"
  - "CORS headers MUST be set on the SERVER response, not on the client request -- misconfigured CORS is a server vulnerability"
  - "NEVER use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true -- browsers reject this combination"
  - "CSP is defense-in-depth, NOT a replacement for input validation or output encoding"
  - "COOP: same-origin breaks OAuth popup flows and payment integrations -- use same-origin-allow-popups for those cases"
  - "Permissions-Policy replaces Feature-Policy -- use the new header name (Feature-Policy is a deprecated alias)"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need to prevent XSS attacks specifically"
    use_instead: "software/security/xss-prevention/2026"
  - condition: "Need CSRF protection (token-based request forgery defense)"
    use_instead: "software/security/csrf-prevention/2026"
  - condition: "Need to configure HTTPS/TLS certificates"
    use_instead: "software/devops/tls-certificate-management/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: "security_goal"
    question: "What is your primary security goal?"
    type: choice
    options: ["Restrict cross-origin data access", "Allow controlled cross-origin API access", "Prevent inline script injection", "Enable SharedArrayBuffer/cross-origin isolation", "Restrict browser features in iframes", "Control referrer information leakage"]
  - key: "deployment_context"
    question: "What is your deployment context?"
    type: choice
    options: ["Single-origin web app", "Multi-origin microservices", "Third-party widget/embed", "CDN-served static assets", "OAuth/payment popup integration"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/security/browser-security-model/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-02-27)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/security/xss-prevention/2026"
      label: "XSS Prevention Guide"
    - id: "software/security/csrf-prevention/2026"
      label: "CSRF Prevention"
  solves: []
  alternative_to: []
  often_confused_with:
    - id: "software/security/xss-prevention/2026"
      label: "XSS Prevention (CSP is one layer of XSS defense, not the whole browser security model)"

# === SOURCES (7 authoritative sources) ===
# Types: official_docs, technical_blog, rfc_spec, academic_paper, community_resource, industry_report
# Reliability: high, moderate_high, moderate, moderate_low, low, authoritative
sources:
  - id: src1
    title: "Same-origin policy"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Same-origin_policy
    type: official_docs
    published: 2025-11-15
    reliability: authoritative
  - id: src2
    title: "Cross-Origin Resource Sharing (CORS)"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS
    type: official_docs
    published: 2025-11-30
    reliability: authoritative
  - id: src3
    title: "Content Security Policy (CSP)"
    author: MDN Web Docs
    url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
    type: official_docs
    published: 2025-06-01
    reliability: authoritative
  - id: src4
    title: "Same-origin policy (SOP)"
    author: PortSwigger Web Security Academy
    url: https://portswigger.net/web-security/cors/same-origin-policy
    type: technical_blog
    published: 2025-01-10
    reliability: high
  - id: src5
    title: "Making your website cross-origin isolated using COOP and COEP"
    author: Google Web Dev
    url: https://web.dev/articles/coop-coep
    type: technical_blog
    published: 2024-09-01
    reliability: high
  - id: src6
    title: "Content Security Policy Level 3"
    author: W3C
    url: https://www.w3.org/TR/CSP3/
    type: rfc_spec
    published: 2025-06-06
    reliability: authoritative
  - id: src7
    title: "Site Isolation Design Document"
    author: Chromium Project
    url: https://www.chromium.org/developers/design-documents/site-isolation/
    type: official_docs
    published: 2025-09-01
    reliability: high
---

# Browser Security Model: SOP, CSP, CORS, and Cross-Origin Isolation

## TL;DR

- **Bottom line**: The browser security model is a layered defense system where the Same-Origin Policy (SOP) is the foundation restricting cross-origin data access, CORS selectively relaxes SOP for controlled API sharing, CSP restricts resource loading to prevent injection attacks, and COOP/COEP enable process-level isolation against Spectre-class side-channel attacks.
- **Key tool/command**: `curl -sI https://your-site.com | grep -iE 'content-security|access-control|cross-origin|referrer-policy|permissions-policy'` to audit all browser security headers at once.
- **Watch out for**: Using `Access-Control-Allow-Origin: *` with credentials -- browsers silently reject this, causing hard-to-debug CORS failures.
- **Works with**: All modern browsers. CSP Level 3 in Chrome 59+, Firefox 58+, Safari 15.4+, Edge 79+. COOP/COEP in Chrome 83+, Firefox 79+, Safari 15.2+.

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- SOP is enforced by the BROWSER, not the server -- server-side code cannot rely on SOP for protection
- CORS headers MUST be set on the SERVER response, not on the client request -- misconfigured CORS is a server vulnerability
- NEVER use `Access-Control-Allow-Origin: *` with `Access-Control-Allow-Credentials: true` -- browsers reject this combination
- CSP is defense-in-depth, NOT a replacement for input validation or output encoding
- COOP: `same-origin` breaks OAuth popup flows and payment integrations -- use `same-origin-allow-popups` for those cases
- Permissions-Policy replaces Feature-Policy -- use the new header name (Feature-Policy is a deprecated alias)

## Quick Reference

| # | Policy/Header | Purpose | Scope | Default Behavior | Bypass Risk |
|---|---|---|---|---|---|
| 1 | **Same-Origin Policy (SOP)** | Restricts cross-origin DOM access, XHR/fetch reads, and storage | Browser-enforced on all origins | Blocks cross-origin reads; allows embeds and writes | Misconfigured CORS, `document.domain` (deprecated), `postMessage` without origin check |
| 2 | **Content Security Policy (CSP)** | Controls which resources (scripts, styles, images) a page can load | Per-page via HTTP header or `<meta>` | No restrictions (everything allowed) | `unsafe-inline`, `unsafe-eval`, overly broad allowlists, CSP bypass via script gadgets |
| 3 | **Cross-Origin Resource Sharing (CORS)** | Allows servers to opt in to cross-origin requests | Per-resource via response headers | Browsers block cross-origin fetch/XHR responses | Wildcard origin with credentials, reflected Origin header, null origin trust |
| 4 | **Cross-Origin-Opener-Policy (COOP)** | Isolates browsing context group from cross-origin openers | Per-document via response header | `unsafe-none` (no isolation) | Breaking popup-based OAuth/payment flows with `same-origin` |
| 5 | **Cross-Origin-Embedder-Policy (COEP)** | Requires subresources to opt in via CORS/CORP | Per-document via response header | `unsafe-none` (no restrictions) | Third-party resources without CORP/CORS headers get blocked |
| 6 | **Cross-Origin-Resource-Policy (CORP)** | Controls which origins can embed a resource | Per-resource via response header | Resources loadable from any origin | Blocks legitimate cross-origin embeds if set too restrictively |
| 7 | **Permissions-Policy** | Restricts browser features (camera, geolocation, etc.) | Per-page and per-iframe | All features available to top-level; restricted in iframes by spec defaults | Overly permissive `allow` on iframes |
| 8 | **Referrer-Policy** | Controls what referrer info is sent with requests | Per-page or per-request | `strict-origin-when-cross-origin` (Chrome 85+ default) | `no-referrer-when-downgrade` leaks full URL on HTTPS-to-HTTPS navigations |

**Origin Definition** (SOP foundation):

| Component | Same-Origin Example | Cross-Origin Example |
|---|---|---|
| Scheme | `https://a.com` = `https://a.com` | `http://a.com` != `https://a.com` |
| Host | `a.com` = `a.com` | `a.com` != `b.a.com` |
| Port | `a.com:443` = `a.com:443` | `a.com:443` != `a.com:8443` |

## Decision Tree

```
START: What is your cross-origin security goal?
+-- Need to BLOCK cross-origin data reads?
|   +-- YES -> SOP handles this by default. No action needed.
|   +-- NO v
+-- Need to ALLOW cross-origin API access?
|   +-- YES -> Configure CORS headers on the server (Access-Control-Allow-Origin)
|   +-- NO v
+-- Need to prevent inline script injection / restrict resource loading?
|   +-- YES -> Deploy Content Security Policy (CSP) with nonce-based script-src
|   +-- NO v
+-- Need SharedArrayBuffer or high-res timers (cross-origin isolation)?
|   +-- YES -> Set COOP: same-origin + COEP: require-corp on the document
|   +-- NO v
+-- Need to restrict browser features in embedded iframes?
|   +-- YES -> Use Permissions-Policy header + iframe allow attribute
|   +-- NO v
+-- Need to limit referrer information leakage?
|   +-- YES -> Set Referrer-Policy: strict-origin-when-cross-origin (or stricter)
|   +-- NO v
+-- DEFAULT -> Deploy all security headers: CSP + COOP + COEP + Permissions-Policy + Referrer-Policy
```

## Step-by-Step Guide

### 1. Audit current security headers

Check which headers your site already sends. Missing headers mean the browser uses permissive defaults. [src1]

```bash
# Audit all browser security headers at once
curl -sI https://your-site.com | grep -iE \
  'content-security|access-control|cross-origin|referrer-policy|permissions-policy|x-frame|x-content-type|strict-transport'
```

**Verify**: Every line below should appear in the output. Missing lines indicate unset headers:
- `Content-Security-Policy`
- `Cross-Origin-Opener-Policy`
- `Cross-Origin-Embedder-Policy`
- `Referrer-Policy`
- `Permissions-Policy`

### 2. Deploy a strict Content Security Policy

CSP is the most impactful single header -- it mitigates XSS, data injection, and clickjacking. Use nonce-based policies for best protection. [src3]

```http
Content-Security-Policy:
  default-src 'self';
  script-src 'nonce-{random}' 'strict-dynamic';
  style-src 'self' 'nonce-{random}';
  img-src 'self' https:;
  font-src 'self';
  connect-src 'self' https://api.your-domain.com;
  object-src 'none';
  base-uri 'none';
  frame-ancestors 'none';
  form-action 'self';
  upgrade-insecure-requests;
```

**Verify**: Inject `<script>alert(1)</script>` -- CSP should block it. Check DevTools Console for CSP violation reports.

### 3. Configure CORS on your API server

Set specific origins -- never reflect the Origin header blindly. [src2]

```javascript
// Node.js/Express CORS configuration
const cors = require('cors');  // ^2.8.0

const corsOptions = {
  origin: ['https://your-app.com', 'https://staging.your-app.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
  maxAge: 86400  // Preflight cache: 24 hours
};

app.use('/api', cors(corsOptions));
```

**Verify**: `curl -H "Origin: https://evil.com" -sI https://api.your-site.com/endpoint` -- should NOT return `Access-Control-Allow-Origin: https://evil.com`.

### 4. Enable cross-origin isolation (COOP + COEP)

Required for SharedArrayBuffer and high-resolution timers. Test in report-only mode first. [src5]

```http
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

For pages that need OAuth popups or payment integrations:

```http
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Embedder-Policy: credentialless
```

All subresources must opt in with CORP or CORS headers:

```http
# On your CDN / static asset server:
Cross-Origin-Resource-Policy: cross-origin

# On same-site internal APIs:
Cross-Origin-Resource-Policy: same-site
```

**Verify**: Open DevTools Console and check `self.crossOriginIsolated === true`.

### 5. Set Permissions-Policy and Referrer-Policy

Restrict unnecessary browser features and control referrer leakage. [src1]

```http
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(self),
  usb=(), magnetometer=(), gyroscope=(), accelerometer=()

Referrer-Policy: strict-origin-when-cross-origin
```

**Verify**: `document.featurePolicy.allowsFeature('camera')` should return `false` in DevTools Console.

## Code Examples

### Node.js/Express: Complete Security Headers Middleware

```javascript
const crypto = require('crypto');

function securityHeaders(req, res, next) {
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.cspNonce = nonce;

  res.set({
    'Content-Security-Policy':
      `default-src 'self'; script-src 'nonce-${nonce}' 'strict-dynamic'; ` +
      `style-src 'self' 'nonce-${nonce}'; object-src 'none'; base-uri 'none'; ` +
      `frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests`,
    'Cross-Origin-Opener-Policy': 'same-origin',
    'Cross-Origin-Embedder-Policy': 'require-corp',
    'Referrer-Policy': 'strict-origin-when-cross-origin',
    'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY'
  });
  next();
}
```

### Nginx: Security Headers Configuration

```nginx
# /etc/nginx/snippets/security-headers.conf
add_header Content-Security-Policy
  "default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"
  always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy
  "camera=(), microphone=(), geolocation=(), payment=(self)"
  always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
```

### Python/Django: Middleware Security Headers

```python
# settings.py -- Django 4.x+ built-in security middleware
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin"
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
X_FRAME_OPTIONS = "DENY"

# CSP via django-csp (^4.0)
CSP_DEFAULT_SRC = ("'self'",)
CSP_SCRIPT_SRC = ("'self'",)  # Add nonce support with CSP_INCLUDE_NONCE_IN
CSP_OBJECT_SRC = ("'none'",)
CSP_BASE_URI = ("'none'",)
CSP_FRAME_ANCESTORS = ("'none'",)

# CORS via django-cors-headers (^4.0)
CORS_ALLOWED_ORIGINS = [
    "https://your-frontend.com",
    "https://staging.your-frontend.com",
]
CORS_ALLOW_CREDENTIALS = True
```

### Go: Security Headers Middleware

```go
package main

import "net/http"

func securityHeaders(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Security-Policy",
            "default-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'")
        w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
        w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
        w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
        w.Header().Set("Permissions-Policy", "camera=(), microphone=(), geolocation=()")
        w.Header().Set("X-Content-Type-Options", "nosniff")
        w.Header().Set("X-Frame-Options", "DENY")
        next.ServeHTTP(w, r)
    })
}
```

## Anti-Patterns

### Wrong: Reflecting the Origin header in CORS

```javascript
// BAD -- reflects any origin, equivalent to disabling SOP
app.use((req, res, next) => {
  res.set('Access-Control-Allow-Origin', req.headers.origin);
  res.set('Access-Control-Allow-Credentials', 'true');
  next();
});
// Attacker on https://evil.com can read authenticated responses
```

### Correct: Allowlist specific origins

```javascript
// GOOD -- only trusted origins can make credentialed requests
const ALLOWED = new Set(['https://app.example.com', 'https://staging.example.com']);

app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (ALLOWED.has(origin)) {
    res.set('Access-Control-Allow-Origin', origin);
    res.set('Access-Control-Allow-Credentials', 'true');
    res.set('Vary', 'Origin');  // Critical for caching
  }
  next();
});
```

### Wrong: CSP with unsafe-inline and unsafe-eval

```http
# BAD -- defeats the entire purpose of CSP
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'
```

### Correct: Nonce-based CSP with strict-dynamic

```http
# GOOD -- nonces block injected scripts, strict-dynamic trusts loader chains
Content-Security-Policy: default-src 'self'; script-src 'nonce-abc123' 'strict-dynamic'
```

### Wrong: Trusting the null origin in CORS

```javascript
// BAD -- null origin comes from sandboxed iframes, data: URLs, redirects
app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (origin === 'null') {
    res.set('Access-Control-Allow-Origin', 'null');
  }
  next();
});
// Attacker can forge null origin via sandboxed iframe
```

### Correct: Never trust null origin

```javascript
// GOOD -- reject null and only trust explicit HTTPS origins
const ALLOWED = new Set(['https://app.example.com']);

app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (origin && ALLOWED.has(origin)) {
    res.set('Access-Control-Allow-Origin', origin);
    res.set('Vary', 'Origin');
  }
  next();
});
```

### Wrong: Missing Vary: Origin on CORS responses

```javascript
// BAD -- CDN caches response for one origin, serves it to all
res.set('Access-Control-Allow-Origin', req.headers.origin);
// Missing: res.set('Vary', 'Origin');
```

### Correct: Always set Vary: Origin

```javascript
// GOOD -- ensures CDN/proxy caches differentiate by origin
res.set('Access-Control-Allow-Origin', origin);
res.set('Vary', 'Origin');
```

## Common Pitfalls

- **CORS preflight caching**: Browsers cache preflight responses (OPTIONS) based on `Access-Control-Max-Age`. If you change allowed methods/headers, users won't see the change until the cache expires. Fix: Set a reasonable `Access-Control-Max-Age` (e.g., 86400 seconds) and document it. [src2]
- **CSP strict-dynamic + script gadgets**: `strict-dynamic` trusts any script loaded by a trusted script. Libraries like jQuery or Angular that evaluate strings as code can be exploited as script gadgets. Fix: Audit third-party libraries for `eval()`-like behavior; prefer nonce-only policies. [src6]
- **COEP blocks third-party resources**: Enabling `Cross-Origin-Embedder-Policy: require-corp` blocks all cross-origin resources without CORP/CORS headers (ads, analytics, fonts). Fix: Use `credentialless` mode or add `crossorigin` attribute to `<img>`, `<script>`, `<link>` tags. [src5]
- **postMessage without origin verification**: `window.addEventListener('message', handler)` without checking `event.origin` enables cross-origin data injection. Fix: Always validate `event.origin` against an allowlist before processing the message. [src1]
- **COOP breaks window.opener**: `Cross-Origin-Opener-Policy: same-origin` severs the `window.opener` reference for cross-origin popups, breaking OAuth redirect flows. Fix: Use `same-origin-allow-popups` when popup communication is needed. [src5]
- **Missing CORS on error responses**: Server returns CORS headers on 200 OK but not on 4xx/5xx errors, causing the browser to block the error details from JavaScript. Fix: Apply CORS headers to ALL responses, including errors. [src2]
- **Referrer leakage on HTTPS-to-HTTP downgrades**: Default `strict-origin-when-cross-origin` stops sending referrer on protocol downgrade, but `no-referrer-when-downgrade` leaks full URL on HTTPS-to-HTTPS cross-origin requests. Fix: Use `strict-origin-when-cross-origin` or `no-referrer`. [src1]
- **document.domain deprecation**: Setting `document.domain` to relax SOP between subdomains is deprecated in Chrome 115+ and disabled by default. Fix: Use `postMessage()` or CORS for cross-subdomain communication. [src1]

## Diagnostic Commands

```bash
# Audit all security headers at once
curl -sI https://your-site.com | grep -iE \
  'content-security|access-control|cross-origin|referrer-policy|permissions-policy|x-frame|strict-transport'

# Test CORS: check if an origin is allowed
curl -H "Origin: https://app.example.com" -sI https://api.example.com/endpoint \
  | grep -i access-control

# Test CORS preflight (OPTIONS request)
curl -X OPTIONS \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: Content-Type, Authorization" \
  -sI https://api.example.com/endpoint

# Check cross-origin isolation status (in browser console)
# self.crossOriginIsolated  // should be true

# Validate CSP with Google's CSP Evaluator
# Visit: https://csp-evaluator.withgoogle.com/

# Scan security headers with securityheaders.com
# Visit: https://securityheaders.com/?q=https://your-site.com

# Check for CORS misconfigurations with curl
curl -H "Origin: https://evil.com" -sI https://your-site.com/api \
  | grep -i access-control-allow-origin
# Should NOT return: Access-Control-Allow-Origin: https://evil.com
```

## Version History & Compatibility

| Standard/Feature | Status | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|---|
| Same-Origin Policy (SOP) | Foundational | All | All | All | All |
| CSP Level 2 (script-src, style-src) | W3C Rec | 40+ | 31+ | 10+ | 15+ |
| CSP Level 3 (strict-dynamic, nonces) | W3C WD | 59+ | 58+ | 15.4+ | 79+ |
| CORS (basic) | W3C Rec | 4+ | 3.5+ | 4+ | 12+ |
| COOP (same-origin) | Standard | 83+ | 79+ | 15.2+ | 83+ |
| COEP (require-corp) | Standard | 83+ | 79+ | 15.2+ | 83+ |
| COEP (credentialless) | Standard | 96+ | 119+ | No | 96+ |
| Cross-Origin-Resource-Policy (CORP) | Standard | 73+ | 74+ | 12+ | 79+ |
| Permissions-Policy | Standard | 88+ | 65+ (partial) | No | 88+ |
| Referrer-Policy | Standard | 56+ | 50+ | 11.1+ | 79+ |
| Site Isolation (process per site) | Chrome-specific | 67+ (desktop), 77+ (Android) | Fission (95+) | Process per tab | 67+ |
| Trusted Types | Draft | 83+ | Behind flag | No | 83+ |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Your API serves multiple frontend origins | API and frontend share the same origin | SOP already blocks unauthorized access -- CORS not needed |
| Preventing inline script injection (XSS defense layer) | You need sole XSS prevention | CSP alone is insufficient -- add output encoding (see XSS Prevention unit) |
| App uses SharedArrayBuffer, WASM threads, or high-res timers | App is a simple content site with no advanced APIs | COOP/COEP add complexity with no benefit |
| Embedding third-party iframes that should not access camera/mic | Top-level page controls all features itself | Permissions-Policy is most valuable for iframe restrictions |
| Hosting resources that should only load on your own site | Hosting public CDN resources meant for cross-origin use | Set CORP: `cross-origin` for public resources |

## Important Caveats

- SOP allows cross-origin writes (form submissions, navigations) and embeds (images, scripts, stylesheets, iframes) by default -- it only blocks cross-origin reads (XHR/fetch responses, DOM access)
- CORS does NOT protect against CSRF -- CORS is about reading responses, while CSRF exploits the browser automatically attaching cookies to cross-origin requests
- CSP `strict-dynamic` propagates trust: if a trusted script loads a third-party script, that third-party script is also trusted, which can be exploited via script gadgets in libraries like jQuery or Angular
- Site Isolation (process-per-site) adds 10-13% memory overhead on desktop -- it's a browser-level defense, not something developers configure, but it impacts performance budgets
- `document.domain` is deprecated and disabled by default in Chrome 115+ -- do not rely on it for cross-subdomain communication
- The Permissions-Policy header has inconsistent browser support -- Safari does not support it, and Firefox support is partial (use `<iframe allow="...">` for broader compatibility)

## Related Units
<!-- Generated from related_kos frontmatter -->

- [XSS Prevention Guide](/software/security/xss-prevention/2026)
- [CSRF Prevention](/software/security/csrf-prevention/2026)
