flawopen.com/リファレンス/Next.js Server Actions CSRF
Next.js Server Actions の CSRF:Origin 検証と安全な設定
Next.js Server Actions は POST を使い、Origin のホストを x-forwarded-host または host と比較します。訪問者の招待状に書かれた場所が、サーバーの想定と一致するか確かめるようなものです。これはクロスサイト送信の防止に役立ちますが、認可ではありません。各アクションでユーザー認証、入力検証、権限確認が必要です。
重要な制限があります。現行ドキュメントでは Origin のないリクエストは警告付きで処理されます。リバースプロキシも比較対象のホストに影響します。この検証を防御層の一つと捉え、プロキシで信頼できるホスト値を設定してください。
- Origin
- ブラウザーが送る開始ページのオリジン。Next.js はそのホストとアプリのホストを比較します。
- Host / X-Forwarded-Host
- 比較に使われるホスト値。プロキシは転送情報を設定または検証します。
- allowedOrigins
- Server Actions が受け入れる追加 Origin ホストの明示リスト。正確なホストとワイルドカードが使えます。
- Authorization
- 認証済みユーザーが特定オブジェクトに対してこの操作を実行できるかを判定します。
Server Actions の組み込み CSRF 検証の流れ
ブラウザーが Server Action を送信
Server Action は HTTP POST で呼び出されます。SameSite cookie は多くのクロスサイト送信を既定で防ぎますが、POST だけで完全な CSRF 防御にはなりません。
Next.js がホストを比較
Origin がある場合、Next.js はそのホストを x-forwarded-host または host と比較します。一致せず、serverActions.allowedOrigins にも含まれなければ拒否されます。
アクションは独自のポリシーを適用
リクエスト検証後も、アクションはユーザーを認証し、各引数を検証し、操作を認可します。アクション ID や非表示フォーム項目はアクセス制御ではありません。
重要な制約:Origin 欠落と allowedOrigins
現行ドキュメントでは、Origin のないリクエストは警告付きで続行します。すべてのリクエストが比較済みだと考えず、欠落の理由を調べ、アクション内で認証、認可、入力検証を行ってください。
allowedOrigins は正確なホストとワイルドカードを受け付けます。* はラベル一つ、** は一つ以上に一致します。組織が管理し、必要とするドメインとサブドメインだけを許可してください。ユーザー管理のサブドメインまで含むと、管理外の Origin を信頼することになります。
リバースプロキシもセキュリティ境界として設定
Next.js は比較に x-forwarded-host または host を使います。エッジプロキシはクライアント由来の転送ヘッダーを破棄し、検証済みの公開ホスト名で値を設定します。アプリには信頼するプロキシ経由だけでアクセスできるようにします。プロキシが内部ホスト名を転送する場合は、必要な公開 Origin だけを allowedOrigins に設定します。任意のホストを信頼して不一致を解消しないでください。
// Every subdomain, including delegated or tenant-controlled names, is trusted.
module.exports = {
experimental: {
serverActions: {
allowedOrigins: ['**.example.com'],
},
},
};
// Add only the public host that this deployment requires. module.exports = { experimental: { serverActions: { allowedOrigins: ['admin.example.com'], }, }, }; // Configure the edge to overwrite X-Forwarded-Host // with the validated public hostname.
Host に関する勧告:関連するが CSRF とは別のリスク
Host への信頼は Server Actions で SSRF の原因になった事例があります。CVE-2024-34351 は、Host を変更でき、アクションが / で始まる相対リダイレクトを行う条件下で、14.1.1 より前のセルフホスト版に影響しました。別の2026年7月の Vercel 勧告は、カスタムサーバーでクライアントがホスト関連ヘッダーを制御できる場合の SSRF と内部値の漏えいを説明し、修正版として 15.5.21 と 16.2.11 を挙げています。これはホスト信頼の欠陥であり、Origin による CSRF 検証の回避を示すものではありません。
2026年の勧告に対しては修正版へ更新してください。それまでの間、エッジまたはプロキシで Host と X-Forwarded-Host を固定または検証します。勧告では 14.2.0 以降の追加策として __NEXT_PRIVATE_ORIGIN も説明されています。適用前に勧告で対象・サポート中のリリース系列を確認してください。
すべての Server Action を認可・検証
Next.js の文書は、アクション引数を信頼できない値として扱い、現在のユーザーが呼び出せるか確認するよう求めています。危険な例は呼び出し元が渡したオブジェクト ID を信頼します。修正版は認証と ID 検証を行い、データベース更新自体に所有者条件を含めます。
"use server";
export async function deleteInvoice(invoiceId: string) {
await db.invoice.delete({ where: { id: invoiceId } });
}
"use server";
import { z } from "zod";
import { requireUser } from "@/auth";
const invoiceIdSchema = z.string().uuid();
export async function deleteInvoice(rawId: unknown) {
const user = await requireUser();
const invoiceId = invoiceIdSchema.parse(rawId);
const result = await db.invoice.deleteMany({
where: { id: invoiceId, ownerId: user.id },
});
if (result.count !== 1) throw new Error("Forbidden");
}
Server Actions の CSRF と認可チェックリスト
- ✓プロキシで不明な公開ホストを拒否し、クライアントが送った
Host/X-Forwarded-Hostを検証済み値で上書きします。 - ✓プロキシや複数オリジン構成で必要な場合を除き
allowedOriginsは空にし、管理下のホストのみを最も狭いパターンで許可します。 - ✓各 Server Action でユーザー認証、実行時の引数検証、対象オブジェクトまたは操作の認可を行います。
- ✓
Origin欠落は調査対象のログ異常として扱います。フレームワークの警告は認可判定ではありません。 - ✓カスタム Route Handler は別途監査します。Server Actions の Origin 検証を継承しないため、cookie 認証の更新処理には適切な CSRF 防御を実装してテストしてください。
- ✓Next.js のセキュリティ勧告を追跡し、影響を受ける構成、特にクライアント由来のホストヘッダーを受け入れるカスタムサーバーを更新します。