# Why Cursor Keeps Generating Wildcard CORS Headers in Your API

> Source: <https://dev.to/c_k_fb750e731394/why-cursor-keeps-generating-wildcard-cors-headers-in-your-api-33ii>
> Published: 2026-07-24 16:49:36+00:00

I hit a CORS error in a side project last week. Frontend on one port, API on another, browser blocking the request. I asked Cursor to fix it, and it did, instantly. The error went away. I moved on to the actual feature I was building.

Three days later I was reading through the generated middleware for something unrelated and noticed what "fixed" actually meant. It hadn't allowlisted my frontend's origin. It had told the server to accept requests from anywhere, with cookies attached.

That's the trade AI editors make by default. You ask for the error to go away, and the fastest way to make a CORS error go away is to stop checking who's asking.

The pattern shows up as origin reflection, not a plain wildcard. A bare `Access-Control-Allow-Origin: *`

combined with `Access-Control-Allow-Credentials: true`

actually gets rejected by the browser, so tutorials work around that by echoing back whatever Origin header the request sent. That workaround is the vulnerability.

``` js
// ❌ CWE-942: Permissive Cross-domain Policy
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
  next();
});
```

`req.headers.origin`

is a value the requester controls. A page hosted on `evil-site.com`

sends `Origin: evil-site.com`

, the server echoes it straight back, and the browser sees a match. Credentials are allowed, so the victim's session cookie rides along. Any authenticated GET or POST your API exposes is now readable and callable from a page the victim never meant to trust.

Origin reflection survives in training data because it's the fastest fix that makes a CORS error disappear in local development, and almost every public snippet optimizes for that. Stack Overflow answers, boilerplate repos, and "quick fix" gists all reach for the same three lines because they work identically whether you're testing on `localhost:3000`

, `localhost:5173`

, or a Vercel preview URL. Nobody has to think about which origins are actually supposed to be allowed.

An explicit allowlist requires knowing your production frontend's domain ahead of time, which isn't information available in an isolated code snippet. So the training data skews toward the version that works everywhere and restricts nothing. AI editors reproduce that pattern faithfully, and it ships because it passes every test a developer actually runs before deploying.

Replace origin reflection with a fixed list of domains you actually trust, checked explicitly against each incoming request.

``` js
// ✅ Explicit allowlist, no reflection
const allowedOrigins = [
  'https://app.example.com',
  'https://admin.example.com'
];

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
}));
```

Python/Flask version of the same fix:

``` python
from flask_cors import CORS

CORS(
    app,
    origins=["https://app.example.com", "https://admin.example.com"],
    supports_credentials=True
)
```

For local development, add `localhost`

ports to the allowlist explicitly rather than falling back to a wildcard or reflection "just for now." Environment variables work well here: one allowlist for dev, a locked-down one for production, both explicit.

**Q: Is Access-Control-Allow-Origin: * with credentials actually dangerous?**

**Q: Does a CORS allowlist replace authentication?**

A: No. CORS controls which browser-based origins can read a response, not who's authorized to call the endpoint. You still need real auth checks; CORS is a second layer that stops the browser from letting an untrusted page use a victim's session.

**Q: How do I check my API for this right now?**

A: Look for any CORS middleware where the `Access-Control-Allow-Origin`

value comes from a request header instead of a fixed list. If you see `req.headers.origin`

or `req.get('origin')`

written straight into the response, that's the pattern.

I've been running [SafeWeave](https://tinyurl.com/23dknpup) for this. It hooks into Cursor and Claude Code as an MCP server and flags these patterns before I move on. Even a basic pre-commit hook with semgrep and gitleaks will catch most of what's in this post, the important thing is catching it early, whatever tool you use.
