# CORS properly configured

- **Pattern:** `ab-002194` (`saas-api-design.api-security.cors-configured`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002194
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002194)

## Why it matters

A wildcard `Access-Control-Allow-Origin: *` on an authenticated endpoint completely voids same-origin protection: any page on any domain can read the response from a cross-origin fetch, bypassing the browser's security model (CWE-942, OWASP A05:2021). Pairing `Allow-Credentials: true` with `Allow-Origin: *` is a misconfiguration that browsers reject, breaking legitimate cross-origin authenticated requests. Missing CORS configuration on APIs that have external consumers silently fails for those clients, producing hard-to-debug network errors.

## Severity rationale

High because wildcard CORS on authenticated routes enables cross-origin data theft from any attacker-controlled website that can lure an authenticated user into a browser.

## Remediation

Configure CORS explicitly in `next.config.ts` via the `headers()` function, pinning the allowed origin to your actual domain:

```ts
// next.config.ts
async headers() {
  return [{
    source: '/api/:path*',
    headers: [
      { key: 'Access-Control-Allow-Origin', value: process.env.ALLOWED_ORIGIN! },
      { key: 'Access-Control-Allow-Methods', value: 'GET,POST,PUT,PATCH,DELETE,OPTIONS' },
      { key: 'Access-Control-Allow-Headers', value: 'Content-Type,Authorization' },
    ],
  }]
},
```

Never use `*` on authenticated routes. Use an environment variable for the origin so staging and production can differ. If you need cookie-based cross-origin auth, add `Access-Control-Allow-Credentials: true` only alongside the specific origin allowlist — never alongside `*`.

## Detection

- **ID:** `cors-configured`
- **Severity:** `high`
- **What to look for:** Enumerate all CORS configuration locations. Quote the actual `Access-Control-Allow-Origin` header value found. Check the CORS configuration for API routes. Look for: `Access-Control-Allow-Origin` header settings in framework config, middleware, or individual route handlers; use of `cors` npm package with an `origin` allowlist; Vercel/Netlify header config; wildcard `*` on routes that require authentication (this is a security issue — authenticated endpoints should never use `*`). Also check: `Access-Control-Allow-Credentials` — if this is `true`, `Access-Control-Allow-Origin` must not be `*`. Explicit signals for cross-origin consumers include: comments describing external callers or integrations in route handlers, CORS headers already set, `Access-Control-*` headers in middleware, a separate `/api/public/` or `/api/external/` route namespace, or documentation referencing third-party integrations calling your API.
- **Pass criteria:** CORS is explicitly configured with at least 1 specific domain in the allowlist. Authenticated routes use a specific domain allowlist (not `*`). Unauthenticated public API routes may use `*` if intentional. `Allow-Credentials: true` is never paired with `Allow-Origin: *`.
- **Fail criteria:** No CORS configuration (relying on browser defaults, which may fail for cross-origin clients); or wildcard `*` on authenticated routes; or `Allow-Credentials: true` paired with `Allow-Origin: *`.
- **Skip (N/A) when:** The API is only called from the same origin (no cross-origin clients, no mobile app, no third-party integrations). Signal: no CORS headers configured anywhere AND no evidence of cross-origin clients (all API calls are server-side or same-origin fetch).
- **Detail on fail:** Describe the CORS issue (e.g., "No CORS configuration found for /api/ routes; Access-Control-Allow-Origin: * set on authenticated /api/user routes"). Max 500 chars.
- **Remediation:** Configure CORS explicitly in `next.config.ts` or `src/middleware.ts` rather than relying on defaults. For Next.js, add CORS headers in `next.config.ts` via the `headers()` function, or use a middleware wrapper. Specify the exact origin(s) that should be allowed: `Access-Control-Allow-Origin: https://yourapp.com`. If you have multiple environments (staging, production), use an environment variable for the origin. Never use wildcard `*` on routes that read or write authenticated user data. If you need to support credentials (cookies) cross-origin, use a specific origin allowlist.

## External references

- cwe CWE-942
- owasp A05

Taxons: access-control

HTML version: https://auditbuffet.com/patterns/ab-002194
