CORSの設定ミス:ワイルドカードと反射の落とし穴
Cross-Origin Resource Sharing(CORS)は、あなたのAPIからの応答をどの他のWebサイトが読めるかを制御します。ワイルドカードや反射型のオリジンポリシーは、任意のサイトに認証付きのリクエストを行わせ、その結果を読ませてしまう可能性があります。
これは何か
ブラウザは既定でクロスオリジンの読み取りをブロックします。CORSヘッダーはそれを選択的に緩めるものです。Access-Control-Allow-Origin: * は、応答をすべてのWebサイトに開放します。
より分かりにくいのがオリジンの反射です。サーバーがリクエストの Origin をそのまま allow-origin ヘッダーに返すもので、特定しているように見えて、実質的には全員を信頼してしまいます。
なぜ重要か
あなたのAPIがユーザーデータを提供し、認証情報を許可している場合、広すぎるCORSポリシーは、悪意あるサイトにログイン中の被害者のデータをあなたのAPIから直接読み取らせてしまいます。
反射と Access-Control-Allow-Credentials: true の組み合わせは特に危険です——通常はユーザーデータを守っている same-origin の保護を打ち破ってしまいます。
直し方
リクエストの Origin を、信頼できるドメインの固定リストに照らして検証し、そのうえでのみ返してください。
const ALLOWED = new Set(["https://app.yourdomain.com"]);
const origin = req.headers.get("origin") ?? "";
const allow = ALLOWED.has(origin) ? origin : "";
// only set the header when allow is non-emptyブラウザは Access-Control-Allow-Origin: * と認証情報の併用を禁じているため、アプリは代わりにオリジンを反射してしまうことがあります——これが脆弱性です。代わりに厳格な許可リストを使ってください。
クロスオリジンアクセスが不要なエンドポイントには、CORSヘッダーを一切送らないでください。本当に必要な特定のルートだけを開放しましょう。
FAQ
Access-Control-Allow-Origin: * は常に悪いのですか?
本当に公開されている、認証情報を伴わないリソース(例:公開フォントやオープンデータAPI)には問題ありません。危険なのは、ユーザーセッションに紐づくものすべてです。
CORSはサーバーを守ってくれますか?
いいえ。CORSはサーバーではなくブラウザが強制します。制御するのは、他サイトのJavaScriptが何を読めるかであって、リクエストがあなたに届くかどうかではありません。