← All Articles 🔒 Security Vulnerabilities High By Nishant Kumar Verma Updated

CORS Misconfiguration in Vibe-Coded Apps: Wildcard Origins Explained

Wildcard CORS origins let any website call your API. Learn how AI tools misconfigure Access-Control headers and how to fix them.

SEC-004

Quick Answer

A wildcard CORS origin (Access-Control-Allow-Origin: *) tells browsers that any website in the world may read your API's responses. Browsers refuse to combine * with credentials, so the serious hole appears when an API reflects the caller's origin and allows credentials. AI tools generate wildcard CORS headers by default because they eliminate friction during development - the problem is those defaults ship to production.

What CORS Actually Does

Cross-Origin Resource Sharing (CORS) is a browser security mechanism that restricts which origins can call your API from JavaScript running on a different domain. Without CORS headers, a script on evil.com cannot fetch data from yourapp.com/api/users - the browser blocks it. When you add Access-Control-Allow-Origin: *, you instruct the browser to lift that restriction for every origin on the internet.

The distinction that matters: CORS is enforced by browsers, not servers. Direct server-to-server requests, curl, and tools like Postman bypass CORS entirely. What CORS protects is the response: it stops a malicious website from reading your API's data through a logged-in user's browser. It does not stop a simple request from reaching your server, which is why CSRF needs its own defenses.

The OWASP API Security Top 10 (2023) lists a missing or improperly set CORS policy under API8, Security Misconfiguration.

How AI Tools Generate Wildcard CORS

When you ask Cursor, Bolt, or Lovable to "add CORS support to my Express API," the generated code often looks like this:

// ❌ BAD - Wildcard CORS that allows any origin
const express = require('express');
const cors = require('cors');

const app = express();

// AI-generated: "allows all origins" - dangerous in production
app.use(cors());
// Equivalent to:
// app.use(cors({ origin: '*' }));

app.get('/api/user/profile', async (req, res) => {
  const userId = req.session.userId;
  const user = await db.user.findUnique({ where: { id: userId } });
  res.json(user);
});

Calling cors() with no arguments is equivalent to setting Access-Control-Allow-Origin: *, and it answers preflight requests from any domain. Any website can then read every response your API gives to a request made without credentials. Browsers will not share a cookie-authenticated response with a wildcard origin, so the bigger risk comes when someone "fixes" that.

The Credentials Combination Makes It Critical

Wildcard CORS alone is bad. An API that reflects whatever Origin it receives and also sends Access-Control-Allow-Credentials: true is a critical vulnerability. Browsers block credentialed responses that come back with Access-Control-Allow-Origin: *, so when you prompt an AI tool to "fix CORS errors with authentication," it may switch to reflecting the origin, for example cors({ origin: true, credentials: true }). Then any website can read a logged-in user's data.

// ✅ GOOD - Explicit allowlist of permitted origins
const allowedOrigins = [
  'https://yourapp.com',
  'https://www.yourapp.com',
  process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : null,
].filter(Boolean);

app.use(cors({
  origin: (origin, callback) => {
    // Allow requests with no origin (curl, Postman, server-to-server)
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error(`CORS: origin ${origin} not allowed`));
    }
  },
  credentials: true,         // Only safe with an explicit origin list
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
}));

In Next.js, CORS is configured per-route in the route.ts handler or globally via next.config.js headers. Next.js Proxy (called middleware before Next.js 16) is also a place to enforce an origin allowlist before requests reach your route handlers.

CORS Misconfiguration Patterns to Watch For

Misconfiguration Risk Fix
Access-Control-Allow-Origin: * Any site can read public API responses Explicit origin allowlist
Origin: * + credentials: true Browsers block the response; reflecting the origin to work around that opens a real hole Never combine wildcard with credentials
Reflecting request Origin without validation Attacker controls the allowed origin dynamically Validate against explicit allowlist before reflecting
Null origin allowed Sandboxed iframes and data: URIs bypass restriction Remove null from allowlist entirely
Subdomain wildcard (*.yourapp.com) Any subdomain including XSS-vulnerable ones List specific subdomains explicitly

CORS in Supabase and Vercel Deployments

Supabase's hosted API already has its own CORS configuration, but when you add a Next.js or Express backend layer in front of Supabase - a common Bolt and Lovable architecture - that layer needs its own CORS policy. The Supabase client configuration on the frontend does not protect the middleware layer.

Vercel deployments support CORS header configuration in vercel.json. A wildcard header there is added to every matching response, including routes where your application deliberately left the header off to reject an origin. Always audit your vercel.json headers block when deploying to Vercel. A common AI-generated pattern is:

// ❌ BAD - vercel.json wildcard that bypasses app-level CORS
{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [{ "key": "Access-Control-Allow-Origin", "value": "*" }]
    }
  ]
}

This single configuration change can undo application-level origin validation across every API route in the project.

How to Find CORS Misconfigurations

A targeted search covers most cases. Look for cors() called without arguments, Access-Control-Allow-Origin set to a string literal "*", and any place where the incoming Origin header is reflected directly back without validation. In Next.js, check both next.config.js headers and individual route.ts files for response header assignments.

Tools like VibeDoctor's Vibe Check automatically flag explicit wildcard or reflected origins (origin: '*', origin: true, an Access-Control-Allow-Origin: * header) in JavaScript and TypeScript, and wildcard settings in Flask-CORS, FastAPI, and Django, with specific file paths and line numbers. A bare cors() call and vercel.json are not checked, so search for those yourself. Free to sign up.

FAQ

Does wildcard CORS affect non-browser clients?

No. CORS is enforced by browsers only. Command-line tools like curl, server-to-server HTTP calls, and API clients like Postman ignore CORS headers entirely. The risk is exclusively about what a malicious website running in a victim's browser can do on their behalf.

Is wildcard CORS acceptable for public, read-only APIs?

Potentially, for truly public data that carries no user-specific information and requires no credentials. A public weather API or exchange rate feed can reasonably use a wildcard. The problem is that AI tools apply wildcard CORS to all routes including authenticated ones. Scope it deliberately rather than globally.

How does CORS interact with CSRF tokens?

They address different threat vectors. CORS controls cross-origin reads; CSRF tokens prevent cross-origin state-changing requests (writes). A properly configured CORS allowlist reduces the attack surface for CSRF, but it is not a substitute for CSRF protection on state-changing endpoints. Both should be in place.

What happens when I set credentials: true with a wildcard origin?

Modern browsers will reject the response with an error: "The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'." So the combination fails in browsers, and the configuration intent is still wrong. The real danger is the workaround: reflecting the request's Origin with credentials enabled, which browsers do accept.

Does Supabase handle CORS for me?

Supabase's hosted API handles CORS for its own endpoints. Your own code does not inherit that: Supabase Edge Functions need CORS headers added (the withSupabase wrapper or the SDK's corsHeaders export can do it for you), and any Next.js or Express backend you write needs its own policy.

Diagnose your codebase - free

VibeDoctor checks for SEC-004 and 148 other issues across 21 diagnostic areas - security, performance, code quality, and more.

SCAN MY APP →