Fix guide · high · cors_origin_reflected

Server reflects arbitrary Origin in Access-Control-Allow-Origin

What this rule means

vibecheck sent a request with Origin: https://attacker.example and your server echoed that exact value back in the Access-Control-Allow-Origin response header. The CORS allowlist isn't actually filtering — every origin is accepted.

Why it matters

The 'echo the Origin header' pattern is the most common CORS bug in vibe-coded apps. It looks correct (browsers permit cross-origin requests, dev appears to work) but it's the same as Access-Control-Allow-Origin: * from a security standpoint — there's no filtering. Without Allow-Credentials: true an attacker can't read authenticated responses, but they can still:

If this finding is paired with cors_origin_reflected_with_credentials (the credentials variant), every authenticated visitor's data is readable from any malicious site.

How to fix it

Replace echo-the-Origin with an allowlist. Express + cors:

import cors from "cors";

const ALLOWED_ORIGINS = [
  "https://your-app.com",
  "https://www.your-app.com",
  "https://app.your-app.com",
];

app.use(cors({
  origin: (origin, cb) => {
    if (!origin) return cb(null, true);  // Allow same-origin/no-Origin requests
    if (ALLOWED_ORIGINS.includes(origin)) return cb(null, true);
    return cb(new Error("Origin not allowed"));
  },
  credentials: true,
}));

Hono / Cloudflare Workers:

import { cors } from "hono/cors";

app.use("/*", cors({
  origin: ALLOWED_ORIGINS,                 // explicit list, not a function that always returns origin
  credentials: true,
  allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
}));

Two anti-patterns to specifically avoid:

After deploying, verify with curl:

curl -i -H "Origin: https://attacker.example" https://your-app.com/api/anything
# Look for Access-Control-Allow-Origin in the response. It should NOT be
# "https://attacker.example". It should either be missing or be one of
# your allowed origins.

Full guide: /blog/cors-misconfig-vibe-coded.

Did vibecheck flag this on your app?

If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.

Run another inspection