How to fix a wildcard (*) CORS policy
Your API responds with `Access-Control-Allow-Origin: *`, which allows any website to call your endpoints. For public APIs that do not handle authentication, this is intentional and fine. For any endpoint that relies on session cookies or auth tokens, it is a bug. Fix it by setting the header to a specific allowed origin, or a narrow allowlist — and remove `Access-Control-Allow-Credentials: true` if you do not actually use credentialed requests.
Why it matters
CORS is defense against cross-origin attacks. A wildcard means any malicious site can call your API from a user's browser. If you set both `Allow-Origin: *` and `Allow-Credentials: true` (which browsers reject, but proxies sometimes rewrite), you have a serious CSRF-equivalent.
How to check
- 01Open DevTools → Network → find a request to your API.
- 02Look at Response Headers: `access-control-allow-origin`.
- 03`*` means any origin; a specific domain is fine; missing means browsers default to same-origin only.
- 04Also check `access-control-allow-credentials` — if both are true for the same endpoint, that is a misconfiguration.
Or let SafeToShip check it for you in 60 seconds:
How to fix it
Next.js Route Handlers
Read the request Origin header; reflect it if it is in your allowlist.
const ALLOWED = ['https://app.example.com', 'https://example.com'];
export async function GET(req: Request) {
const origin = req.headers.get('origin');
const headers = new Headers({ 'content-type': 'application/json' });
if (origin && ALLOWED.includes(origin)) {
headers.set('Access-Control-Allow-Origin', origin);
headers.set('Vary', 'Origin');
}
return new Response(JSON.stringify({ ok: true }), { headers });
}Generic
For public data endpoints with no auth, wildcard is OK. For everything else, reflect from an allowlist. Add `Vary: Origin` for caching.
Access-Control-Allow-Origin: https://app.example.com
Vary: OriginAI prompt
Copy-paste into your AI tool
Paste this prompt into Cursor, Lovable, Bolt, v0, or Claude Code and it will walk through the fix for your specific codebase.
My API responds with `Access-Control-Allow-Origin: *`. For each of my API endpoints, tell me whether it is meant to be public (in which case the wildcard is fine) or meant to serve authenticated user data (in which case it is a bug). For the authenticated ones, implement an allowlist of my known frontend origins and reflect the Origin header when it matches. Add `Vary: Origin` for correct caching.FAQ
Frequently asked questions
- Can I just use credentials: "include" with wildcard?
- No — browsers reject that combination. If your fetch uses `credentials: "include"`, you must set a specific origin, not *.
- What about preflight (OPTIONS) requests?
- Preflight responses also need the allow-origin header, plus `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers`. Handle OPTIONS explicitly in your route handler.
Related fix guides
Fix these too
CORS credentials misconfiguration
Setting both Allow-Origin: * and Allow-Credentials: true is a dangerous misconfiguration. Here is why browsers block it and how to fix it correctly.
Read moreMissing CSP header
A missing Content-Security-Policy header lets attackers inject scripts into your site. Here is what CSP does, why you need it, and how to add it in Next.js, Vercel, and Supabase apps.
Read moreFree tools
Check this yourself
Platform guides
Building on these platforms?
Next.js security
Next.js is the most popular React framework, but even experienced developers miss security headers and accidentally expose server files in production.
Read moreVercel security
Vercel handles hosting and SSL, but your application code still needs security hardening. Missing CSP headers and exposed environment variables are the top issues.
Read moreLovable security
Lovable makes it easy to ship fast, but AI-generated backends often ship with open Supabase tables and leaked API keys. Scan your Lovable app before your users find out.
Read moreScan your site for this and 50+ other issues
Free scan. Results in 60 seconds. No account required.