# CORS headers are explicitly configured

- **Pattern:** `ab-000012` (`security-headers.headers.cors-configured`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-17
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000012
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000012)

## Why it matters

Wildcard CORS (`Access-Control-Allow-Origin: *`) allows any website on the internet to make authenticated API requests using the user's credentials. An attacker's page can silently read your API responses, trigger state-changing calls, and exfiltrate data — all without the user knowing. The impact depends on what your API does: for a read-only public API, wildcard CORS may be intentional; for an API that returns user data or modifies state, it is a critical data exposure. CWE-942 (Permissive Cross-domain Policy with Untrusted Domains) and OWASP A05 (Security Misconfiguration) directly apply. CWE-346 (Origin Validation Error) maps to the failure to validate the requesting origin.

## Severity rationale

Info because wildcard CORS becomes dangerous only when the API also handles authentication or returns user-specific data — context determines actual severity.

## Remediation

Replace wildcard `*` CORS with an explicit allowlist of your own domains. Never use `*` on routes that handle authentication or return user-specific data.

```ts
// Next.js API route — src/app/api/example/route.ts
const allowedOrigins = ['https://yoursite.com', 'https://app.yoursite.com']

export async function GET(req: Request) {
  const origin = req.headers.get('origin') ?? ''
  const headers: Record<string, string> = {}
  if (allowedOrigins.includes(origin)) {
    headers['Access-Control-Allow-Origin'] = origin
  }
  return Response.json({ data }, { headers })
}
```

If your API is genuinely public with no user data, document the intentional wildcard in a comment so auditors can verify it's a conscious decision.

## Detection

- **ID:** `cors-configured`
- **Severity:** `info`
- **What to look for:** Count all API route files in the project. For each, check for CORS configuration — `Access-Control-Allow-Origin` headers set directly or via middleware. Check for wildcard `*` usage in production config. Report: "X API routes found, Y set CORS headers."
- **Pass criteria:** Two distinct pass states:
  - **(a) Same-origin only:** No CORS headers are set anywhere in the project — the API is same-origin only and this is correct. 0 routes set cross-origin headers. Detail should note: `"No CORS headers configured — same-origin API usage."`.
  - **(b) Explicit allowlist:** CORS headers are set with an explicit origin allowlist (not wildcard `*`). No more than 0 routes should use wildcard `*` origin. Detail should note the configured origins.
- **Fail criteria:** `Access-Control-Allow-Origin: *` is set on at least 1 route in production, even if other routes have specific origins configured.
- **Skip (N/A) when:** No API routes detected — the project has no endpoints that would need CORS configuration.
- **Detail on fail:** `"API routes return Access-Control-Allow-Origin: * — any website can make requests to your API"` or `"CORS middleware uses wildcard origin in production config"`
- **Remediation:** Wildcard CORS (`Access-Control-Allow-Origin: *`) allows any website to make API requests to your backend. Restrict it to your own domains:

  ```ts
  // Example for Next.js API routes
  const allowedOrigins = ['https://yoursite.com', 'https://app.yoursite.com']
  const origin = req.headers.get('origin')
  if (allowedOrigins.includes(origin)) {
    res.headers.set('Access-Control-Allow-Origin', origin)
  }
  ```

---

## External references

- cwe CWE-942
- cwe CWE-346
- owasp A05

Taxons: access-control

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