Configuration & Environment
MCP server sets `Access-Control-Allow-Origin: *` (or reflects the request `Origin` header) AND `Access-Control-Allow-Credentials: true` — combo creates an effective CSRF amplifier on every state-changing route.
Browsers reject the literal `*` + credentials combo, but reflecting `req.headers.origin` and serving credentials is functionally equivalent and widely accepted. Either pattern means: any website the user visits can issue authenticated requests to your MCP server, with the user's cookies/auth headers attached. The right defense is an explicit allowlist of trusted origins, OR drop credentials and use bearer tokens in the `Authorization` header.
MCP servers exposing HTTP transport on a public domain are a CSRF target — an attacker's web page can call destructive MCP tools through the user's browser. Permissive CORS makes it trivial. The CSA / OWASP "MCP Top 10" calls this out as a common misconfiguration; this rule closes the gap.
import express from "express"; |
import cors from "cors"; |
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
const app = express(); |
const mcp = new McpServer({ name: "my-mcp", version: "1.0.0" }); |
// Wildcard origin + credentials = CSRF amplifier. |
app.use(cors({ |
origin: "*", |
credentials: true, |
})); |
// Equally bad: reflecting Origin header. |
app.use(cors({ |
origin: (req) => req.headers.origin, |
credentials: true, |
})); |
import express from "express"; |
import cors from "cors"; |
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
const app = express(); |
const mcp = new McpServer({ name: "my-mcp", version: "1.0.0" }); |
// Explicit allowlist + credentials = safe. |
app.use(cors({ |
origin: ["https://app.example.com", "https://admin.example.com"], |
credentials: true, |
})); |
Per-occurrence in MCP-server-context files. Fires when CORS configuration sets BOTH (1) wildcard origin (`origin: "*"`) or reflecting origin (`origin: req.headers.origin`, `origin: true` in `cors()` — which mirrors the request) AND (2) credentials enabled (`credentials: true` / `allow_credentials=True` / `Access-Control-Allow-Credentials: true` header) in the same configuration object or call. Frameworks supported: Express `cors({...})` middleware, FastAPI `add_middleware(CORSMiddleware, ...)`, Flask-CORS `CORS(app, ...)`, manual header sets (`res.setHeader` / `response.headers[...]`).
See the full threat catalog for every documented detection.
MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.
Scan now